From 3f90f52d457a89361ef5a430ed5371ab484ab938 Mon Sep 17 00:00:00 2001 From: yangyanjun Date: Mon, 6 Feb 2023 15:53:57 +0800 Subject: [PATCH 1/3] =?UTF-8?q?nip=E8=99=9A=E6=8B=9F=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yangyanjun --- src/linux/drivers/net/bt/Makefile | 1 + src/linux/drivers/net/bt/btdev.c | 1226 +++++++++++++++++++++++++ src/linux/drivers/net/bt/btdev.h | 243 +++++ src/linux/drivers/net/bt/btdev_user.h | 46 + 4 files changed, 1516 insertions(+) create mode 100644 src/linux/drivers/net/bt/Makefile create mode 100644 src/linux/drivers/net/bt/btdev.c create mode 100644 src/linux/drivers/net/bt/btdev.h create mode 100644 src/linux/drivers/net/bt/btdev_user.h diff --git a/src/linux/drivers/net/bt/Makefile b/src/linux/drivers/net/bt/Makefile new file mode 100644 index 0000000..00a6e8b --- /dev/null +++ b/src/linux/drivers/net/bt/Makefile @@ -0,0 +1 @@ +obj-y += btdev.o diff --git a/src/linux/drivers/net/bt/btdev.c b/src/linux/drivers/net/bt/btdev.c new file mode 100644 index 0000000..e994354 --- /dev/null +++ b/src/linux/drivers/net/bt/btdev.c @@ -0,0 +1,1226 @@ +/** + * NewIP kernel module + * + * Forward packets between the userspace bluetooth + * and NewIP protocol stack + */ + +#include "btdev.h" + + +static bt_drv_t *bt_drv; + +static int bt_seq_show(struct seq_file *m, void *v) +{ + bt_virnet_t *vnet = NULL; + pr_devel("bt_seq_show\n"); + seq_printf(m, "Total device: %d (bitmap: 0x%X) Ring size: %d\n", + bt_get_total_device(bt_drv), bt_drv->bitmap, + BT_RING_BUFFER_SIZE); + + list_for_each_entry(vnet, &bt_drv->devices_table->head, virnet_entry) { + seq_printf(m, "dev: %12s, interface: %5s, state: %12s, MTU: %4d," + " ring head: %4d, ring tail: %4d, packets num: %4d\n", + bt_virnet_get_cdev_name(vnet), bt_virnet_get_ndev_name(vnet), + bt_virnet_get_state_rep(vnet), vnet->ndev->mtu, + vnet->tx_ring->head, vnet->tx_ring->tail, + bt_virnet_get_ring_packets(vnet)); + } + + return 0; +} + +static int bt_proc_open(struct inode *inode, struct file *file) +{ + pr_devel("bt_proc_open\n"); + return single_open(file, bt_seq_show, PDE_DATA(inode)); +} + +static struct proc_ops bt_proc_fops = { + .proc_open = bt_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release +}; + +static int bt_io_file_open(struct inode *node, struct file *filp) +{ + bt_virnet_t *vnet = NULL; + int ret = 0; + pr_devel("bt io file open called...\n"); + + list_for_each_entry(vnet, &(bt_drv->devices_table)->head, virnet_entry) { + + if (bt_virnet_get_cdev(vnet) == node->i_cdev) { + + if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { + if (unlikely(!atomic_dec_and_test( + &vnet->io_file->read_open_limit))) { + atomic_inc(&vnet->io_file->read_open_limit); + pr_err("file %s has been opened for read twice already\n", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + } + } else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { + if (unlikely(!atomic_dec_and_test( + &vnet->io_file->write_open_limit))) { + atomic_inc(&vnet->io_file->write_open_limit); + pr_err("file %s has been opened for write twice already\n", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + } + } else if ((filp->f_flags & O_ACCMODE) == O_RDWR) { + if (unlikely(!atomic_dec_and_test( + &vnet->io_file->read_open_limit))) { + atomic_inc(&vnet->io_file->read_open_limit); + pr_err("file %s has been opened for read twice already\n", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + } + + if (unlikely(!atomic_dec_and_test( + &vnet->io_file->write_open_limit))) { + atomic_inc(&vnet->io_file->write_open_limit); + pr_err("file %s has been opened for write twice already\n", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + } + } + + rtnl_lock(); + if (unlikely(!(vnet->ndev->flags & IFF_UP))) { + ret = dev_change_flags(vnet->ndev, vnet->ndev->flags | IFF_UP, NULL); + if (unlikely(ret < 0)) { + rtnl_unlock(); + pr_err("bt_io_file_open: dev_change_flags error: ret=%d\n", ret); + return -EBUSY; + } + } + rtnl_unlock(); + + SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); + filp->private_data = vnet; + return 0; + } + } + + return -EFAULT; +} + +static int bt_io_file_release(struct inode *node, struct file *filp) +{ + bt_virnet_t *vnet = filp->private_data; + pr_devel("bt io file release called...\n"); + + if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { + atomic_inc(&vnet->io_file->read_open_limit); + } else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { + atomic_inc(&vnet->io_file->write_open_limit); + } else if ((filp->f_flags & O_ACCMODE) == O_RDWR) { + atomic_inc(&vnet->io_file->read_open_limit); + atomic_inc(&vnet->io_file->write_open_limit); + } + + SET_STATE(vnet, BT_VIRNET_STATE_DISCONNECTED); + + return 0; +} + +static ssize_t bt_io_file_read(struct file *filp, + char __user *buffer, + size_t size, loff_t *off) +{ + bt_virnet_t *vnet = filp->private_data; + ssize_t out_sz; + struct sk_buff *skb = NULL; + + pr_devel("bt io file read called...\n"); + + while (unlikely(bt_ring_is_empty(vnet->tx_ring))) { + if (filp->f_flags & O_NONBLOCK) { + return -EAGAIN; + } + if (wait_event_interruptible(vnet->rx_queue, + !bt_ring_is_empty(vnet->tx_ring))) { + return -ERESTARTSYS; + } + } + + skb = bt_ring_current(vnet->tx_ring); + out_sz = skb->len - 2 * ETH_ALEN; + if (unlikely(out_sz > size)) { + pr_err("io file read: buffer too small: skb's len=%ld buffer's len=%ld\n", + (long)out_sz, (long)size); + return -EINVAL; + } + + bt_ring_consume(vnet->tx_ring); + if (copy_to_user(buffer, skb->data + 2 * ETH_ALEN, out_sz)) { + pr_err("io file read: copy_to_user failed\n"); + return -EFAULT; + } + + dev_kfree_skb(skb); + skb = NULL; + + if (unlikely(netif_queue_stopped(vnet->ndev))) { + pr_info("consume data: wake the queue\n"); + netif_wake_queue(vnet->ndev); + } + + return out_sz; +} + +static ssize_t bt_io_file_write(struct file *filp, + const char __user *buffer, + size_t size, loff_t *off) +{ + bt_virnet_t *vnet = filp->private_data; + struct sk_buff *skb = NULL; + int ret; + int len; + ssize_t in_sz; + + pr_devel("bt io file write called...\n"); + + pr_info("bt io file write called: %lu bytes\n", size); + + in_sz = size + 2 * ETH_ALEN; + + skb = netdev_alloc_skb(bt_virnet_get_ndev(vnet), in_sz + 2); + if (unlikely(!skb)) { + return -ENOMEM; + } + + skb_reserve(skb, 2); + skb_put(skb, in_sz); + + memset(skb->data, 0, 2 * ETH_ALEN); + if (copy_from_user(skb->data + 2 * ETH_ALEN, buffer, size)) { + return -EFAULT; + } + + len = skb->len; + skb->dev = bt_virnet_get_ndev(vnet); + skb->protocol = eth_type_trans(skb, bt_virnet_get_ndev(vnet)); + ret = netif_rx_ni(skb); + + if (ret == NET_RX_SUCCESS) { + vnet->ndev->stats.rx_packets++; + vnet->ndev->stats.rx_bytes += len; + } else { + vnet->ndev->stats.rx_errors++; + vnet->ndev->stats.rx_dropped++; + } + + return size; +} + +static int bt_virnet_change_mtu(struct net_device *dev, int mtu) +{ + pr_devel("bt virnet change mtu called...\n"); + dev->mtu = mtu; + return 0; +} + +static int bt_set_mtu(struct net_device *dev, int mtu) +{ + int err = 0; + pr_info("bt_set_mtu called...\n"); + rtnl_lock(); + if ((err = dev_set_mtu(dev, mtu)) < 0) { + pr_err("bt_set_mtu failed to changed MTU to %d, err:%d", mtu, err); + } + rtnl_unlock(); + + return err; +} + +static int bt_cmd_enable_virnet(bt_virnet_t *vnet, unsigned long arg) +{ + int ret; + + BUG_ON(!vnet); + + if (unlikely(vnet->state != BT_VIRNET_STATE_DISABLED)) { + pr_err("bt cmd enable virnet: enable can only be set at DISABLED \ + state\n"); + return -1; // enable failed + } + + rtnl_lock(); + ret = dev_change_flags(vnet->ndev, vnet->ndev->flags | IFF_UP, NULL); + if (unlikely(ret < 0)) { + rtnl_unlock(); + pr_err("bt cmd enable virnet: dev_change_flags error: ret=%d\n", ret); + return -2; + } + rtnl_unlock(); + + SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); + return 0; +} + +static int bt_cmd_disable_virnet(bt_virnet_t *vnet, unsigned long arg) +{ + int ret; + BUG_ON(!vnet); + if (unlikely(vnet->state != BT_VIRNET_STATE_CONNECTED)) { + pr_err("bt_cmd_disable_virnet: disable can only be set at CONNECTED \ + state\n"); + return -1; + } + + rtnl_lock(); + ret = dev_change_flags(vnet->ndev, vnet->ndev->flags & ~IFF_UP, NULL); + if (unlikely(ret < 0)) { + rtnl_unlock(); + pr_err("bt cmd disable virnet: dev_change_flags error: ret=%d\n", ret); + return -2; + } + rtnl_unlock(); + + SET_STATE(vnet, BT_VIRNET_STATE_DISABLED); + bt_ring_clear(vnet->tx_ring); + return 0; +} + +static int bt_cmd_change_mtu(bt_virnet_t *vnet, unsigned long arg) +{ + int mtu; + int ret; + + BUG_ON(!vnet); + + if (unlikely(get_user(mtu, (int __user *)arg))) { + pr_err("get_user failed!!\n"); + return -1; + } + + ret = bt_set_mtu(vnet->ndev, mtu); + + if (unlikely(ret < 0)) { + pr_err("bt_dev_ioctl: changed mtu failed\n"); + return -1; + } + return 0; +} + +static int bt_cmd_peek_packet(bt_virnet_t *vnet, unsigned long arg) +{ + struct sk_buff *skb = NULL; + + pr_devel("bt peek packet called...\n"); + + if (unlikely(bt_ring_is_empty(vnet->tx_ring))) { + pr_err("bt peek packet ring is empty...\n"); + return -EAGAIN; + } + + skb = bt_ring_current(vnet->tx_ring); + if (unlikely(put_user(skb->len - 2 * ETH_ALEN, (int __user *)arg))) { + pr_err("put_user failed!!\n"); + return -1; + } + + return 0; +} + +static long bt_io_file_ioctl(struct file *filep, + unsigned int cmd, + unsigned long arg) +{ + long ret; + + bt_virnet_t *vnet = filep->private_data; + + pr_devel("bt io file ioctl called...\n"); + switch (cmd) { + case BT_IOC_CHANGE_MTU: + { + ret = bt_cmd_change_mtu(vnet, arg); + break; + } + case BT_IOC_ENABLE: + { + ret = bt_cmd_enable_virnet(vnet, arg); + break; + } + case BT_IOC_DISABLE: + { + ret = bt_cmd_disable_virnet(vnet, arg); + break; + } + case BT_IOC_PEEK_PACKET: + { + ret = bt_cmd_peek_packet(vnet, arg); + break; + } + default: + { + pr_err("not a valid cmd\n"); + return -1; + } + } + + return ret; +} + +static unsigned int bt_io_file_poll(struct file *filp, poll_table *wait) +{ + bt_virnet_t *vnet = filp->private_data; + unsigned int mask = 0; + + poll_wait(filp, &vnet->rx_queue, wait); + poll_wait(filp, &vnet->tx_queue, wait); + + if (!bt_ring_is_empty(vnet->tx_ring)) // readable + mask |= POLLIN | POLLRDNORM; + + if (!bt_ring_is_full(vnet->tx_ring)) // writable + mask |= POLLOUT | POLLWRNORM; + + return mask; +} + +static struct file_operations bt_io_file_ops = { + .owner = THIS_MODULE, + .open = bt_io_file_open, + .release = bt_io_file_release, + .read = bt_io_file_read, + .write = bt_io_file_write, + .poll = bt_io_file_poll, + .unlocked_ioctl = bt_io_file_ioctl, + .compat_ioctl = bt_io_file_ioctl +}; + +static int bt_mng_file_open(struct inode *node, struct file *filp) +{ + pr_devel("bt mng file open called...\n"); + + if (unlikely(!atomic_dec_and_test(&bt_drv->mng_file->open_limit))) { + atomic_inc(&bt_drv->mng_file->open_limit); + pr_err("file %s has been opened already\n", + bt_drv->mng_file->bt_cdev->dev_filename); + return -EBUSY; + } + filp->private_data = bt_drv; + return 0; +} + +static int bt_mng_file_release(struct inode *node, struct file *filp) +{ + bt_drv_t *bt_drv = filp->private_data; + + pr_devel("bt mng file release called...\n"); + + atomic_inc(&bt_drv->mng_file->open_limit); + return 0; +} + +static int bt_cmd_create_virnet(bt_drv_t *bt_mng, unsigned long arg) +{ + int id; + int ret; + bt_virnet_t *vnet = NULL; + struct bt_uioc_args vp; + unsigned long size; + + BUG_ON(!bt_mng); + + mutex_lock(&bt_mng->bitmap_lock); + id = bt_get_unused_id(&bt_mng->bitmap); + pr_info("create io_file: get unused bit: %d\n", id); + + if (unlikely(bt_mng->devices_table->num == BT_VIRNET_MAX_NUM)) { + pr_err("reach the limit of max virnets\n"); + mutex_unlock(&bt_mng->bitmap_lock); + return -1; + } + vnet = bt_virnet_create(bt_mng, id); + if (unlikely(!vnet)) { + pr_err("bt virnet create failed\n"); + mutex_unlock(&bt_mng->bitmap_lock); + return -1; + } + + vnet->bt_table_head = bt_mng->devices_table; + ret = bt_table_add_device(bt_mng->devices_table, vnet); + if (unlikely(ret < 0)) { + pr_err("bt table add device failed: ret=%d", ret); + bt_virnet_destroy(vnet); + mutex_unlock(&bt_mng->bitmap_lock); + return -1; // failed to create + } + + bt_set_bit(&bt_mng->bitmap, id); + mutex_unlock(&bt_mng->bitmap_lock); + + memcpy(vp.ifa_name, bt_virnet_get_ndev_name(vnet), + sizeof(vp.ifa_name)); + memcpy(vp.cfile_name, bt_virnet_get_cdev_name(vnet), + sizeof(vp.cfile_name)); + + mdelay(100); + + size = copy_to_user((void __user *)arg, &vp, sizeof(struct bt_uioc_args)); + if (unlikely(size)) { + pr_err("copy_to_user failed: left size=%lu", size); + return -1; + } + return 0; +} + +static int bt_cmd_delete_virnet(bt_drv_t *bt_mng, unsigned long arg) +{ + int id; + bt_virnet_t *vnet = NULL; + struct bt_uioc_args vp; + unsigned long size; + + BUG_ON(!bt_mng); + + size = copy_from_user(&vp, (void __user *)arg, + sizeof(struct bt_uioc_args)); + if (unlikely(size)) { + pr_err("copy_from_user failed: left size=%lu", size); + return -1; + } + + vnet = bt_table_find(bt_mng->devices_table, vp.ifa_name); + if (unlikely(!vnet)) { + pr_err("virnet: %s cannot be found in bt table", vp.ifa_name); + return -2; // not found + } + + mutex_lock(&bt_mng->bitmap_lock); + id = MINOR(bt_virnet_get_cdev_number(vnet)); + bt_table_remove_device(bt_mng->devices_table, vnet); + bt_virnet_destroy(vnet); + bt_clear_bit(&bt_mng->bitmap, id); + mutex_unlock(&bt_mng->bitmap_lock); + return 0; +} + +static int bt_cmd_query_all_virnets(bt_drv_t *bt_mng, unsigned long arg) +{ + BUG_ON(!bt_mng); + if (unlikely(put_user(bt_mng->bitmap, (uint32_t *)arg))) { + pr_err("put_user failed!!\n"); + return -1; + } + return 0; +} + +static int bt_cmd_delete_all_virnets(bt_drv_t *bt_mng, unsigned long arg) +{ + BUG_ON(!bt_mng); + bt_table_delete_all(bt_mng); + return 0; +} + +static long bt_mng_file_ioctl(struct file *filep, + unsigned int cmd, + unsigned long arg) +{ + int ret; + + bt_drv_t *bt_mng = filep->private_data; + + pr_devel("bt mng file ioctl called...\n"); + switch (cmd) { + case BT_IOC_CREATE: + { + ret = bt_cmd_create_virnet(bt_mng, arg); + break; + } + + case BT_IOC_DELETE: + { + ret = bt_cmd_delete_virnet(bt_mng, arg); + break; + } + + case BT_IOC_QUERY_ALL: + { + ret = bt_cmd_query_all_virnets(bt_mng, arg); + break; + } + + case BT_IOC_DELETE_ALL: + { + ret = bt_cmd_delete_all_virnets(bt_mng, arg); + break; + } + + default: + { + pr_err("not a valid command\n"); + return -1; + } + } + return ret; +} + +static struct file_operations bt_mng_file_ops = { + .owner = THIS_MODULE, + .open = bt_mng_file_open, + .release = bt_mng_file_release, + .unlocked_ioctl = bt_mng_file_ioctl, + .compat_ioctl = bt_mng_file_ioctl +}; + +static netdev_tx_t bt_virnet_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + int ret; + bt_virnet_t *vnet = NULL; + int len = skb->len; + + pr_alert("alert: bt_virnet_xmit: called...\n"); + + vnet = bt_table_find(bt_drv->devices_table, dev->name); + BUG_ON(!vnet); + + ret = bt_virnet_produce_data(vnet, (void *)skb); + + if (unlikely(ret < 0)) { + pr_info("virnet xmit: produce data failed: ring is full\n" + "need to stop queue\n"); + netif_stop_queue(vnet->ndev); + return NETDEV_TX_BUSY; + } + + vnet->ndev->stats.tx_packets++; + vnet->ndev->stats.tx_bytes += len; + + return NETDEV_TX_OK; +} + +static const struct net_device_ops bt_virnet_ops = { + .ndo_start_xmit = bt_virnet_xmit, + .ndo_change_mtu = bt_virnet_change_mtu +}; + +static bt_table_t *bt_table_init(void) +{ + bt_table_t *tbl = kmalloc(sizeof(bt_table_t), GFP_KERNEL); + if (unlikely(!tbl)) { + pr_err("alloc bt_table_t failed: oom"); + return NULL; + } + + INIT_LIST_HEAD(&tbl->head); + mutex_init(&tbl->tbl_lock); + tbl->num = 0; + return tbl; +} + +static int bt_table_add_device(bt_table_t *tbl, bt_virnet_t *vn) +{ + bt_virnet_t *vnet = NULL; + BUG_ON(!tbl); + BUG_ON(!vn); + + vnet = bt_table_find(tbl, bt_virnet_get_ndev_name(vn)); + if (unlikely(vnet)) { + pr_err("found duplicated device"); + return -1; // duplicated + } + + mutex_lock(&tbl->tbl_lock); + list_add_tail(&vn->virnet_entry, &tbl->head); + ++tbl->num; + mutex_unlock(&tbl->tbl_lock); + + return 0; +} + +static void bt_table_remove_device(bt_table_t *tbl, bt_virnet_t *vn) +{ + BUG_ON(!tbl); + BUG_ON(!vn); + mutex_lock(&tbl->tbl_lock); + list_del(&vn->virnet_entry); + --tbl->num; + mutex_unlock(&tbl->tbl_lock); +} + +static bt_virnet_t *bt_table_find(bt_table_t *tbl, const char *ifa_name) +{ + bt_virnet_t *vnet = NULL; + + BUG_ON(!tbl); + + if (unlikely(!ifa_name)) { + return NULL; + } + + list_for_each_entry(vnet, &tbl->head, virnet_entry) { + if (!strcmp(bt_virnet_get_ndev_name(vnet), ifa_name)) { + return vnet; + } + } + return NULL; +} + +static void __bt_table_delete_all(bt_drv_t *drv) +{ + uint32_t id; + bt_virnet_t *vnet = NULL, *tmp_vnet = NULL; + BUG_ON(!drv); + list_for_each_entry_safe(vnet, + tmp_vnet, + &drv->devices_table->head, + virnet_entry) { + id = MINOR(bt_virnet_get_cdev_number(vnet)); + list_del(&vnet->virnet_entry); + bt_clear_bit(&drv->bitmap, id); + bt_virnet_destroy(vnet); + } + drv->devices_table->num = 0; +} + +static void bt_table_delete_all(bt_drv_t *bt_drv) +{ + BUG_ON(!bt_drv); + mutex_lock(&bt_drv->bitmap_lock); + mutex_lock(&bt_drv->devices_table->tbl_lock); + + __bt_table_delete_all(bt_drv); + + mutex_unlock(&bt_drv->devices_table->tbl_lock); + mutex_unlock(&bt_drv->bitmap_lock); +} + +static void bt_table_destroy(bt_drv_t *bt_drv) +{ + BUG_ON(!bt_drv); + __bt_table_delete_all(bt_drv); + kfree(bt_drv->devices_table); + bt_drv->devices_table = NULL; +} + +static bt_ring_t *__bt_ring_create(int size) +{ + bt_ring_t *ring = kmalloc(sizeof(bt_ring_t), GFP_KERNEL); + if (unlikely(!ring)) { + pr_err("ring create alloc failed: oom\n"); + return NULL; + } + + if (unlikely(size < 0)) { + return NULL; + } + + ring->head = 0; + ring->tail = 0; + ring->data = kmalloc(size * sizeof(void *), GFP_KERNEL); + if (unlikely(!ring->data)) { + pr_err("ring create alloc data failed: oom\n"); + kfree(ring); + return NULL; + } + ring->size = size; + + return ring; +} + +static bt_ring_t *bt_ring_create() +{ + return __bt_ring_create(BT_RING_BUFFER_SIZE); +} + +static int bt_ring_is_empty(const bt_ring_t *ring) +{ + BUG_ON(!ring); + return ring->head == ring->tail; +} + +static int bt_ring_is_full(const bt_ring_t *ring) +{ + BUG_ON(!ring); + return (ring->head + 1) % ring->size == ring->tail; +} + +static void bt_ring_produce(bt_ring_t *ring, void *data) +{ + BUG_ON(!ring); + BUG_ON(!data); + + smp_mb(); + ring->data[ring->head] = data; + ring->head = (ring->head + 1) % ring->size; + smp_wmb(); +} + +static void *bt_ring_current(bt_ring_t *ring) +{ + void *data = NULL; + + BUG_ON(!ring); + data = ring->data[ring->tail]; + return data; +} + +static void bt_ring_consume(bt_ring_t *ring) +{ + BUG_ON(!ring); + + smp_rmb(); + ring->tail = (ring->tail + 1) % ring->size; + smp_mb(); +} + +static void bt_ring_clear(bt_ring_t *ring) +{ + BUG_ON(!ring); + ring->head = 0; + ring->tail = 0; +} + +static void bt_ring_destroy(bt_ring_t *ring) +{ + BUG_ON(!ring); + kfree(ring->data); + kfree(ring); + ring = NULL; +} + +static int bt_virnet_produce_data(bt_virnet_t *dev, void *data) +{ + BUG_ON(!dev); + BUG_ON(!data); + if (unlikely(bt_ring_is_full(dev->tx_ring))) { + pr_info("ring is full"); + return -1; + } + + smp_wmb(); + bt_ring_produce(dev->tx_ring, data); + smp_wmb(); + + wake_up(&dev->rx_queue); + return 0; +} + +/** + * register all the region + */ +static int bt_cdev_region_init(int major, int count) +{ + return register_chrdev_region(MKDEV(major, 0), count, "bt"); +} + +static struct class *bt_dev_class_create(void) +{ + struct class *cls = class_create(THIS_MODULE, "bt"); + if (unlikely(IS_ERR(cls))) { + pr_err("create struct class failed"); + return NULL; + } + return cls; +} + +static void bt_dev_class_destroy(struct class *cls) +{ + BUG_ON(!cls); + class_destroy(cls); +} + +static int bt_cdev_device_create(struct bt_cdev *dev, + struct class *cls, + uint32_t id) +{ + struct device *device = NULL; + dev_t devno = MKDEV(BT_DEV_MAJOR, id); + + BUG_ON(!dev); + BUG_ON(!cls); + + pr_devel("bt_cdev_device_create: id=%d\n", id); + + dev->bt_class = cls; + + device = device_create(cls, NULL, devno, NULL, "%s%u", BT_DEV_NAME_PREFIX, id); + if (unlikely(IS_ERR(device))) { + pr_err("create device failed"); + return -1; + } + snprintf(dev->dev_filename, sizeof(dev->dev_filename), "%s%u",BT_DEV_PATH_PREFIX, id); + return 0; +} + +static void bt_cdev_device_destroy(struct bt_cdev *dev) +{ + BUG_ON(!dev); + device_destroy(dev->bt_class, dev->cdev->dev); +} + +static struct bt_cdev *bt_cdev_create(struct file_operations *ops, + uint32_t id) +{ + int ret; + int minor = id; + struct bt_cdev *dev = NULL; + struct cdev *chrdev = NULL; + + BUG_ON(!ops); + + pr_devel("bt cdev create called...\n"); + + dev = kmalloc(sizeof(struct bt_cdev), GFP_KERNEL); + if (unlikely(!dev)) { + pr_err("bt_cdev_create alloc failed: oom\n"); + goto err1; + } + + chrdev = cdev_alloc(); + if (unlikely(!chrdev)) { + pr_err("bt_cdev_create: cdev_alloc() failed: oom\n"); + goto err2; + } + + cdev_init(chrdev, ops); + dev->cdev = chrdev; + + ret = cdev_add(chrdev, MKDEV(BT_DEV_MAJOR, minor), 1); + if (unlikely(ret < 0)) { + pr_err("cdev_add failed\n"); + goto err3; + } + + if (unlikely(bt_cdev_device_create(dev, bt_drv->bt_class, minor) < 0)) { + pr_err("bt_cdev_device_create failed\n"); + goto err3; + } + return dev; + +err3: + cdev_del(chrdev); + +err2: + kfree(dev); + +err1: + return NULL; +} + +/** + * delete one char device + */ +static void bt_cdev_delete(bt_cdev_t *bt_cdev) +{ + dev_t devno; + BUG_ON(!bt_cdev); + if (unlikely(!bt_cdev)) { + pr_err("bt_cdev_delete: cdev is null"); + return; + } else { + devno = bt_cdev->cdev->dev; + + unregister_chrdev(MAJOR(devno), bt_cdev->dev_filename + 5); + bt_cdev_device_destroy(bt_cdev); + + cdev_del(bt_cdev->cdev); + bt_cdev = NULL; + } +} + +/** + * create and add data char device + */ +static bt_io_file_t *bt_create_io_file(uint32_t id) +{ + bt_io_file_t *file = kmalloc(sizeof(bt_io_file_t), GFP_KERNEL); + if (unlikely(!file)) { + pr_err("bt_create_io_file alloc failed: oom\n"); + return NULL; + } + file->bt_cdev = bt_cdev_create(&bt_io_file_ops, id); + if (unlikely(!file->bt_cdev)) { + pr_err("bt_create_io_file: create cdev failed\n"); + kfree(file); + return NULL; + } + atomic_set(&file->read_open_limit, 1); + atomic_set(&file->write_open_limit, 1); + return file; +} + +static bt_io_file_t **bt_create_io_files(void) +{ + int i = 0; + bt_io_file_t **all_files = kmalloc(BT_VIRNET_MAX_NUM * sizeof(bt_io_file_t *), GFP_KERNEL); + if (unlikely(!all_files)) { + pr_err("bt_create_io_files alloc failed: oom\n"); + return NULL; + } + for (i=0; ibt_cdev); + kfree(file); + file = NULL; +} + +static void bt_delete_io_files(bt_drv_t *bt_mng) +{ + int i; + for (i=0; iio_files[i]); + } + kfree(bt_mng->io_files); + bt_mng->io_files = NULL; +} + +/** + * create and add management char device + */ +static bt_mng_file_t *bt_create_mng_file(int id) +{ + bt_mng_file_t *file = kmalloc(sizeof(bt_mng_file_t), GFP_KERNEL); + if (unlikely(!file)) { + pr_err("bt_create_mng_file: oom\n"); + return NULL; + } + + file->bt_cdev = bt_cdev_create(&bt_mng_file_ops, id); + if (unlikely(!file->bt_cdev)) { + pr_err("bt_create_mng_file: create cdev failed\n"); + kfree(file); + return NULL; + } + + atomic_set(&file->open_limit, 1); + + return file; +} + +static void bt_delete_mng_file(bt_mng_file_t *file) +{ + if (unlikely(!file)) { + return; + } + bt_cdev_delete(file->bt_cdev); + kfree(file); + file = NULL; +} + +/** + * unregister the region + */ +static void bt_cdev_region_destroy(int major, int count) +{ + return unregister_chrdev_region(MKDEV(major, 0), count); +} + +/** + * create one net device + */ +static struct net_device *bt_net_device_create(uint32_t id) +{ + struct net_device *ndev = NULL; + int err; + char ifa_name[IFNAMSIZ]; + + snprintf(ifa_name, sizeof(ifa_name), "%s%d", BT_VIRNET_NAME_PREFIX, id); + ndev = alloc_netdev(0, ifa_name, NET_NAME_UNKNOWN, ether_setup); + if (unlikely(!ndev)) { + pr_err("alloc_netdev failed\n"); + return NULL; + } + + ndev->netdev_ops = &bt_virnet_ops; + ndev->flags |= IFF_NOARP; + ndev->flags &= ~IFF_BROADCAST & ~IFF_MULTICAST; + ndev->min_mtu = 1; + ndev->max_mtu = ETH_MAX_MTU; + + err = register_netdev(ndev); + if (unlikely(err)) { + pr_err("create net_device failed"); + free_netdev(ndev); + return NULL; + } + + return ndev; +} + +/** + * destroy one net device + */ +static void bt_net_device_destroy(struct net_device *dev) +{ + BUG_ON(!dev); + unregister_netdev(dev); + kfree(dev); + dev = NULL; +} + + +static bt_io_file_t *bt_get_io_file(bt_drv_t *drv, int id) +{ + BUG_ON(id < 1); + BUG_ON(id > BT_VIRNET_MAX_NUM); + return drv->io_files[id-1]; +} + +/** + * create an virtual net_device + */ +static bt_virnet_t *bt_virnet_create(bt_drv_t *bt_mng, uint32_t id) +{ + bt_virnet_t *vnet = kmalloc(sizeof(bt_virnet_t), GFP_KERNEL); + if (unlikely(!vnet)) { + pr_err("error: bt_virnet init failed\n"); + goto failure1; + } + + vnet->tx_ring = bt_ring_create(); + if (unlikely(!vnet->tx_ring)) { + pr_err("create ring failed"); + goto failure2; + } + + vnet->ndev = bt_net_device_create(id); + if (unlikely(!vnet->ndev)) { + pr_err("create net device failed"); + goto failure3; + } + + vnet->io_file = bt_get_io_file(bt_mng, id); + if (unlikely(!vnet->io_file)) { + pr_err("create cdev failed"); + goto failure4; + } + + init_waitqueue_head(&vnet->rx_queue); + init_waitqueue_head(&vnet->tx_queue); + + SET_STATE(vnet, BT_VIRNET_STATE_CREATED); + return vnet; + +failure4: + bt_net_device_destroy(vnet->ndev); + +failure3: + bt_ring_destroy(vnet->tx_ring); + +failure2: + kfree(vnet); + +failure1: + return NULL; +} + +static void bt_virnet_destroy(bt_virnet_t *vnet) +{ + BUG_ON(!vnet); + bt_ring_destroy(vnet->tx_ring); + bt_net_device_destroy(vnet->ndev); + + SET_STATE(vnet, BT_VIRNET_STATE_DELETED); + + kfree(vnet); + vnet = NULL; +} + +static void bt_module_release(void) +{ + bt_table_destroy(bt_drv); + bt_delete_io_files(bt_drv); + bt_delete_mng_file(bt_drv->mng_file); + bt_dev_class_destroy(bt_drv->bt_class); + bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); + + kfree(bt_drv); + bt_drv = NULL; + remove_proc_entry("bt_info_proc", NULL); +} + +/** + * module init function + */ +static int __init bt_module_init(void) +{ + int mid; + struct proc_dir_entry *entry = NULL; + + pr_devel("bt module_init called...\n"); + bt_drv = kmalloc(sizeof(bt_drv_t), GFP_KERNEL); + if (unlikely(!bt_drv)) { + pr_err("module init: alloc bt_drv_t failed: oom"); + goto failure1; + } + + if (unlikely(bt_cdev_region_init(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM) < 0)) { + pr_err("bt_cdev_region_init: failed"); + goto failure2; + } + + bt_drv->devices_table = bt_table_init(); + if (unlikely(!bt_drv->devices_table)) { + pr_err("bt_table_init(): failed"); + goto failure2; + } + + bt_drv->bt_class = bt_dev_class_create(); + if (unlikely(IS_ERR(bt_drv->bt_class))) { + pr_err("class create failed"); + goto failure3; + } + + bt_drv->io_files = bt_create_io_files(); + + mutex_init(&bt_drv->bitmap_lock); + bt_drv->bitmap = 0; + + mutex_lock(&bt_drv->bitmap_lock); + mid = bt_get_unused_id(&bt_drv->bitmap); + pr_info("create mng_file: get unused bit: %d\n", mid); + + bt_drv->mng_file = bt_create_mng_file(mid); + if (unlikely(!bt_drv->mng_file)) { + pr_err("bt_ctrl_cdev_init(): failed"); + mutex_unlock(&bt_drv->bitmap_lock); + goto failure4; + } + bt_set_bit(&bt_drv->bitmap, mid); + mutex_unlock(&bt_drv->bitmap_lock); + + entry = proc_create_data("bt_info_proc", 0, NULL, &bt_proc_fops, NULL); + if (unlikely(!entry)) { + pr_err("create proc data failed"); + goto failure5; + } + + return 0; + +failure5: + bt_delete_mng_file(bt_drv->mng_file); + +failure4: + bt_dev_class_destroy(bt_drv->bt_class); + +failure3: + bt_table_destroy(bt_drv); + +failure2: + kfree(bt_drv); + +failure1: + return -1; +} + +module_init(bt_module_init); +module_exit(bt_module_release); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/src/linux/drivers/net/bt/btdev.h b/src/linux/drivers/net/bt/btdev.h new file mode 100644 index 0000000..e65f036 --- /dev/null +++ b/src/linux/drivers/net/bt/btdev.h @@ -0,0 +1,243 @@ +#ifndef _BTDEV_H_ +#define _BTDEV_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* must include btdev_user.h first before any macro definition */ +#include "btdev_user.h" + +#define BT_DEV_MAJOR 125 +#define BT_DEV_MINOR 0 +#define BT_RING_BUFFER_SIZE 4096 +#define STRTOLL_BASE 10 +#define BT_DEV_ID_OFFSET (sizeof(BT_DEV_PATH_PREFIX) - 1) +#define BT_STATISTIC_KTIME_MAX ULONG_MAX + +/* + * for debug + */ +#define DEBUG + +/** + * ring buffer + */ +typedef struct bt_ring { + u32 head; + u32 tail; + u32 size; + void **data; +} bt_ring_t; + +/** + * one char device + */ +typedef struct bt_cdev { + struct cdev *cdev; + struct class *bt_class; + char dev_filename[BT_PATHNAME_MAX]; +} bt_cdev_t; + +typedef struct bt_mng_file { + bt_cdev_t *bt_cdev; + atomic_t open_limit; +} bt_mng_file_t; + + +typedef struct bt_io_file { + bt_cdev_t *bt_cdev; + atomic_t read_open_limit; + atomic_t write_open_limit; +} bt_io_file_t; + +/** + * virnet list + */ +typedef struct bt_table { + struct list_head head; + struct mutex tbl_lock; + uint32_t num; +} bt_table_t; + +/** + * bt virnet state + */ +enum bt_virnet_state { + BT_VIRNET_STATE_CREATED, + BT_VIRNET_STATE_CONNECTED, + BT_VIRNET_STATE_DISCONNECTED, + BT_VIRNET_STATE_DISABLED, + BT_VIRNET_STATE_DELETED, + BT_VIRNET_STAET_NUM +}; + +/** + * one virnet device + */ +typedef struct bt_virnet { + bt_ring_t *tx_ring; + bt_io_file_t *io_file; + struct net_device *ndev; + struct list_head virnet_entry; + bt_table_t *bt_table_head; + enum bt_virnet_state state; + struct semaphore sem; + wait_queue_head_t rx_queue, tx_queue; +} bt_virnet_t; + +/** + * instance of the module + */ +typedef struct bt_drv { + bt_table_t *devices_table; + bt_mng_file_t *mng_file; + bt_io_file_t **io_files; + uint32_t bitmap; + struct mutex bitmap_lock; + struct class *bt_class; +} bt_drv_t; + +/** + * state to string + */ +static const char* bt_virnet_state_rep[BT_VIRNET_STAET_NUM] = { + "CREATED", + "CONNECTED", + "DISCONNECTED", + "DISABLED", + "ENABLED" +}; + +/** + * inline functions + */ +static inline int bt_get_unused_id(const uint32_t *bitmap) +{ + int i; + BUG_ON(!bitmap); + for (i=0; istate = state; +} + +static inline const struct cdev *bt_virnet_get_cdev(const bt_virnet_t *vn) +{ + BUG_ON(!vn); + return vn->io_file->bt_cdev->cdev; +} + +static inline const dev_t bt_virnet_get_cdev_number(const bt_virnet_t *vn) +{ + BUG_ON(!vn); + return vn->io_file->bt_cdev->cdev->dev; +} + +static inline const char *bt_virnet_get_cdev_name(const bt_virnet_t *vn) +{ + BUG_ON(!vn); + return vn->io_file->bt_cdev->dev_filename; +} + +static inline struct net_device *bt_virnet_get_ndev(const bt_virnet_t *vn) +{ + BUG_ON(!vn); + return vn->ndev; +} + +static inline const char *bt_virnet_get_ndev_name(const bt_virnet_t *vn) +{ + BUG_ON(!vn); + return vn->ndev->name; +} + +static inline const char *bt_virnet_get_state_rep(const bt_virnet_t *vn) +{ + BUG_ON(!vn); + return bt_virnet_state_rep[vn->state]; +} + +static inline int bt_get_total_device(const bt_drv_t *bt_drv) +{ + BUG_ON(!bt_drv); + return bt_drv->devices_table->num; +} + +static inline int bt_virnet_get_ring_packets(const bt_virnet_t *vn) +{ + int packets = 0; + BUG_ON(!vn); + packets = vn->tx_ring->head - vn->tx_ring->tail; + if (unlikely(packets < 0)) { + packets += BT_RING_BUFFER_SIZE; + } + return packets; +} + +static bt_table_t *bt_table_init(void); +static int bt_table_add_device(bt_table_t *tbl, bt_virnet_t *vn); +static void bt_table_remove_device(bt_table_t *tbl, bt_virnet_t *vn); +static void bt_table_delete_all(bt_drv_t *drv); +static bt_virnet_t *bt_table_find(bt_table_t *tbl, const char *ifa_name); +static void bt_table_destroy(bt_drv_t *drv); +static void bt_delete_io_files(bt_drv_t *drv); +static bt_io_file_t **bt_create_io_files(void); + +static bt_ring_t *bt_ring_create(void); +static int bt_ring_is_empty(const bt_ring_t *ring); +static int bt_ring_is_full(const bt_ring_t *ring); +static void *bt_ring_current(bt_ring_t *ring); +static void bt_ring_produce(bt_ring_t *ring, void *data); +static void bt_ring_consume(bt_ring_t *ring); +static void bt_ring_clear(bt_ring_t *ring); +static void bt_ring_destroy(bt_ring_t *ring); + +static int bt_virnet_produce_data(bt_virnet_t *dev, void *data); +static bt_virnet_t *bt_virnet_create(bt_drv_t *drv, uint32_t id); +static void bt_virnet_destroy(bt_virnet_t *dev); + +#endif diff --git a/src/linux/drivers/net/bt/btdev_user.h b/src/linux/drivers/net/bt/btdev_user.h new file mode 100644 index 0000000..281a388 --- /dev/null +++ b/src/linux/drivers/net/bt/btdev_user.h @@ -0,0 +1,46 @@ +#ifndef _BTDEV_USER_H_ +#define _BTDEV_USER_H_ + +#include +#include + + +#define BT_VIRNET_NAME_PREFIX "btn" +#define BT_DEV_NAME_PREFIX "btdev" +#define BT_DEV_PATH_PREFIX "/dev/"BT_DEV_NAME_PREFIX + +#define BT_DEV_PATH(idx) BT_DEV_PATH_PREFIX#idx +#define BT_DEV_NAME(idx) BT_DEV_NAME_PREFIX#idx + +#define BT_DEV_NAME_MNG_FILE BT_DEV_NAME(0) +#define BT_DEV_PATH_MNG_FILE BT_DEV_PATH(0) +#define BT_DEV_NAME_IO_FILE(idx) BT_DEV_NAME(idx) +#define BT_DEV_PATH_IO_FILE(idx) BT_DEV_PATH(idx) +#define BT_VIRNET_NAME(idx) BT_VIRNET_NAME_PREFIX#idx + +#define BT_PATHNAME_MAX 256 +#define BT_VIRNET_MAX_NUM 16 +#define BT_VIRNET_DATA_HEAD_LEN 2 + +/* + * ioctl cmd + */ +#define BT_IOC_CREATE _IO('b', 1) +#define BT_IOC_DELETE _IO('b', 2) +#define BT_IOC_CHANGE_MTU _IO('b', 3) +#define BT_IOC_QUERY_ALL _IO('b', 4) +#define BT_IOC_DELETE_ALL _IO('b', 5) +#define BT_IOC_ENABLE _IO('b', 6) +#define BT_IOC_DISABLE _IO('b', 7) +#define BT_IOC_PEEK_PACKET _IO('b', 8) + + +/** + * user space ioctl arguments + */ +struct bt_uioc_args { + char ifa_name[IFNAMSIZ]; + char cfile_name[BT_PATHNAME_MAX]; +}; + +#endif -- Gitee From 76b602810a4d01b0a1688645851c00a85f7affeb Mon Sep 17 00:00:00 2001 From: yangyanjun Date: Tue, 14 Mar 2023 10:58:02 +0800 Subject: [PATCH 2/3] =?UTF-8?q?btdev=E8=99=9A=E6=8B=9F=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E4=BB=A3=E5=90=88=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yangyanjun --- src/linux/drivers/net/bt/btdev.c | 1817 ++++++++++++------------- src/linux/drivers/net/bt/btdev.h | 269 ++-- src/linux/drivers/net/bt/btdev_user.h | 55 +- 3 files changed, 1068 insertions(+), 1073 deletions(-) diff --git a/src/linux/drivers/net/bt/btdev.c b/src/linux/drivers/net/bt/btdev.c index e994354..037709c 100644 --- a/src/linux/drivers/net/bt/btdev.c +++ b/src/linux/drivers/net/bt/btdev.c @@ -1,807 +1,792 @@ -/** - * NewIP kernel module - * - * Forward packets between the userspace bluetooth - * and NewIP protocol stack +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. */ #include "btdev.h" - -static bt_drv_t *bt_drv; +static struct bt_drv *bt_drv; static int bt_seq_show(struct seq_file *m, void *v) { - bt_virnet_t *vnet = NULL; - pr_devel("bt_seq_show\n"); - seq_printf(m, "Total device: %d (bitmap: 0x%X) Ring size: %d\n", - bt_get_total_device(bt_drv), bt_drv->bitmap, - BT_RING_BUFFER_SIZE); - - list_for_each_entry(vnet, &bt_drv->devices_table->head, virnet_entry) { - seq_printf(m, "dev: %12s, interface: %5s, state: %12s, MTU: %4d," - " ring head: %4d, ring tail: %4d, packets num: %4d\n", - bt_virnet_get_cdev_name(vnet), bt_virnet_get_ndev_name(vnet), - bt_virnet_get_state_rep(vnet), vnet->ndev->mtu, - vnet->tx_ring->head, vnet->tx_ring->tail, - bt_virnet_get_ring_packets(vnet)); - } - - return 0; + struct bt_virnet *vnet = NULL; + + pr_devel("bt seq_show\n"); + seq_printf(m, "Total device: %d (bitmap: 0x%X) Ring size: %d\n", + bt_get_total_device(bt_drv), bt_drv->bitmap, + BT_RING_BUFFER_SIZE); + + list_for_each_entry(vnet, &bt_drv->devices_table->head, virnet_entry) { + seq_printf(m, "dev: %12s, interface: %5s, state: %12s, MTU: %4d\n", + bt_virnet_get_cdev_name(vnet), bt_virnet_get_ndev_name(vnet), + bt_virnet_get_state_rep(vnet), vnet->ndev->mtu); + seq_printf(m, "ring head: %4d, ring tail: %4d, packets num: %4d\n", + vnet->tx_ring->head, vnet->tx_ring->tail, + bt_virnet_get_ring_packets(vnet)); + } + + return 0; } static int bt_proc_open(struct inode *inode, struct file *file) { - pr_devel("bt_proc_open\n"); - return single_open(file, bt_seq_show, PDE_DATA(inode)); + pr_devel("bt proc_open\n"); + return single_open(file, bt_seq_show, PDE_DATA(inode)); } static struct proc_ops bt_proc_fops = { - .proc_open = bt_proc_open, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release -}; + .proc_open = bt_proc_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release}; static int bt_io_file_open(struct inode *node, struct file *filp) { - bt_virnet_t *vnet = NULL; - int ret = 0; - pr_devel("bt io file open called...\n"); - - list_for_each_entry(vnet, &(bt_drv->devices_table)->head, virnet_entry) { - - if (bt_virnet_get_cdev(vnet) == node->i_cdev) { - - if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { - if (unlikely(!atomic_dec_and_test( - &vnet->io_file->read_open_limit))) { - atomic_inc(&vnet->io_file->read_open_limit); - pr_err("file %s has been opened for read twice already\n", - bt_virnet_get_cdev_name(vnet)); - return -EBUSY; - } - } else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { - if (unlikely(!atomic_dec_and_test( - &vnet->io_file->write_open_limit))) { - atomic_inc(&vnet->io_file->write_open_limit); - pr_err("file %s has been opened for write twice already\n", - bt_virnet_get_cdev_name(vnet)); - return -EBUSY; - } - } else if ((filp->f_flags & O_ACCMODE) == O_RDWR) { - if (unlikely(!atomic_dec_and_test( - &vnet->io_file->read_open_limit))) { - atomic_inc(&vnet->io_file->read_open_limit); - pr_err("file %s has been opened for read twice already\n", - bt_virnet_get_cdev_name(vnet)); - return -EBUSY; - } - - if (unlikely(!atomic_dec_and_test( - &vnet->io_file->write_open_limit))) { - atomic_inc(&vnet->io_file->write_open_limit); - pr_err("file %s has been opened for write twice already\n", - bt_virnet_get_cdev_name(vnet)); - return -EBUSY; - } - } - - rtnl_lock(); - if (unlikely(!(vnet->ndev->flags & IFF_UP))) { - ret = dev_change_flags(vnet->ndev, vnet->ndev->flags | IFF_UP, NULL); - if (unlikely(ret < 0)) { - rtnl_unlock(); - pr_err("bt_io_file_open: dev_change_flags error: ret=%d\n", ret); - return -EBUSY; - } - } - rtnl_unlock(); - - SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); - filp->private_data = vnet; - return 0; - } - } - - return -EFAULT; + struct bt_virnet *vnet = NULL; + int ret = 0; + + pr_devel("bt io file open called...\n"); + + list_for_each_entry(vnet, &bt_drv->devices_table->head, virnet_entry) { + if (bt_virnet_get_cdev(vnet) == node->i_cdev) { + if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->read_open_limit))) { + atomic_inc(&vnet->io_file->read_open_limit); + pr_err("file %s has been opened for read twice already\n", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + } + } else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->write_open_limit))) { + atomic_inc(&vnet->io_file->write_open_limit); + pr_err("file %s has been opened for write twice already\n", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + } + } else if ((filp->f_flags & O_ACCMODE) == O_RDWR) { + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->read_open_limit))) { + atomic_inc(&vnet->io_file->read_open_limit); + pr_err("file %s has been opened for read twice already\n", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + } + + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->write_open_limit))) { + atomic_inc(&vnet->io_file->write_open_limit); + pr_err("file %s has been opened for write twice already\n", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + } + } + + rtnl_lock(); + if (unlikely(!(vnet->ndev->flags & IFF_UP))) { + ret = dev_change_flags(vnet->ndev, vnet->ndev + ->flags | IFF_UP, NULL); + if (unlikely(ret < 0)) { + rtnl_unlock(); + pr_err("bt dev_change_flags error: ret=%d\n", ret); + return -EBUSY; + } + } + rtnl_unlock(); + + SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); + filp->private_data = vnet; + return 0; + } + } + + return -EFAULT; } static int bt_io_file_release(struct inode *node, struct file *filp) { - bt_virnet_t *vnet = filp->private_data; - pr_devel("bt io file release called...\n"); + struct bt_virnet *vnet = filp->private_data; + + pr_devel("bt io file release called...\n"); - if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { - atomic_inc(&vnet->io_file->read_open_limit); - } else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { - atomic_inc(&vnet->io_file->write_open_limit); - } else if ((filp->f_flags & O_ACCMODE) == O_RDWR) { - atomic_inc(&vnet->io_file->read_open_limit); - atomic_inc(&vnet->io_file->write_open_limit); - } + if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { + atomic_inc(&vnet->io_file->read_open_limit); + } else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { + atomic_inc(&vnet->io_file->write_open_limit); + } else if ((filp->f_flags & O_ACCMODE) == O_RDWR) { + atomic_inc(&vnet->io_file->read_open_limit); + atomic_inc(&vnet->io_file->write_open_limit); + } - SET_STATE(vnet, BT_VIRNET_STATE_DISCONNECTED); + SET_STATE(vnet, BT_VIRNET_STATE_DISCONNECTED); - return 0; + return 0; } static ssize_t bt_io_file_read(struct file *filp, - char __user *buffer, - size_t size, loff_t *off) + char __user *buffer, + size_t size, loff_t *off) { - bt_virnet_t *vnet = filp->private_data; - ssize_t out_sz; - struct sk_buff *skb = NULL; - - pr_devel("bt io file read called...\n"); - - while (unlikely(bt_ring_is_empty(vnet->tx_ring))) { - if (filp->f_flags & O_NONBLOCK) { - return -EAGAIN; - } - if (wait_event_interruptible(vnet->rx_queue, - !bt_ring_is_empty(vnet->tx_ring))) { - return -ERESTARTSYS; - } - } - - skb = bt_ring_current(vnet->tx_ring); - out_sz = skb->len - 2 * ETH_ALEN; - if (unlikely(out_sz > size)) { - pr_err("io file read: buffer too small: skb's len=%ld buffer's len=%ld\n", - (long)out_sz, (long)size); - return -EINVAL; - } - - bt_ring_consume(vnet->tx_ring); - if (copy_to_user(buffer, skb->data + 2 * ETH_ALEN, out_sz)) { - pr_err("io file read: copy_to_user failed\n"); - return -EFAULT; - } - - dev_kfree_skb(skb); - skb = NULL; - - if (unlikely(netif_queue_stopped(vnet->ndev))) { - pr_info("consume data: wake the queue\n"); - netif_wake_queue(vnet->ndev); - } - - return out_sz; + struct bt_virnet *vnet = filp->private_data; + ssize_t out_sz; + struct sk_buff *skb = NULL; + + pr_devel("bt io file read called...\n"); + + while (unlikely(bt_ring_is_empty(vnet->tx_ring))) { + if (filp->f_flags & O_NONBLOCK) + return -EAGAIN; + + if (wait_event_interruptible(vnet->rx_queue, + !bt_ring_is_empty(vnet->tx_ring))) + return -ERESTARTSYS; + } + + skb = bt_ring_current(vnet->tx_ring); + out_sz = skb->len - 2 * ETH_ALEN; + if (unlikely(out_sz > size)) { + pr_err("io file read: buffer too small: skb's len=%ld buffer's len=%ld\n", + (long)out_sz, (long)size); + return -EINVAL; + } + + bt_ring_consume(vnet->tx_ring); + if (copy_to_user(buffer, skb->data + 2 * ETH_ALEN, out_sz)) { + pr_err("io file read: copy_to_user failed\n"); + return -EFAULT; + } + + dev_kfree_skb(skb); + skb = NULL; + + if (unlikely(netif_queue_stopped(vnet->ndev))) { + pr_info("consume data: wake the queue\n"); + netif_wake_queue(vnet->ndev); + } + + return out_sz; } static ssize_t bt_io_file_write(struct file *filp, - const char __user *buffer, - size_t size, loff_t *off) + const char __user *buffer, + size_t size, loff_t *off) { - bt_virnet_t *vnet = filp->private_data; - struct sk_buff *skb = NULL; - int ret; - int len; - ssize_t in_sz; + struct bt_virnet *vnet = filp->private_data; + struct sk_buff *skb = NULL; + int ret; + int len; + ssize_t in_sz; - pr_devel("bt io file write called...\n"); + pr_devel("bt io file write called...\n"); - pr_info("bt io file write called: %lu bytes\n", size); + pr_info("bt io file write called: %lu bytes\n", size); - in_sz = size + 2 * ETH_ALEN; + in_sz = size + 2 * ETH_ALEN; - skb = netdev_alloc_skb(bt_virnet_get_ndev(vnet), in_sz + 2); - if (unlikely(!skb)) { - return -ENOMEM; - } + skb = netdev_alloc_skb(bt_virnet_get_ndev(vnet), in_sz + 2); + if (unlikely(!skb)) + return -ENOMEM; - skb_reserve(skb, 2); - skb_put(skb, in_sz); + skb_reserve(skb, 2); + skb_put(skb, in_sz); - memset(skb->data, 0, 2 * ETH_ALEN); - if (copy_from_user(skb->data + 2 * ETH_ALEN, buffer, size)) { - return -EFAULT; - } + memset(skb->data, 0, 2 * ETH_ALEN); + if (copy_from_user(skb->data + 2 * ETH_ALEN, buffer, size)) + return -EFAULT; - len = skb->len; - skb->dev = bt_virnet_get_ndev(vnet); - skb->protocol = eth_type_trans(skb, bt_virnet_get_ndev(vnet)); - ret = netif_rx_ni(skb); + len = skb->len; + skb->dev = bt_virnet_get_ndev(vnet); + skb->protocol = eth_type_trans(skb, bt_virnet_get_ndev(vnet)); + ret = netif_rx_ni(skb); - if (ret == NET_RX_SUCCESS) { - vnet->ndev->stats.rx_packets++; - vnet->ndev->stats.rx_bytes += len; - } else { - vnet->ndev->stats.rx_errors++; - vnet->ndev->stats.rx_dropped++; - } + if (ret == NET_RX_SUCCESS) { + vnet->ndev->stats.rx_packets++; + vnet->ndev->stats.rx_bytes += len; + } else { + vnet->ndev->stats.rx_errors++; + vnet->ndev->stats.rx_dropped++; + } - return size; + return size; } static int bt_virnet_change_mtu(struct net_device *dev, int mtu) { - pr_devel("bt virnet change mtu called...\n"); - dev->mtu = mtu; - return 0; + pr_devel("bt virnet change mtu called...\n"); + dev->mtu = mtu; + return 0; } static int bt_set_mtu(struct net_device *dev, int mtu) { - int err = 0; - pr_info("bt_set_mtu called...\n"); - rtnl_lock(); - if ((err = dev_set_mtu(dev, mtu)) < 0) { - pr_err("bt_set_mtu failed to changed MTU to %d, err:%d", mtu, err); - } - rtnl_unlock(); - - return err; + int err = 0; + + pr_info("bt set_mtu called...\n"); + rtnl_lock(); + err = dev_set_mtu(dev, mtu); + if (err < 0) + pr_err("bt set_mtu failed to changed MTU to %d, err:%d", mtu, err); + + rtnl_unlock(); + + return err; } -static int bt_cmd_enable_virnet(bt_virnet_t *vnet, unsigned long arg) +static int bt_cmd_enable_virnet(struct bt_virnet *vnet, unsigned long arg) { - int ret; - - BUG_ON(!vnet); - - if (unlikely(vnet->state != BT_VIRNET_STATE_DISABLED)) { - pr_err("bt cmd enable virnet: enable can only be set at DISABLED \ - state\n"); - return -1; // enable failed - } - - rtnl_lock(); - ret = dev_change_flags(vnet->ndev, vnet->ndev->flags | IFF_UP, NULL); - if (unlikely(ret < 0)) { - rtnl_unlock(); - pr_err("bt cmd enable virnet: dev_change_flags error: ret=%d\n", ret); - return -2; - } - rtnl_unlock(); - - SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); - return 0; + int ret; + + WARN_ON(!vnet); + + if (unlikely(vnet->state != BT_VIRNET_STATE_DISABLED)) { + pr_err("bt enable can only be set at DISABLED state\n"); + return -1; // enable failed + } + + rtnl_lock(); + ret = dev_change_flags(vnet->ndev, vnet->ndev->flags | IFF_UP, NULL); + if (unlikely(ret < 0)) { + rtnl_unlock(); + pr_err("bt cmd enable virnet: dev_change_flags error: ret=%d\n", ret); + return -2; + } + rtnl_unlock(); + + SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); + return 0; } -static int bt_cmd_disable_virnet(bt_virnet_t *vnet, unsigned long arg) +static int bt_cmd_disable_virnet(struct bt_virnet *vnet, unsigned long arg) { - int ret; - BUG_ON(!vnet); - if (unlikely(vnet->state != BT_VIRNET_STATE_CONNECTED)) { - pr_err("bt_cmd_disable_virnet: disable can only be set at CONNECTED \ - state\n"); - return -1; - } - - rtnl_lock(); - ret = dev_change_flags(vnet->ndev, vnet->ndev->flags & ~IFF_UP, NULL); - if (unlikely(ret < 0)) { - rtnl_unlock(); - pr_err("bt cmd disable virnet: dev_change_flags error: ret=%d\n", ret); - return -2; - } - rtnl_unlock(); - - SET_STATE(vnet, BT_VIRNET_STATE_DISABLED); - bt_ring_clear(vnet->tx_ring); - return 0; + int ret; + + WARN_ON(!vnet); + if (unlikely(vnet->state != BT_VIRNET_STATE_CONNECTED)) { + pr_err("bt disable can only be set at CONNECTED state\n"); + return -1; + } + + rtnl_lock(); + ret = dev_change_flags(vnet->ndev, vnet->ndev->flags & ~IFF_UP, NULL); + if (unlikely(ret < 0)) { + rtnl_unlock(); + pr_err("bt cmd disable virnet: dev_change_flags error: ret=%d\n", ret); + return -2; + } + rtnl_unlock(); + + SET_STATE(vnet, BT_VIRNET_STATE_DISABLED); + return 0; } -static int bt_cmd_change_mtu(bt_virnet_t *vnet, unsigned long arg) +static int bt_cmd_change_mtu(struct bt_virnet *vnet, unsigned long arg) { - int mtu; - int ret; + int mtu; + int ret; - BUG_ON(!vnet); + WARN_ON(!vnet); - if (unlikely(get_user(mtu, (int __user *)arg))) { - pr_err("get_user failed!!\n"); - return -1; - } + if (unlikely(get_user(mtu, (int __user *)arg))) { + pr_err("get_user failed!!\n"); + return -1; + } - ret = bt_set_mtu(vnet->ndev, mtu); + ret = bt_set_mtu(vnet->ndev, mtu); - if (unlikely(ret < 0)) { - pr_err("bt_dev_ioctl: changed mtu failed\n"); - return -1; - } - return 0; + if (unlikely(ret < 0)) { + pr_err("bt_dev_ioctl: changed mtu failed\n"); + return -1; + } + return 0; } -static int bt_cmd_peek_packet(bt_virnet_t *vnet, unsigned long arg) +static int bt_cmd_peek_packet(struct bt_virnet *vnet, unsigned long arg) { - struct sk_buff *skb = NULL; + struct sk_buff *skb = NULL; - pr_devel("bt peek packet called...\n"); + pr_devel("bt peek packet called...\n"); - if (unlikely(bt_ring_is_empty(vnet->tx_ring))) { - pr_err("bt peek packet ring is empty...\n"); - return -EAGAIN; - } + if (unlikely(bt_ring_is_empty(vnet->tx_ring))) { + pr_err("bt peek packet ring is empty...\n"); + return -EAGAIN; + } - skb = bt_ring_current(vnet->tx_ring); - if (unlikely(put_user(skb->len - 2 * ETH_ALEN, (int __user *)arg))) { - pr_err("put_user failed!!\n"); - return -1; - } + skb = bt_ring_current(vnet->tx_ring); + if (unlikely(put_user(skb->len - 2 * ETH_ALEN, (int __user *)arg))) { + pr_err("put_user failed!!\n"); + return -1; + } - return 0; + return 0; } static long bt_io_file_ioctl(struct file *filep, - unsigned int cmd, - unsigned long arg) + unsigned int cmd, + unsigned long arg) { - long ret; - - bt_virnet_t *vnet = filep->private_data; - - pr_devel("bt io file ioctl called...\n"); - switch (cmd) { - case BT_IOC_CHANGE_MTU: - { - ret = bt_cmd_change_mtu(vnet, arg); - break; - } - case BT_IOC_ENABLE: - { - ret = bt_cmd_enable_virnet(vnet, arg); - break; - } - case BT_IOC_DISABLE: - { - ret = bt_cmd_disable_virnet(vnet, arg); - break; - } - case BT_IOC_PEEK_PACKET: - { - ret = bt_cmd_peek_packet(vnet, arg); - break; - } - default: - { - pr_err("not a valid cmd\n"); - return -1; - } - } - - return ret; + long ret; + + struct bt_virnet *vnet = filep->private_data; + + pr_devel("bt io file ioctl called...\n"); + switch (cmd) { + case BT_IOC_CHANGE_MTU: + { + ret = bt_cmd_change_mtu(vnet, arg); + break; + } + case BT_IOC_ENABLE: + { + ret = bt_cmd_enable_virnet(vnet, arg); + break; + } + case BT_IOC_DISABLE: + { + ret = bt_cmd_disable_virnet(vnet, arg); + break; + } + case BT_IOC_PEEK_PACKET: + { + ret = bt_cmd_peek_packet(vnet, arg); + break; + } + default: + { + pr_err("not a valid cmd\n"); + return -1; + } + } + + return ret; } static unsigned int bt_io_file_poll(struct file *filp, poll_table *wait) { - bt_virnet_t *vnet = filp->private_data; - unsigned int mask = 0; + struct bt_virnet *vnet = filp->private_data; + unsigned int mask = 0; - poll_wait(filp, &vnet->rx_queue, wait); - poll_wait(filp, &vnet->tx_queue, wait); + poll_wait(filp, &vnet->rx_queue, wait); + poll_wait(filp, &vnet->tx_queue, wait); - if (!bt_ring_is_empty(vnet->tx_ring)) // readable - mask |= POLLIN | POLLRDNORM; + if (!bt_ring_is_empty(vnet->tx_ring)) // readable + mask |= POLLIN | POLLRDNORM; - if (!bt_ring_is_full(vnet->tx_ring)) // writable - mask |= POLLOUT | POLLWRNORM; + if (!bt_ring_is_full(vnet->tx_ring)) // writable + mask |= POLLOUT | POLLWRNORM; - return mask; + return mask; } -static struct file_operations bt_io_file_ops = { - .owner = THIS_MODULE, - .open = bt_io_file_open, - .release = bt_io_file_release, - .read = bt_io_file_read, - .write = bt_io_file_write, - .poll = bt_io_file_poll, - .unlocked_ioctl = bt_io_file_ioctl, - .compat_ioctl = bt_io_file_ioctl -}; +static const struct file_operations bt_io_file_ops = { + .owner = THIS_MODULE, + .open = bt_io_file_open, + .release = bt_io_file_release, + .read = bt_io_file_read, + .write = bt_io_file_write, + .poll = bt_io_file_poll, + .unlocked_ioctl = bt_io_file_ioctl, + .compat_ioctl = bt_io_file_ioctl}; static int bt_mng_file_open(struct inode *node, struct file *filp) { - pr_devel("bt mng file open called...\n"); - - if (unlikely(!atomic_dec_and_test(&bt_drv->mng_file->open_limit))) { - atomic_inc(&bt_drv->mng_file->open_limit); - pr_err("file %s has been opened already\n", - bt_drv->mng_file->bt_cdev->dev_filename); - return -EBUSY; - } - filp->private_data = bt_drv; - return 0; + pr_devel("bt mng file open called...\n"); + + if (unlikely(!atomic_dec_and_test(&bt_drv->mng_file->open_limit))) { + atomic_inc(&bt_drv->mng_file->open_limit); + pr_err("file %s has been opened already\n", + bt_drv->mng_file->bt_cdev->dev_filename); + return -EBUSY; + } + filp->private_data = bt_drv; + return 0; } static int bt_mng_file_release(struct inode *node, struct file *filp) { - bt_drv_t *bt_drv = filp->private_data; + struct bt_drv *bt_drv = filp->private_data; - pr_devel("bt mng file release called...\n"); + pr_devel("bt mng file release called...\n"); - atomic_inc(&bt_drv->mng_file->open_limit); - return 0; + atomic_inc(&bt_drv->mng_file->open_limit); + return 0; } -static int bt_cmd_create_virnet(bt_drv_t *bt_mng, unsigned long arg) +static int bt_cmd_create_virnet(struct bt_drv *bt_mng, unsigned long arg) { - int id; - int ret; - bt_virnet_t *vnet = NULL; - struct bt_uioc_args vp; - unsigned long size; - - BUG_ON(!bt_mng); - - mutex_lock(&bt_mng->bitmap_lock); - id = bt_get_unused_id(&bt_mng->bitmap); - pr_info("create io_file: get unused bit: %d\n", id); - - if (unlikely(bt_mng->devices_table->num == BT_VIRNET_MAX_NUM)) { - pr_err("reach the limit of max virnets\n"); - mutex_unlock(&bt_mng->bitmap_lock); - return -1; - } - vnet = bt_virnet_create(bt_mng, id); - if (unlikely(!vnet)) { - pr_err("bt virnet create failed\n"); - mutex_unlock(&bt_mng->bitmap_lock); - return -1; - } - - vnet->bt_table_head = bt_mng->devices_table; - ret = bt_table_add_device(bt_mng->devices_table, vnet); - if (unlikely(ret < 0)) { - pr_err("bt table add device failed: ret=%d", ret); - bt_virnet_destroy(vnet); - mutex_unlock(&bt_mng->bitmap_lock); - return -1; // failed to create - } - - bt_set_bit(&bt_mng->bitmap, id); - mutex_unlock(&bt_mng->bitmap_lock); - - memcpy(vp.ifa_name, bt_virnet_get_ndev_name(vnet), - sizeof(vp.ifa_name)); - memcpy(vp.cfile_name, bt_virnet_get_cdev_name(vnet), - sizeof(vp.cfile_name)); - - mdelay(100); - - size = copy_to_user((void __user *)arg, &vp, sizeof(struct bt_uioc_args)); - if (unlikely(size)) { - pr_err("copy_to_user failed: left size=%lu", size); - return -1; - } - return 0; + int id; + int ret; + struct bt_virnet *vnet = NULL; + struct bt_uioc_args vp; + unsigned long size; + + WARN_ON(!bt_mng); + + mutex_lock(&bt_mng->bitmap_lock); + id = bt_get_unused_id(&bt_mng->bitmap); + pr_info("create io_file: get unused bit: %d\n", id); + + if (unlikely(bt_mng->devices_table->num == BT_VIRNET_MAX_NUM)) { + pr_err("reach the limit of max virnets\n"); + mutex_unlock(&bt_mng->bitmap_lock); + return -1; + } + vnet = bt_virnet_create(bt_mng, id); + if (unlikely(!vnet)) { + pr_err("bt virnet create failed\n"); + mutex_unlock(&bt_mng->bitmap_lock); + return -1; + } + + vnet->bt_table_head = bt_mng->devices_table; + ret = bt_table_add_device(bt_mng->devices_table, vnet); + if (unlikely(ret < 0)) { + pr_err("bt table add device failed: ret=%d", ret); + bt_virnet_destroy(vnet); + mutex_unlock(&bt_mng->bitmap_lock); + return -1; // failed to create + } + + bt_set_bit(&bt_mng->bitmap, id); + mutex_unlock(&bt_mng->bitmap_lock); + + memcpy(vp.ifa_name, bt_virnet_get_ndev_name(vnet), + sizeof(vp.ifa_name)); + memcpy(vp.cfile_name, bt_virnet_get_cdev_name(vnet), + sizeof(vp.cfile_name)); + + mdelay(100); + + size = copy_to_user((void __user *)arg, &vp, sizeof(struct bt_uioc_args)); + if (unlikely(size)) { + pr_err("copy_to_user failed: left size=%lu", size); + return -1; + } + return 0; } -static int bt_cmd_delete_virnet(bt_drv_t *bt_mng, unsigned long arg) +static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) { - int id; - bt_virnet_t *vnet = NULL; - struct bt_uioc_args vp; - unsigned long size; - - BUG_ON(!bt_mng); - - size = copy_from_user(&vp, (void __user *)arg, - sizeof(struct bt_uioc_args)); - if (unlikely(size)) { - pr_err("copy_from_user failed: left size=%lu", size); - return -1; - } - - vnet = bt_table_find(bt_mng->devices_table, vp.ifa_name); - if (unlikely(!vnet)) { - pr_err("virnet: %s cannot be found in bt table", vp.ifa_name); - return -2; // not found - } - - mutex_lock(&bt_mng->bitmap_lock); - id = MINOR(bt_virnet_get_cdev_number(vnet)); - bt_table_remove_device(bt_mng->devices_table, vnet); - bt_virnet_destroy(vnet); - bt_clear_bit(&bt_mng->bitmap, id); - mutex_unlock(&bt_mng->bitmap_lock); - return 0; + int id; + struct bt_virnet *vnet = NULL; + struct bt_uioc_args vp; + unsigned long size; + + WARN_ON(!bt_mng); + + size = copy_from_user(&vp, (void __user *)arg, + sizeof(struct bt_uioc_args)); + if (unlikely(size)) { + pr_err("copy_from_user failed: left size=%lu", size); + return -1; + } + + vnet = bt_table_find(bt_mng->devices_table, vp.ifa_name); + if (unlikely(!vnet)) { + pr_err("virnet: %s cannot be found in bt table", vp.ifa_name); + return -2; // not found + } + + mutex_lock(&bt_mng->bitmap_lock); + id = MINOR(bt_virnet_get_cdev_number(vnet)); + bt_table_remove_device(bt_mng->devices_table, vnet); + bt_virnet_destroy(vnet); + bt_clear_bit(&bt_mng->bitmap, id); + mutex_unlock(&bt_mng->bitmap_lock); + return 0; } -static int bt_cmd_query_all_virnets(bt_drv_t *bt_mng, unsigned long arg) +static int bt_cmd_query_all_virnets(struct bt_drv *bt_mng, unsigned long arg) { - BUG_ON(!bt_mng); - if (unlikely(put_user(bt_mng->bitmap, (uint32_t *)arg))) { - pr_err("put_user failed!!\n"); - return -1; - } - return 0; + WARN_ON(!bt_mng); + if (unlikely(put_user(bt_mng->bitmap, (u32 *)arg))) { + pr_err("put_user failed!!\n"); + return -1; + } + return 0; } -static int bt_cmd_delete_all_virnets(bt_drv_t *bt_mng, unsigned long arg) +static int bt_cmd_delete_all_virnets(struct bt_drv *bt_mng, unsigned long arg) { - BUG_ON(!bt_mng); - bt_table_delete_all(bt_mng); - return 0; + WARN_ON(!bt_mng); + bt_table_delete_all(bt_mng); + return 0; } static long bt_mng_file_ioctl(struct file *filep, - unsigned int cmd, - unsigned long arg) + unsigned int cmd, + unsigned long arg) { - int ret; - - bt_drv_t *bt_mng = filep->private_data; - - pr_devel("bt mng file ioctl called...\n"); - switch (cmd) { - case BT_IOC_CREATE: - { - ret = bt_cmd_create_virnet(bt_mng, arg); - break; - } - - case BT_IOC_DELETE: - { - ret = bt_cmd_delete_virnet(bt_mng, arg); - break; - } - - case BT_IOC_QUERY_ALL: - { - ret = bt_cmd_query_all_virnets(bt_mng, arg); - break; - } - - case BT_IOC_DELETE_ALL: - { - ret = bt_cmd_delete_all_virnets(bt_mng, arg); - break; - } - - default: - { - pr_err("not a valid command\n"); - return -1; - } - } - return ret; + int ret; + + struct bt_drv *bt_mng = filep->private_data; + + pr_devel("bt mng file ioctl called...\n"); + switch (cmd) { + case BT_IOC_CREATE: + { + ret = bt_cmd_create_virnet(bt_mng, arg); + break; + } + + case BT_IOC_DELETE: + { + ret = bt_cmd_delete_virnet(bt_mng, arg); + break; + } + + case BT_IOC_QUERY_ALL: + { + ret = bt_cmd_query_all_virnets(bt_mng, arg); + break; + } + + case BT_IOC_DELETE_ALL: + { + ret = bt_cmd_delete_all_virnets(bt_mng, arg); + break; + } + + default: + { + pr_err("not a valid command\n"); + return -1; + } + } + return ret; } -static struct file_operations bt_mng_file_ops = { - .owner = THIS_MODULE, - .open = bt_mng_file_open, - .release = bt_mng_file_release, - .unlocked_ioctl = bt_mng_file_ioctl, - .compat_ioctl = bt_mng_file_ioctl -}; +static const struct file_operations bt_mng_file_ops = { + .owner = THIS_MODULE, + .open = bt_mng_file_open, + .release = bt_mng_file_release, + .unlocked_ioctl = bt_mng_file_ioctl, + .compat_ioctl = bt_mng_file_ioctl}; static netdev_tx_t bt_virnet_xmit(struct sk_buff *skb, - struct net_device *dev) + struct net_device *dev) { - int ret; - bt_virnet_t *vnet = NULL; - int len = skb->len; + int ret; + struct bt_virnet *vnet = NULL; + int len = skb->len; - pr_alert("alert: bt_virnet_xmit: called...\n"); + pr_alert("alert: bt virnet_xmit: called...\n"); - vnet = bt_table_find(bt_drv->devices_table, dev->name); - BUG_ON(!vnet); + vnet = bt_table_find(bt_drv->devices_table, dev->name); + WARN_ON(!vnet); - ret = bt_virnet_produce_data(vnet, (void *)skb); + ret = bt_virnet_produce_data(vnet, (void *)skb); - if (unlikely(ret < 0)) { - pr_info("virnet xmit: produce data failed: ring is full\n" - "need to stop queue\n"); - netif_stop_queue(vnet->ndev); - return NETDEV_TX_BUSY; - } + if (unlikely(ret < 0)) { + pr_info("virnet xmit: produce data failed: ring is full\n" + "need to stop queue\n"); + netif_stop_queue(vnet->ndev); + return NETDEV_TX_BUSY; + } - vnet->ndev->stats.tx_packets++; - vnet->ndev->stats.tx_bytes += len; + vnet->ndev->stats.tx_packets++; + vnet->ndev->stats.tx_bytes += len; - return NETDEV_TX_OK; + return NETDEV_TX_OK; } static const struct net_device_ops bt_virnet_ops = { - .ndo_start_xmit = bt_virnet_xmit, - .ndo_change_mtu = bt_virnet_change_mtu -}; + .ndo_start_xmit = bt_virnet_xmit, + .ndo_change_mtu = bt_virnet_change_mtu}; -static bt_table_t *bt_table_init(void) +static struct bt_table *bt_table_init(void) { - bt_table_t *tbl = kmalloc(sizeof(bt_table_t), GFP_KERNEL); - if (unlikely(!tbl)) { - pr_err("alloc bt_table_t failed: oom"); - return NULL; - } - - INIT_LIST_HEAD(&tbl->head); - mutex_init(&tbl->tbl_lock); - tbl->num = 0; - return tbl; + struct bt_table *tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); + + if (unlikely(!tbl)) { + pr_err("alloc struct bt_table failed: oom"); + return NULL; + } + + INIT_LIST_HEAD(&tbl->head); + mutex_init(&tbl->tbl_lock); + tbl->num = 0; + return tbl; } -static int bt_table_add_device(bt_table_t *tbl, bt_virnet_t *vn) +static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn) { - bt_virnet_t *vnet = NULL; - BUG_ON(!tbl); - BUG_ON(!vn); - - vnet = bt_table_find(tbl, bt_virnet_get_ndev_name(vn)); - if (unlikely(vnet)) { - pr_err("found duplicated device"); - return -1; // duplicated - } - - mutex_lock(&tbl->tbl_lock); - list_add_tail(&vn->virnet_entry, &tbl->head); - ++tbl->num; - mutex_unlock(&tbl->tbl_lock); - - return 0; + struct bt_virnet *vnet = NULL; + + WARN_ON(!tbl); + WARN_ON(!vn); + + vnet = bt_table_find(tbl, bt_virnet_get_ndev_name(vn)); + if (unlikely(vnet)) { + pr_err("found duplicated device"); + return -1; // duplicated + } + + mutex_lock(&tbl->tbl_lock); + list_add_tail(&vn->virnet_entry, &tbl->head); + ++tbl->num; + mutex_unlock(&tbl->tbl_lock); + + return 0; } -static void bt_table_remove_device(bt_table_t *tbl, bt_virnet_t *vn) +static void bt_table_remove_device(struct bt_table *tbl, struct bt_virnet *vn) { - BUG_ON(!tbl); - BUG_ON(!vn); - mutex_lock(&tbl->tbl_lock); - list_del(&vn->virnet_entry); - --tbl->num; - mutex_unlock(&tbl->tbl_lock); + WARN_ON(!tbl); + WARN_ON(!vn); + mutex_lock(&tbl->tbl_lock); + list_del(&vn->virnet_entry); + --tbl->num; + mutex_unlock(&tbl->tbl_lock); } -static bt_virnet_t *bt_table_find(bt_table_t *tbl, const char *ifa_name) +static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_name) { - bt_virnet_t *vnet = NULL; + struct bt_virnet *vnet = NULL; - BUG_ON(!tbl); + WARN_ON(!tbl); - if (unlikely(!ifa_name)) { - return NULL; - } + if (unlikely(!ifa_name)) + return NULL; - list_for_each_entry(vnet, &tbl->head, virnet_entry) { - if (!strcmp(bt_virnet_get_ndev_name(vnet), ifa_name)) { - return vnet; - } - } - return NULL; + list_for_each_entry(vnet, &tbl->head, virnet_entry) { + if (!strcmp(bt_virnet_get_ndev_name(vnet), ifa_name)) + return vnet; + } + return NULL; } -static void __bt_table_delete_all(bt_drv_t *drv) +static void __bt_table_delete_all(struct bt_drv *drv) { - uint32_t id; - bt_virnet_t *vnet = NULL, *tmp_vnet = NULL; - BUG_ON(!drv); - list_for_each_entry_safe(vnet, - tmp_vnet, - &drv->devices_table->head, - virnet_entry) { - id = MINOR(bt_virnet_get_cdev_number(vnet)); - list_del(&vnet->virnet_entry); - bt_clear_bit(&drv->bitmap, id); - bt_virnet_destroy(vnet); - } - drv->devices_table->num = 0; + u32 id; + struct bt_virnet *vnet = NULL, *tmp_vnet = NULL; + + WARN_ON(!drv); + list_for_each_entry_safe(vnet, + tmp_vnet, + &drv->devices_table->head, + virnet_entry) { + id = MINOR(bt_virnet_get_cdev_number(vnet)); + list_del(&vnet->virnet_entry); + bt_clear_bit(&drv->bitmap, id); + bt_virnet_destroy(vnet); + } + drv->devices_table->num = 0; } -static void bt_table_delete_all(bt_drv_t *bt_drv) +static void bt_table_delete_all(struct bt_drv *bt_drv) { - BUG_ON(!bt_drv); - mutex_lock(&bt_drv->bitmap_lock); - mutex_lock(&bt_drv->devices_table->tbl_lock); + WARN_ON(!bt_drv); + mutex_lock(&bt_drv->bitmap_lock); + mutex_lock(&bt_drv->devices_table->tbl_lock); - __bt_table_delete_all(bt_drv); + __bt_table_delete_all(bt_drv); - mutex_unlock(&bt_drv->devices_table->tbl_lock); - mutex_unlock(&bt_drv->bitmap_lock); + mutex_unlock(&bt_drv->devices_table->tbl_lock); + mutex_unlock(&bt_drv->bitmap_lock); } -static void bt_table_destroy(bt_drv_t *bt_drv) +static void bt_table_destroy(struct bt_drv *bt_drv) { - BUG_ON(!bt_drv); - __bt_table_delete_all(bt_drv); - kfree(bt_drv->devices_table); - bt_drv->devices_table = NULL; + WARN_ON(!bt_drv); + __bt_table_delete_all(bt_drv); + kfree(bt_drv->devices_table); + bt_drv->devices_table = NULL; } -static bt_ring_t *__bt_ring_create(int size) +static struct bt_ring *__bt_ring_create(int size) { - bt_ring_t *ring = kmalloc(sizeof(bt_ring_t), GFP_KERNEL); - if (unlikely(!ring)) { - pr_err("ring create alloc failed: oom\n"); - return NULL; - } - - if (unlikely(size < 0)) { - return NULL; - } - - ring->head = 0; - ring->tail = 0; - ring->data = kmalloc(size * sizeof(void *), GFP_KERNEL); - if (unlikely(!ring->data)) { - pr_err("ring create alloc data failed: oom\n"); - kfree(ring); - return NULL; - } - ring->size = size; - - return ring; + struct bt_ring *ring = kmalloc(sizeof(*ring), GFP_KERNEL); + + if (unlikely(!ring)) { + pr_err("ring create alloc failed: oom\n"); + return NULL; + } + + if (unlikely(size < 0)) + return NULL; + + ring->head = 0; + ring->tail = 0; + ring->data = kmalloc_array(size, sizeof(void *), GFP_KERNEL); + if (unlikely(!ring->data)) { + pr_err("ring create alloc data failed: oom\n"); + kfree(ring); + return NULL; + } + ring->size = size; + + return ring; } -static bt_ring_t *bt_ring_create() +static struct bt_ring *bt_ring_create(void) { - return __bt_ring_create(BT_RING_BUFFER_SIZE); + return __bt_ring_create(BT_RING_BUFFER_SIZE); } -static int bt_ring_is_empty(const bt_ring_t *ring) +static int bt_ring_is_empty(const struct bt_ring *ring) { - BUG_ON(!ring); - return ring->head == ring->tail; + WARN_ON(!ring); + return ring->head == ring->tail; } -static int bt_ring_is_full(const bt_ring_t *ring) +static int bt_ring_is_full(const struct bt_ring *ring) { - BUG_ON(!ring); - return (ring->head + 1) % ring->size == ring->tail; + WARN_ON(!ring); + return (ring->head + 1) % ring->size == ring->tail; } -static void bt_ring_produce(bt_ring_t *ring, void *data) +static void bt_ring_produce(struct bt_ring *ring, void *data) { - BUG_ON(!ring); - BUG_ON(!data); + WARN_ON(!ring); + WARN_ON(!data); - smp_mb(); - ring->data[ring->head] = data; - ring->head = (ring->head + 1) % ring->size; - smp_wmb(); + smp_mb(); // Make sure the read and write order is correct + ring->data[ring->head] = data; + ring->head = (ring->head + 1) % ring->size; + smp_wmb(); // Make sure the write order is correct } -static void *bt_ring_current(bt_ring_t *ring) +static void *bt_ring_current(struct bt_ring *ring) { - void *data = NULL; + void *data = NULL; - BUG_ON(!ring); - data = ring->data[ring->tail]; - return data; + WARN_ON(!ring); + data = ring->data[ring->tail]; + return data; } -static void bt_ring_consume(bt_ring_t *ring) +static void bt_ring_consume(struct bt_ring *ring) { - BUG_ON(!ring); - - smp_rmb(); - ring->tail = (ring->tail + 1) % ring->size; - smp_mb(); -} + WARN_ON(!ring); -static void bt_ring_clear(bt_ring_t *ring) -{ - BUG_ON(!ring); - ring->head = 0; - ring->tail = 0; + smp_rmb(); // Make sure the read order is correct + ring->tail = (ring->tail + 1) % ring->size; + smp_mb(); // Make sure the read and write order is correct } -static void bt_ring_destroy(bt_ring_t *ring) +static void bt_ring_destroy(struct bt_ring *ring) { - BUG_ON(!ring); - kfree(ring->data); - kfree(ring); - ring = NULL; + WARN_ON(!ring); + kfree(ring->data); + kfree(ring); } -static int bt_virnet_produce_data(bt_virnet_t *dev, void *data) +static int bt_virnet_produce_data(struct bt_virnet *dev, void *data) { - BUG_ON(!dev); - BUG_ON(!data); - if (unlikely(bt_ring_is_full(dev->tx_ring))) { - pr_info("ring is full"); - return -1; - } - - smp_wmb(); - bt_ring_produce(dev->tx_ring, data); - smp_wmb(); - - wake_up(&dev->rx_queue); - return 0; + WARN_ON(!dev); + WARN_ON(!data); + if (unlikely(bt_ring_is_full(dev->tx_ring))) { + pr_info("ring is full"); + return -1; + } + + smp_wmb(); // Make sure the write order is correct + bt_ring_produce(dev->tx_ring, data); + smp_wmb(); // Make sure twrite order is correct + + wake_up(&dev->rx_queue); + return 0; } /** @@ -809,210 +794,214 @@ static int bt_virnet_produce_data(bt_virnet_t *dev, void *data) */ static int bt_cdev_region_init(int major, int count) { - return register_chrdev_region(MKDEV(major, 0), count, "bt"); + return register_chrdev_region(MKDEV(major, 0), count, "bt"); } static struct class *bt_dev_class_create(void) { - struct class *cls = class_create(THIS_MODULE, "bt"); - if (unlikely(IS_ERR(cls))) { - pr_err("create struct class failed"); - return NULL; - } - return cls; + struct class *cls = class_create(THIS_MODULE, "bt"); + + if (IS_ERR(cls)) { + pr_err("create struct class failed"); + return NULL; + } + return cls; } static void bt_dev_class_destroy(struct class *cls) { - BUG_ON(!cls); - class_destroy(cls); + WARN_ON(!cls); + class_destroy(cls); } static int bt_cdev_device_create(struct bt_cdev *dev, - struct class *cls, - uint32_t id) + struct class *cls, + u32 id) { - struct device *device = NULL; - dev_t devno = MKDEV(BT_DEV_MAJOR, id); + struct device *device = NULL; + dev_t devno = MKDEV(BT_DEV_MAJOR, id); - BUG_ON(!dev); - BUG_ON(!cls); + WARN_ON(!dev); + WARN_ON(!cls); - pr_devel("bt_cdev_device_create: id=%d\n", id); + pr_devel("bt cdev_device_create: id=%d\n", id); - dev->bt_class = cls; + dev->bt_class = cls; - device = device_create(cls, NULL, devno, NULL, "%s%u", BT_DEV_NAME_PREFIX, id); - if (unlikely(IS_ERR(device))) { - pr_err("create device failed"); - return -1; - } - snprintf(dev->dev_filename, sizeof(dev->dev_filename), "%s%u",BT_DEV_PATH_PREFIX, id); - return 0; + device = device_create(cls, NULL, devno, NULL, "%s%u", BT_DEV_NAME_PREFIX, id); + if (IS_ERR(device)) { + pr_err("create device failed"); + return -1; + } + snprintf(dev->dev_filename, sizeof(dev->dev_filename), "%s%u", BT_DEV_PATH_PREFIX, id); + return 0; } static void bt_cdev_device_destroy(struct bt_cdev *dev) { - BUG_ON(!dev); - device_destroy(dev->bt_class, dev->cdev->dev); + WARN_ON(!dev); + device_destroy(dev->bt_class, dev->cdev->dev); } -static struct bt_cdev *bt_cdev_create(struct file_operations *ops, - uint32_t id) +static struct bt_cdev *bt_cdev_create(const struct file_operations *ops, + u32 id) { - int ret; - int minor = id; - struct bt_cdev *dev = NULL; - struct cdev *chrdev = NULL; - - BUG_ON(!ops); - - pr_devel("bt cdev create called...\n"); - - dev = kmalloc(sizeof(struct bt_cdev), GFP_KERNEL); - if (unlikely(!dev)) { - pr_err("bt_cdev_create alloc failed: oom\n"); - goto err1; - } - - chrdev = cdev_alloc(); - if (unlikely(!chrdev)) { - pr_err("bt_cdev_create: cdev_alloc() failed: oom\n"); - goto err2; - } - - cdev_init(chrdev, ops); - dev->cdev = chrdev; - - ret = cdev_add(chrdev, MKDEV(BT_DEV_MAJOR, minor), 1); - if (unlikely(ret < 0)) { - pr_err("cdev_add failed\n"); - goto err3; - } - - if (unlikely(bt_cdev_device_create(dev, bt_drv->bt_class, minor) < 0)) { - pr_err("bt_cdev_device_create failed\n"); - goto err3; - } - return dev; + int ret; + int minor = id; + struct bt_cdev *dev = NULL; + struct cdev *chrdev = NULL; + + WARN_ON(!ops); + + pr_devel("bt cdev create called...\n"); + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (unlikely(!dev)) { + pr_err("bt cdev_create alloc failed: oom\n"); + goto err1; + } + + chrdev = cdev_alloc(); + if (unlikely(!chrdev)) { + pr_err("bt cdev_create: cdev_alloc() failed: oom\n"); + goto err2; + } + + cdev_init(chrdev, ops); + dev->cdev = chrdev; + + ret = cdev_add(chrdev, MKDEV(BT_DEV_MAJOR, minor), 1); + if (unlikely(ret < 0)) { + pr_err("cdev add failed\n"); + goto err3; + } + + if (unlikely(bt_cdev_device_create(dev, bt_drv->bt_class, minor) < 0)) { + pr_err("bt cdev_device_create failed\n"); + goto err3; + } + return dev; err3: - cdev_del(chrdev); + cdev_del(chrdev); err2: - kfree(dev); + kfree(dev); err1: - return NULL; + return NULL; } /** * delete one char device */ -static void bt_cdev_delete(bt_cdev_t *bt_cdev) +static void bt_cdev_delete(struct bt_cdev *bt_cdev) { - dev_t devno; - BUG_ON(!bt_cdev); - if (unlikely(!bt_cdev)) { - pr_err("bt_cdev_delete: cdev is null"); - return; - } else { - devno = bt_cdev->cdev->dev; - - unregister_chrdev(MAJOR(devno), bt_cdev->dev_filename + 5); - bt_cdev_device_destroy(bt_cdev); - - cdev_del(bt_cdev->cdev); - bt_cdev = NULL; - } + dev_t devno; + + WARN_ON(!bt_cdev); + if (unlikely(bt_cdev)) { + devno = bt_cdev->cdev->dev; + + unregister_chrdev(MAJOR(devno), bt_cdev->dev_filename + 5); + bt_cdev_device_destroy(bt_cdev); + + cdev_del(bt_cdev->cdev); + } else { + pr_err("bt cdev_delete: cdev is null"); + return; + } } /** * create and add data char device */ -static bt_io_file_t *bt_create_io_file(uint32_t id) +static struct bt_io_file *bt_create_io_file(u32 id) { - bt_io_file_t *file = kmalloc(sizeof(bt_io_file_t), GFP_KERNEL); - if (unlikely(!file)) { - pr_err("bt_create_io_file alloc failed: oom\n"); - return NULL; - } - file->bt_cdev = bt_cdev_create(&bt_io_file_ops, id); - if (unlikely(!file->bt_cdev)) { - pr_err("bt_create_io_file: create cdev failed\n"); - kfree(file); - return NULL; - } - atomic_set(&file->read_open_limit, 1); - atomic_set(&file->write_open_limit, 1); - return file; + struct bt_io_file *file = kmalloc(sizeof(*file), GFP_KERNEL); + + if (unlikely(!file)) { + pr_err("bt create_io_file alloc failed: oom\n"); + return NULL; + } + file->bt_cdev = bt_cdev_create(&bt_io_file_ops, id); + if (unlikely(!file->bt_cdev)) { + pr_err("bt create_io_file: create cdev failed\n"); + kfree(file); + return NULL; + } + atomic_set(&file->read_open_limit, 1); + atomic_set(&file->write_open_limit, 1); + return file; } -static bt_io_file_t **bt_create_io_files(void) +static struct bt_io_file **bt_create_io_files(void) { - int i = 0; - bt_io_file_t **all_files = kmalloc(BT_VIRNET_MAX_NUM * sizeof(bt_io_file_t *), GFP_KERNEL); - if (unlikely(!all_files)) { - pr_err("bt_create_io_files alloc failed: oom\n"); - return NULL; - } - for (i=0; ibt_cdev); - kfree(file); - file = NULL; + if (unlikely(!file)) + return; + + bt_cdev_delete(file->bt_cdev); + kfree(file); } -static void bt_delete_io_files(bt_drv_t *bt_mng) +static void bt_delete_io_files(struct bt_drv *bt_mng) { - int i; - for (i=0; iio_files[i]); - } - kfree(bt_mng->io_files); - bt_mng->io_files = NULL; + int i; + + for (i = 0; i < BT_VIRNET_MAX_NUM; ++i) + bt_delete_io_file(bt_mng->io_files[i]); + + kfree(bt_mng->io_files); + bt_mng->io_files = NULL; } /** * create and add management char device */ -static bt_mng_file_t *bt_create_mng_file(int id) +static struct bt_mng_file *bt_create_mng_file(int id) { - bt_mng_file_t *file = kmalloc(sizeof(bt_mng_file_t), GFP_KERNEL); - if (unlikely(!file)) { - pr_err("bt_create_mng_file: oom\n"); - return NULL; - } - - file->bt_cdev = bt_cdev_create(&bt_mng_file_ops, id); - if (unlikely(!file->bt_cdev)) { - pr_err("bt_create_mng_file: create cdev failed\n"); - kfree(file); - return NULL; - } - - atomic_set(&file->open_limit, 1); - - return file; + struct bt_mng_file *file = kmalloc(sizeof(*file), GFP_KERNEL); + + if (unlikely(!file)) { + pr_err("bt create_mng_file: oom\n"); + return NULL; + } + + file->bt_cdev = bt_cdev_create(&bt_mng_file_ops, id); + if (unlikely(!file->bt_cdev)) { + pr_err("bt create_mng_file: create cdev failed\n"); + kfree(file); + return NULL; + } + + atomic_set(&file->open_limit, 1); + + return file; } -static void bt_delete_mng_file(bt_mng_file_t *file) +static void bt_delete_mng_file(struct bt_mng_file *file) { - if (unlikely(!file)) { - return; - } - bt_cdev_delete(file->bt_cdev); - kfree(file); - file = NULL; + if (unlikely(!file)) + return; + + bt_cdev_delete(file->bt_cdev); + kfree(file); } /** @@ -1020,39 +1009,39 @@ static void bt_delete_mng_file(bt_mng_file_t *file) */ static void bt_cdev_region_destroy(int major, int count) { - return unregister_chrdev_region(MKDEV(major, 0), count); + return unregister_chrdev_region(MKDEV(major, 0), count); } /** * create one net device */ -static struct net_device *bt_net_device_create(uint32_t id) +static struct net_device *bt_net_device_create(u32 id) { - struct net_device *ndev = NULL; - int err; - char ifa_name[IFNAMSIZ]; - - snprintf(ifa_name, sizeof(ifa_name), "%s%d", BT_VIRNET_NAME_PREFIX, id); - ndev = alloc_netdev(0, ifa_name, NET_NAME_UNKNOWN, ether_setup); - if (unlikely(!ndev)) { - pr_err("alloc_netdev failed\n"); - return NULL; - } - - ndev->netdev_ops = &bt_virnet_ops; - ndev->flags |= IFF_NOARP; - ndev->flags &= ~IFF_BROADCAST & ~IFF_MULTICAST; - ndev->min_mtu = 1; - ndev->max_mtu = ETH_MAX_MTU; - - err = register_netdev(ndev); - if (unlikely(err)) { - pr_err("create net_device failed"); - free_netdev(ndev); - return NULL; - } - - return ndev; + struct net_device *ndev = NULL; + int err; + char ifa_name[IFNAMSIZ]; + + snprintf(ifa_name, sizeof(ifa_name), "%s%d", BT_VIRNET_NAME_PREFIX, id); + ndev = alloc_netdev(0, ifa_name, NET_NAME_UNKNOWN, ether_setup); + if (unlikely(!ndev)) { + pr_err("alloc_netdev failed\n"); + return NULL; + } + + ndev->netdev_ops = &bt_virnet_ops; + ndev->flags |= IFF_NOARP; + ndev->flags &= ~IFF_BROADCAST & ~IFF_MULTICAST; + ndev->min_mtu = 1; + ndev->max_mtu = ETH_MAX_MTU; + + err = register_netdev(ndev); + if (unlikely(err)) { + pr_err("create net_device failed"); + free_netdev(ndev); + return NULL; + } + + return ndev; } /** @@ -1060,91 +1049,89 @@ static struct net_device *bt_net_device_create(uint32_t id) */ static void bt_net_device_destroy(struct net_device *dev) { - BUG_ON(!dev); - unregister_netdev(dev); - kfree(dev); - dev = NULL; + WARN_ON(!dev); + unregister_netdev(dev); + free_netdev(dev); } - -static bt_io_file_t *bt_get_io_file(bt_drv_t *drv, int id) +static struct bt_io_file *bt_get_io_file(struct bt_drv *drv, int id) { - BUG_ON(id < 1); - BUG_ON(id > BT_VIRNET_MAX_NUM); - return drv->io_files[id-1]; + WARN_ON(id < 1); + WARN_ON(id > BT_VIRNET_MAX_NUM); + return drv->io_files[id - 1]; } /** * create an virtual net_device */ -static bt_virnet_t *bt_virnet_create(bt_drv_t *bt_mng, uint32_t id) +static struct bt_virnet *bt_virnet_create(struct bt_drv *bt_mng, u32 id) { - bt_virnet_t *vnet = kmalloc(sizeof(bt_virnet_t), GFP_KERNEL); - if (unlikely(!vnet)) { - pr_err("error: bt_virnet init failed\n"); - goto failure1; - } - - vnet->tx_ring = bt_ring_create(); - if (unlikely(!vnet->tx_ring)) { - pr_err("create ring failed"); - goto failure2; - } - - vnet->ndev = bt_net_device_create(id); - if (unlikely(!vnet->ndev)) { - pr_err("create net device failed"); - goto failure3; - } - - vnet->io_file = bt_get_io_file(bt_mng, id); - if (unlikely(!vnet->io_file)) { - pr_err("create cdev failed"); - goto failure4; - } - - init_waitqueue_head(&vnet->rx_queue); - init_waitqueue_head(&vnet->tx_queue); - - SET_STATE(vnet, BT_VIRNET_STATE_CREATED); - return vnet; + struct bt_virnet *vnet = kmalloc(sizeof(*vnet), GFP_KERNEL); + + if (unlikely(!vnet)) { + pr_err("error: bt_virnet init failed\n"); + goto failure1; + } + + vnet->tx_ring = bt_ring_create(); + if (unlikely(!vnet->tx_ring)) { + pr_err("create ring failed"); + goto failure2; + } + + vnet->ndev = bt_net_device_create(id); + if (unlikely(!vnet->ndev)) { + pr_err("create net device failed"); + goto failure3; + } + + vnet->io_file = bt_get_io_file(bt_mng, id); + if (unlikely(!vnet->io_file)) { + pr_err("create cdev failed"); + goto failure4; + } + + init_waitqueue_head(&vnet->rx_queue); + init_waitqueue_head(&vnet->tx_queue); + + SET_STATE(vnet, BT_VIRNET_STATE_CREATED); + return vnet; failure4: - bt_net_device_destroy(vnet->ndev); + bt_net_device_destroy(vnet->ndev); failure3: - bt_ring_destroy(vnet->tx_ring); + bt_ring_destroy(vnet->tx_ring); failure2: - kfree(vnet); + kfree(vnet); failure1: - return NULL; + return NULL; } -static void bt_virnet_destroy(bt_virnet_t *vnet) +static void bt_virnet_destroy(struct bt_virnet *vnet) { - BUG_ON(!vnet); - bt_ring_destroy(vnet->tx_ring); - bt_net_device_destroy(vnet->ndev); + WARN_ON(!vnet); + bt_ring_destroy(vnet->tx_ring); + bt_net_device_destroy(vnet->ndev); - SET_STATE(vnet, BT_VIRNET_STATE_DELETED); + SET_STATE(vnet, BT_VIRNET_STATE_DELETED); - kfree(vnet); - vnet = NULL; + kfree(vnet); } static void bt_module_release(void) { - bt_table_destroy(bt_drv); - bt_delete_io_files(bt_drv); - bt_delete_mng_file(bt_drv->mng_file); - bt_dev_class_destroy(bt_drv->bt_class); - bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); - - kfree(bt_drv); - bt_drv = NULL; - remove_proc_entry("bt_info_proc", NULL); + bt_table_destroy(bt_drv); + bt_delete_io_files(bt_drv); + bt_delete_mng_file(bt_drv->mng_file); + bt_dev_class_destroy(bt_drv->bt_class); + bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); + + kfree(bt_drv); + bt_drv = NULL; + remove_proc_entry("bt_info_proc", NULL); } /** @@ -1152,73 +1139,73 @@ static void bt_module_release(void) */ static int __init bt_module_init(void) { - int mid; - struct proc_dir_entry *entry = NULL; - - pr_devel("bt module_init called...\n"); - bt_drv = kmalloc(sizeof(bt_drv_t), GFP_KERNEL); - if (unlikely(!bt_drv)) { - pr_err("module init: alloc bt_drv_t failed: oom"); - goto failure1; - } - - if (unlikely(bt_cdev_region_init(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM) < 0)) { - pr_err("bt_cdev_region_init: failed"); - goto failure2; - } - - bt_drv->devices_table = bt_table_init(); - if (unlikely(!bt_drv->devices_table)) { - pr_err("bt_table_init(): failed"); - goto failure2; - } - - bt_drv->bt_class = bt_dev_class_create(); - if (unlikely(IS_ERR(bt_drv->bt_class))) { - pr_err("class create failed"); - goto failure3; - } - - bt_drv->io_files = bt_create_io_files(); - - mutex_init(&bt_drv->bitmap_lock); - bt_drv->bitmap = 0; - - mutex_lock(&bt_drv->bitmap_lock); - mid = bt_get_unused_id(&bt_drv->bitmap); - pr_info("create mng_file: get unused bit: %d\n", mid); - - bt_drv->mng_file = bt_create_mng_file(mid); - if (unlikely(!bt_drv->mng_file)) { - pr_err("bt_ctrl_cdev_init(): failed"); - mutex_unlock(&bt_drv->bitmap_lock); - goto failure4; - } - bt_set_bit(&bt_drv->bitmap, mid); - mutex_unlock(&bt_drv->bitmap_lock); - - entry = proc_create_data("bt_info_proc", 0, NULL, &bt_proc_fops, NULL); - if (unlikely(!entry)) { - pr_err("create proc data failed"); - goto failure5; - } - - return 0; + int mid; + struct proc_dir_entry *entry = NULL; + + pr_devel("bt module_init called...\n"); + bt_drv = kmalloc(sizeof(*bt_drv), GFP_KERNEL); + if (unlikely(!bt_drv)) { + pr_err("module init: alloc struct bt_drv failed: oom"); + goto failure1; + } + + if (unlikely(bt_cdev_region_init(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM) < 0)) { + pr_err("bt_cdev_region_init: failed"); + goto failure2; + } + + bt_drv->devices_table = bt_table_init(); + if (unlikely(!bt_drv->devices_table)) { + pr_err("bt_table_init(): failed"); + goto failure2; + } + + bt_drv->bt_class = bt_dev_class_create(); + if (IS_ERR(bt_drv->bt_class)) { + pr_err("class create failed"); + goto failure3; + } + + bt_drv->io_files = bt_create_io_files(); + + mutex_init(&bt_drv->bitmap_lock); + bt_drv->bitmap = 0; + + mutex_lock(&bt_drv->bitmap_lock); + mid = bt_get_unused_id(&bt_drv->bitmap); + pr_info("create mng_file: get unused bit: %d\n", mid); + + bt_drv->mng_file = bt_create_mng_file(mid); + if (unlikely(!bt_drv->mng_file)) { + pr_err("bt_ctrl_cdev_init(): failed"); + mutex_unlock(&bt_drv->bitmap_lock); + goto failure4; + } + bt_set_bit(&bt_drv->bitmap, mid); + mutex_unlock(&bt_drv->bitmap_lock); + + entry = proc_create_data("bt_info_proc", 0, NULL, &bt_proc_fops, NULL); + if (unlikely(!entry)) { + pr_err("create proc data failed"); + goto failure5; + } + + return 0; failure5: - bt_delete_mng_file(bt_drv->mng_file); + bt_delete_mng_file(bt_drv->mng_file); failure4: - bt_dev_class_destroy(bt_drv->bt_class); + bt_dev_class_destroy(bt_drv->bt_class); failure3: - bt_table_destroy(bt_drv); + bt_table_destroy(bt_drv); failure2: - kfree(bt_drv); + kfree(bt_drv); failure1: - return -1; + return -1; } module_init(bt_module_init); diff --git a/src/linux/drivers/net/bt/btdev.h b/src/linux/drivers/net/bt/btdev.h index e65f036..fcf367f 100644 --- a/src/linux/drivers/net/bt/btdev.h +++ b/src/linux/drivers/net/bt/btdev.h @@ -1,3 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + */ + #ifndef _BTDEV_H_ #define _BTDEV_H_ @@ -31,14 +36,14 @@ /* must include btdev_user.h first before any macro definition */ #include "btdev_user.h" -#define BT_DEV_MAJOR 125 -#define BT_DEV_MINOR 0 -#define BT_RING_BUFFER_SIZE 4096 -#define STRTOLL_BASE 10 -#define BT_DEV_ID_OFFSET (sizeof(BT_DEV_PATH_PREFIX) - 1) -#define BT_STATISTIC_KTIME_MAX ULONG_MAX +#define BT_DEV_MAJOR 125 +#define BT_DEV_MINOR 0 +#define BT_RING_BUFFER_SIZE 4096 +#define STRTOLL_BASE 10 +#define BT_DEV_ID_OFFSET (sizeof(BT_DEV_PATH_PREFIX) - 1) +#define BT_STATISTIC_KTIME_MAX ULONG_MAX -/* +/** * for debug */ #define DEBUG @@ -46,198 +51,198 @@ /** * ring buffer */ -typedef struct bt_ring { - u32 head; - u32 tail; - u32 size; - void **data; -} bt_ring_t; +struct bt_ring { + u32 head; + u32 tail; + u32 size; + void **data; +}; /** * one char device */ -typedef struct bt_cdev { - struct cdev *cdev; - struct class *bt_class; - char dev_filename[BT_PATHNAME_MAX]; -} bt_cdev_t; - -typedef struct bt_mng_file { - bt_cdev_t *bt_cdev; - atomic_t open_limit; -} bt_mng_file_t; +struct bt_cdev { + struct cdev *cdev; + struct class *bt_class; + char dev_filename[BT_PATHNAME_MAX]; +}; +struct bt_mng_file { + struct bt_cdev *bt_cdev; + atomic_t open_limit; +}; -typedef struct bt_io_file { - bt_cdev_t *bt_cdev; - atomic_t read_open_limit; - atomic_t write_open_limit; -} bt_io_file_t; +struct bt_io_file { + struct bt_cdev *bt_cdev; + atomic_t read_open_limit; + atomic_t write_open_limit; +}; /** * virnet list */ -typedef struct bt_table { - struct list_head head; - struct mutex tbl_lock; - uint32_t num; -} bt_table_t; +struct bt_table { + struct list_head head; + struct mutex tbl_lock; // lock for table + u32 num; +}; /** * bt virnet state */ enum bt_virnet_state { - BT_VIRNET_STATE_CREATED, - BT_VIRNET_STATE_CONNECTED, - BT_VIRNET_STATE_DISCONNECTED, - BT_VIRNET_STATE_DISABLED, - BT_VIRNET_STATE_DELETED, - BT_VIRNET_STAET_NUM + BT_VIRNET_STATE_CREATED, + BT_VIRNET_STATE_CONNECTED, + BT_VIRNET_STATE_DISCONNECTED, + BT_VIRNET_STATE_DISABLED, + BT_VIRNET_STATE_DELETED, + BT_VIRNET_STAET_NUM }; /** * one virnet device */ -typedef struct bt_virnet { - bt_ring_t *tx_ring; - bt_io_file_t *io_file; - struct net_device *ndev; - struct list_head virnet_entry; - bt_table_t *bt_table_head; - enum bt_virnet_state state; - struct semaphore sem; - wait_queue_head_t rx_queue, tx_queue; -} bt_virnet_t; +struct bt_virnet { + struct bt_ring *tx_ring; + struct bt_io_file *io_file; + struct net_device *ndev; + struct list_head virnet_entry; + struct bt_table *bt_table_head; + enum bt_virnet_state state; + struct semaphore sem; + wait_queue_head_t rx_queue, tx_queue; +}; /** * instance of the module */ -typedef struct bt_drv { - bt_table_t *devices_table; - bt_mng_file_t *mng_file; - bt_io_file_t **io_files; - uint32_t bitmap; - struct mutex bitmap_lock; - struct class *bt_class; -} bt_drv_t; +struct bt_drv { + struct bt_table *devices_table; + struct bt_mng_file *mng_file; + struct bt_io_file **io_files; + u32 bitmap; + struct mutex bitmap_lock; // lock for bitmap + struct class *bt_class; +}; /** * state to string */ -static const char* bt_virnet_state_rep[BT_VIRNET_STAET_NUM] = { - "CREATED", - "CONNECTED", - "DISCONNECTED", - "DISABLED", - "ENABLED" -}; +static const char *bt_virnet_state_rep[BT_VIRNET_STAET_NUM] = { + "CREATED", + "CONNECTED", + "DISCONNECTED", + "DISABLED", + "ENABLED"}; /** * inline functions */ -static inline int bt_get_unused_id(const uint32_t *bitmap) +static inline int bt_get_unused_id(const u32 *bitmap) { - int i; - BUG_ON(!bitmap); - for (i=0; istate = state; + WARN_ON(!vn); + vn->state = state; } -static inline const struct cdev *bt_virnet_get_cdev(const bt_virnet_t *vn) +static inline const struct cdev *bt_virnet_get_cdev(const struct bt_virnet *vn) { - BUG_ON(!vn); - return vn->io_file->bt_cdev->cdev; + WARN_ON(!vn); + return vn->io_file->bt_cdev->cdev; } -static inline const dev_t bt_virnet_get_cdev_number(const bt_virnet_t *vn) +static inline const dev_t bt_virnet_get_cdev_number(const struct bt_virnet *vn) { - BUG_ON(!vn); - return vn->io_file->bt_cdev->cdev->dev; + WARN_ON(!vn); + return vn->io_file->bt_cdev->cdev->dev; } -static inline const char *bt_virnet_get_cdev_name(const bt_virnet_t *vn) +static inline const char *bt_virnet_get_cdev_name(const struct bt_virnet *vn) { - BUG_ON(!vn); - return vn->io_file->bt_cdev->dev_filename; + WARN_ON(!vn); + return vn->io_file->bt_cdev->dev_filename; } -static inline struct net_device *bt_virnet_get_ndev(const bt_virnet_t *vn) +static inline struct net_device *bt_virnet_get_ndev(const struct bt_virnet *vn) { - BUG_ON(!vn); - return vn->ndev; + WARN_ON(!vn); + return vn->ndev; } -static inline const char *bt_virnet_get_ndev_name(const bt_virnet_t *vn) +static inline const char *bt_virnet_get_ndev_name(const struct bt_virnet *vn) { - BUG_ON(!vn); - return vn->ndev->name; + WARN_ON(!vn); + return vn->ndev->name; } -static inline const char *bt_virnet_get_state_rep(const bt_virnet_t *vn) +static inline const char *bt_virnet_get_state_rep(const struct bt_virnet *vn) { - BUG_ON(!vn); - return bt_virnet_state_rep[vn->state]; + WARN_ON(!vn); + return bt_virnet_state_rep[vn->state]; } -static inline int bt_get_total_device(const bt_drv_t *bt_drv) +static inline int bt_get_total_device(const struct bt_drv *bt_drv) { - BUG_ON(!bt_drv); - return bt_drv->devices_table->num; + WARN_ON(!bt_drv); + return bt_drv->devices_table->num; } -static inline int bt_virnet_get_ring_packets(const bt_virnet_t *vn) +static inline int bt_virnet_get_ring_packets(const struct bt_virnet *vn) { - int packets = 0; - BUG_ON(!vn); - packets = vn->tx_ring->head - vn->tx_ring->tail; - if (unlikely(packets < 0)) { - packets += BT_RING_BUFFER_SIZE; - } - return packets; + int packets = 0; + + WARN_ON(!vn); + packets = vn->tx_ring->head - vn->tx_ring->tail; + if (unlikely(packets < 0)) + packets += BT_RING_BUFFER_SIZE; + + return packets; } -static bt_table_t *bt_table_init(void); -static int bt_table_add_device(bt_table_t *tbl, bt_virnet_t *vn); -static void bt_table_remove_device(bt_table_t *tbl, bt_virnet_t *vn); -static void bt_table_delete_all(bt_drv_t *drv); -static bt_virnet_t *bt_table_find(bt_table_t *tbl, const char *ifa_name); -static void bt_table_destroy(bt_drv_t *drv); -static void bt_delete_io_files(bt_drv_t *drv); -static bt_io_file_t **bt_create_io_files(void); - -static bt_ring_t *bt_ring_create(void); -static int bt_ring_is_empty(const bt_ring_t *ring); -static int bt_ring_is_full(const bt_ring_t *ring); -static void *bt_ring_current(bt_ring_t *ring); -static void bt_ring_produce(bt_ring_t *ring, void *data); -static void bt_ring_consume(bt_ring_t *ring); -static void bt_ring_clear(bt_ring_t *ring); -static void bt_ring_destroy(bt_ring_t *ring); - -static int bt_virnet_produce_data(bt_virnet_t *dev, void *data); -static bt_virnet_t *bt_virnet_create(bt_drv_t *drv, uint32_t id); -static void bt_virnet_destroy(bt_virnet_t *dev); +static struct bt_table *bt_table_init(void); +static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn); +static void bt_table_remove_device(struct bt_table *tbl, struct bt_virnet *vn); +static void bt_table_delete_all(struct bt_drv *drv); +static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_name); +static void bt_table_destroy(struct bt_drv *drv); +static void bt_delete_io_files(struct bt_drv *drv); +static struct bt_io_file **bt_create_io_files(void); + +static struct bt_ring *bt_ring_create(void); +static int bt_ring_is_empty(const struct bt_ring *ring); +static int bt_ring_is_full(const struct bt_ring *ring); +static void *bt_ring_current(struct bt_ring *ring); +static void bt_ring_produce(struct bt_ring *ring, void *data); +static void bt_ring_consume(struct bt_ring *ring); +static void bt_ring_destroy(struct bt_ring *ring); + +static int bt_virnet_produce_data(struct bt_virnet *dev, void *data); +static struct bt_virnet *bt_virnet_create(struct bt_drv *drv, u32 id); +static void bt_virnet_destroy(struct bt_virnet *dev); #endif diff --git a/src/linux/drivers/net/bt/btdev_user.h b/src/linux/drivers/net/bt/btdev_user.h index 281a388..22630db 100644 --- a/src/linux/drivers/net/bt/btdev_user.h +++ b/src/linux/drivers/net/bt/btdev_user.h @@ -1,46 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + */ + #ifndef _BTDEV_USER_H_ #define _BTDEV_USER_H_ #include #include +#define BT_VIRNET_NAME_PREFIX "btn" +#define BT_DEV_NAME_PREFIX "btdev" +#define BT_DEV_PATH_PREFIX "/dev/" BT_DEV_NAME_PREFIX -#define BT_VIRNET_NAME_PREFIX "btn" -#define BT_DEV_NAME_PREFIX "btdev" -#define BT_DEV_PATH_PREFIX "/dev/"BT_DEV_NAME_PREFIX - -#define BT_DEV_PATH(idx) BT_DEV_PATH_PREFIX#idx -#define BT_DEV_NAME(idx) BT_DEV_NAME_PREFIX#idx +#define BT_DEV_PATH(idx) (BT_DEV_PATH_PREFIX#idx) +#define BT_DEV_NAME(idx) (BT_DEV_NAME_PREFIX#idx) -#define BT_DEV_NAME_MNG_FILE BT_DEV_NAME(0) -#define BT_DEV_PATH_MNG_FILE BT_DEV_PATH(0) -#define BT_DEV_NAME_IO_FILE(idx) BT_DEV_NAME(idx) -#define BT_DEV_PATH_IO_FILE(idx) BT_DEV_PATH(idx) -#define BT_VIRNET_NAME(idx) BT_VIRNET_NAME_PREFIX#idx +#define BT_DEV_NAME_MNG_FILE BT_DEV_NAME(0) +#define BT_DEV_PATH_MNG_FILE BT_DEV_PATH(0) +#define BT_DEV_NAME_IO_FILE(idx) BT_DEV_NAME(idx) +#define BT_DEV_PATH_IO_FILE(idx) BT_DEV_PATH(idx) +#define BT_VIRNET_NAME(idx) (BT_VIRNET_NAME_PREFIX#idx) -#define BT_PATHNAME_MAX 256 -#define BT_VIRNET_MAX_NUM 16 -#define BT_VIRNET_DATA_HEAD_LEN 2 +#define BT_PATHNAME_MAX 256 +#define BT_VIRNET_MAX_NUM 16 +#define BT_VIRNET_DATA_HEAD_LEN 2 -/* +/** * ioctl cmd */ -#define BT_IOC_CREATE _IO('b', 1) -#define BT_IOC_DELETE _IO('b', 2) -#define BT_IOC_CHANGE_MTU _IO('b', 3) -#define BT_IOC_QUERY_ALL _IO('b', 4) -#define BT_IOC_DELETE_ALL _IO('b', 5) -#define BT_IOC_ENABLE _IO('b', 6) -#define BT_IOC_DISABLE _IO('b', 7) -#define BT_IOC_PEEK_PACKET _IO('b', 8) - +#define BT_IOC_CREATE _IO('b', 1) +#define BT_IOC_DELETE _IO('b', 2) +#define BT_IOC_CHANGE_MTU _IO('b', 3) +#define BT_IOC_QUERY_ALL _IO('b', 4) +#define BT_IOC_DELETE_ALL _IO('b', 5) +#define BT_IOC_ENABLE _IO('b', 6) +#define BT_IOC_DISABLE _IO('b', 7) +#define BT_IOC_PEEK_PACKET _IO('b', 8) /** * user space ioctl arguments */ struct bt_uioc_args { - char ifa_name[IFNAMSIZ]; - char cfile_name[BT_PATHNAME_MAX]; + char ifa_name[IFNAMSIZ]; + char cfile_name[BT_PATHNAME_MAX]; }; #endif -- Gitee From ed0585b035b60d9ce5a04db3eeb0f00197a17000 Mon Sep 17 00:00:00 2001 From: yangyanjun Date: Wed, 15 Mar 2023 11:46:33 +0800 Subject: [PATCH 3/3] =?UTF-8?q?btdev=E9=94=99=E8=AF=AF=E7=A0=81=E6=95=B4?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E7=BC=96=E7=A0=81=E6=A0=BC=E5=BC=8F=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yangyanjun --- src/linux/drivers/net/bt/Makefile | 2 + src/linux/drivers/net/bt/btdev.c | 255 +++++++++++++----------------- src/linux/drivers/net/bt/btdev.h | 4 + 3 files changed, 120 insertions(+), 141 deletions(-) diff --git a/src/linux/drivers/net/bt/Makefile b/src/linux/drivers/net/bt/Makefile index 00a6e8b..74ae415 100644 --- a/src/linux/drivers/net/bt/Makefile +++ b/src/linux/drivers/net/bt/Makefile @@ -1 +1,3 @@ +# enable btdev: +# kernel/linux/linux-5.10/drivers/net/Makefile add obj-y += bt/ obj-y += btdev.o diff --git a/src/linux/drivers/net/bt/btdev.c b/src/linux/drivers/net/bt/btdev.c index 037709c..7c00858 100644 --- a/src/linux/drivers/net/bt/btdev.c +++ b/src/linux/drivers/net/bt/btdev.c @@ -11,7 +11,7 @@ static int bt_seq_show(struct seq_file *m, void *v) { struct bt_virnet *vnet = NULL; - pr_devel("bt seq_show\n"); + pr_devel("bt seq_show"); seq_printf(m, "Total device: %d (bitmap: 0x%X) Ring size: %d\n", bt_get_total_device(bt_drv), bt_drv->bitmap, BT_RING_BUFFER_SIZE); @@ -25,12 +25,12 @@ static int bt_seq_show(struct seq_file *m, void *v) bt_virnet_get_ring_packets(vnet)); } - return 0; + return OK; } static int bt_proc_open(struct inode *inode, struct file *file) { - pr_devel("bt proc_open\n"); + pr_devel("bt proc_open"); return single_open(file, bt_seq_show, PDE_DATA(inode)); } @@ -43,17 +43,19 @@ static struct proc_ops bt_proc_fops = { static int bt_io_file_open(struct inode *node, struct file *filp) { struct bt_virnet *vnet = NULL; - int ret = 0; + int ret = OK; - pr_devel("bt io file open called...\n"); + pr_devel("bt io file open called"); list_for_each_entry(vnet, &bt_drv->devices_table->head, virnet_entry) { if (bt_virnet_get_cdev(vnet) == node->i_cdev) { + struct net_device *ndev; + if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { if (unlikely(!atomic_dec_and_test(&vnet->io_file ->read_open_limit))) { atomic_inc(&vnet->io_file->read_open_limit); - pr_err("file %s has been opened for read twice already\n", + pr_err("file %s has been opened for read twice already", bt_virnet_get_cdev_name(vnet)); return -EBUSY; } @@ -61,7 +63,7 @@ static int bt_io_file_open(struct inode *node, struct file *filp) if (unlikely(!atomic_dec_and_test(&vnet->io_file ->write_open_limit))) { atomic_inc(&vnet->io_file->write_open_limit); - pr_err("file %s has been opened for write twice already\n", + pr_err("file %s has been opened for write twice already", bt_virnet_get_cdev_name(vnet)); return -EBUSY; } @@ -69,7 +71,7 @@ static int bt_io_file_open(struct inode *node, struct file *filp) if (unlikely(!atomic_dec_and_test(&vnet->io_file ->read_open_limit))) { atomic_inc(&vnet->io_file->read_open_limit); - pr_err("file %s has been opened for read twice already\n", + pr_err("file %s has been opened for read twice already", bt_virnet_get_cdev_name(vnet)); return -EBUSY; } @@ -77,19 +79,19 @@ static int bt_io_file_open(struct inode *node, struct file *filp) if (unlikely(!atomic_dec_and_test(&vnet->io_file ->write_open_limit))) { atomic_inc(&vnet->io_file->write_open_limit); - pr_err("file %s has been opened for write twice already\n", + pr_err("file %s has been opened for write twice already", bt_virnet_get_cdev_name(vnet)); return -EBUSY; } } rtnl_lock(); - if (unlikely(!(vnet->ndev->flags & IFF_UP))) { - ret = dev_change_flags(vnet->ndev, vnet->ndev - ->flags | IFF_UP, NULL); + ndev = vnet->ndev; + if (unlikely(!(ndev->flags & IFF_UP))) { + ret = dev_change_flags(ndev, ndev->flags | IFF_UP, NULL); if (unlikely(ret < 0)) { rtnl_unlock(); - pr_err("bt dev_change_flags error: ret=%d\n", ret); + pr_err("bt dev_change_flags error: ret=%d", ret); return -EBUSY; } } @@ -97,18 +99,18 @@ static int bt_io_file_open(struct inode *node, struct file *filp) SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); filp->private_data = vnet; - return 0; + return OK; } } - return -EFAULT; + return -EIO; } static int bt_io_file_release(struct inode *node, struct file *filp) { struct bt_virnet *vnet = filp->private_data; - pr_devel("bt io file release called...\n"); + pr_devel("bt io file release called"); if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { atomic_inc(&vnet->io_file->read_open_limit); @@ -121,7 +123,7 @@ static int bt_io_file_release(struct inode *node, struct file *filp) SET_STATE(vnet, BT_VIRNET_STATE_DISCONNECTED); - return 0; + return OK; } static ssize_t bt_io_file_read(struct file *filp, @@ -132,7 +134,7 @@ static ssize_t bt_io_file_read(struct file *filp, ssize_t out_sz; struct sk_buff *skb = NULL; - pr_devel("bt io file read called...\n"); + pr_devel("bt io file read called"); while (unlikely(bt_ring_is_empty(vnet->tx_ring))) { if (filp->f_flags & O_NONBLOCK) @@ -144,24 +146,24 @@ static ssize_t bt_io_file_read(struct file *filp, } skb = bt_ring_current(vnet->tx_ring); - out_sz = skb->len - 2 * ETH_ALEN; + out_sz = skb->len - MACADDR_LEN; if (unlikely(out_sz > size)) { - pr_err("io file read: buffer too small: skb's len=%ld buffer's len=%ld\n", + pr_err("io file read: buffer too small: skb's len=%ld buffer's len=%ld", (long)out_sz, (long)size); return -EINVAL; } bt_ring_consume(vnet->tx_ring); - if (copy_to_user(buffer, skb->data + 2 * ETH_ALEN, out_sz)) { - pr_err("io file read: copy_to_user failed\n"); - return -EFAULT; + if (copy_to_user(buffer, skb->data + MACADDR_LEN, out_sz)) { + pr_err("io file read: copy_to_user failed"); + return -EIO; } dev_kfree_skb(skb); skb = NULL; if (unlikely(netif_queue_stopped(vnet->ndev))) { - pr_info("consume data: wake the queue\n"); + pr_devel("consume data: wake the queue"); netif_wake_queue(vnet->ndev); } @@ -178,11 +180,8 @@ static ssize_t bt_io_file_write(struct file *filp, int len; ssize_t in_sz; - pr_devel("bt io file write called...\n"); - - pr_info("bt io file write called: %lu bytes\n", size); - - in_sz = size + 2 * ETH_ALEN; + pr_devel("bt io file write called: %lu bytes", size); + in_sz = size + MACADDR_LEN; skb = netdev_alloc_skb(bt_virnet_get_ndev(vnet), in_sz + 2); if (unlikely(!skb)) @@ -191,9 +190,9 @@ static ssize_t bt_io_file_write(struct file *filp, skb_reserve(skb, 2); skb_put(skb, in_sz); - memset(skb->data, 0, 2 * ETH_ALEN); - if (copy_from_user(skb->data + 2 * ETH_ALEN, buffer, size)) - return -EFAULT; + memset(skb->data, 0, MACADDR_LEN); + if (copy_from_user(skb->data + MACADDR_LEN, buffer, size)) + return -EIO; len = skb->len; skb->dev = bt_virnet_get_ndev(vnet); @@ -213,16 +212,16 @@ static ssize_t bt_io_file_write(struct file *filp, static int bt_virnet_change_mtu(struct net_device *dev, int mtu) { - pr_devel("bt virnet change mtu called...\n"); + pr_devel("bt virnet change mtu called"); dev->mtu = mtu; - return 0; + return OK; } static int bt_set_mtu(struct net_device *dev, int mtu) { - int err = 0; + int err = OK; - pr_info("bt set_mtu called...\n"); + pr_devel("bt set_mtu called"); rtnl_lock(); err = dev_set_mtu(dev, mtu); if (err < 0) @@ -240,21 +239,21 @@ static int bt_cmd_enable_virnet(struct bt_virnet *vnet, unsigned long arg) WARN_ON(!vnet); if (unlikely(vnet->state != BT_VIRNET_STATE_DISABLED)) { - pr_err("bt enable can only be set at DISABLED state\n"); - return -1; // enable failed + pr_err("bt enable can only be set at DISABLED state"); + return -EINVAL; // enable failed } rtnl_lock(); ret = dev_change_flags(vnet->ndev, vnet->ndev->flags | IFF_UP, NULL); if (unlikely(ret < 0)) { rtnl_unlock(); - pr_err("bt cmd enable virnet: dev_change_flags error: ret=%d\n", ret); - return -2; + pr_err("bt cmd enable virnet: dev_change_flags error: ret=%d", ret); + return -EIO; } rtnl_unlock(); SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); - return 0; + return OK; } static int bt_cmd_disable_virnet(struct bt_virnet *vnet, unsigned long arg) @@ -263,21 +262,21 @@ static int bt_cmd_disable_virnet(struct bt_virnet *vnet, unsigned long arg) WARN_ON(!vnet); if (unlikely(vnet->state != BT_VIRNET_STATE_CONNECTED)) { - pr_err("bt disable can only be set at CONNECTED state\n"); - return -1; + pr_err("bt disable can only be set at CONNECTED state"); + return -EINVAL; } rtnl_lock(); ret = dev_change_flags(vnet->ndev, vnet->ndev->flags & ~IFF_UP, NULL); if (unlikely(ret < 0)) { rtnl_unlock(); - pr_err("bt cmd disable virnet: dev_change_flags error: ret=%d\n", ret); - return -2; + pr_err("bt cmd disable virnet: dev_change_flags error: ret=%d", ret); + return -EIO; } rtnl_unlock(); SET_STATE(vnet, BT_VIRNET_STATE_DISABLED); - return 0; + return OK; } static int bt_cmd_change_mtu(struct bt_virnet *vnet, unsigned long arg) @@ -288,37 +287,37 @@ static int bt_cmd_change_mtu(struct bt_virnet *vnet, unsigned long arg) WARN_ON(!vnet); if (unlikely(get_user(mtu, (int __user *)arg))) { - pr_err("get_user failed!!\n"); - return -1; + pr_err("get_user failed"); + return -EIO; } ret = bt_set_mtu(vnet->ndev, mtu); if (unlikely(ret < 0)) { - pr_err("bt_dev_ioctl: changed mtu failed\n"); - return -1; + pr_err("bt_dev_ioctl: changed mtu failed"); + return -EIO; } - return 0; + return OK; } static int bt_cmd_peek_packet(struct bt_virnet *vnet, unsigned long arg) { struct sk_buff *skb = NULL; - pr_devel("bt peek packet called...\n"); + pr_devel("bt peek packet called"); if (unlikely(bt_ring_is_empty(vnet->tx_ring))) { - pr_err("bt peek packet ring is empty...\n"); + pr_err("bt peek packet ring is empty"); return -EAGAIN; } skb = bt_ring_current(vnet->tx_ring); - if (unlikely(put_user(skb->len - 2 * ETH_ALEN, (int __user *)arg))) { - pr_err("put_user failed!!\n"); - return -1; + if (unlikely(put_user(skb->len - MACADDR_LEN, (int __user *)arg))) { + pr_err("put_user failed"); + return -EIO; } - return 0; + return OK; } static long bt_io_file_ioctl(struct file *filep, @@ -329,33 +328,23 @@ static long bt_io_file_ioctl(struct file *filep, struct bt_virnet *vnet = filep->private_data; - pr_devel("bt io file ioctl called...\n"); + pr_devel("bt io file ioctl called"); switch (cmd) { case BT_IOC_CHANGE_MTU: - { ret = bt_cmd_change_mtu(vnet, arg); break; - } case BT_IOC_ENABLE: - { ret = bt_cmd_enable_virnet(vnet, arg); break; - } case BT_IOC_DISABLE: - { ret = bt_cmd_disable_virnet(vnet, arg); break; - } case BT_IOC_PEEK_PACKET: - { ret = bt_cmd_peek_packet(vnet, arg); break; - } default: - { - pr_err("not a valid cmd\n"); - return -1; - } + pr_err("not a valid cmd"); + return -ENOIOCTLCMD; } return ret; @@ -390,26 +379,26 @@ static const struct file_operations bt_io_file_ops = { static int bt_mng_file_open(struct inode *node, struct file *filp) { - pr_devel("bt mng file open called...\n"); + pr_devel("bt mng file open called"); if (unlikely(!atomic_dec_and_test(&bt_drv->mng_file->open_limit))) { atomic_inc(&bt_drv->mng_file->open_limit); - pr_err("file %s has been opened already\n", + pr_err("file %s has been opened already", bt_drv->mng_file->bt_cdev->dev_filename); return -EBUSY; } filp->private_data = bt_drv; - return 0; + return OK; } static int bt_mng_file_release(struct inode *node, struct file *filp) { struct bt_drv *bt_drv = filp->private_data; - pr_devel("bt mng file release called...\n"); + pr_devel("bt mng file release called"); atomic_inc(&bt_drv->mng_file->open_limit); - return 0; + return OK; } static int bt_cmd_create_virnet(struct bt_drv *bt_mng, unsigned long arg) @@ -424,18 +413,18 @@ static int bt_cmd_create_virnet(struct bt_drv *bt_mng, unsigned long arg) mutex_lock(&bt_mng->bitmap_lock); id = bt_get_unused_id(&bt_mng->bitmap); - pr_info("create io_file: get unused bit: %d\n", id); + pr_devel("create io_file: get unused bit: %d", id); if (unlikely(bt_mng->devices_table->num == BT_VIRNET_MAX_NUM)) { - pr_err("reach the limit of max virnets\n"); + pr_err("reach the limit of max virnets"); mutex_unlock(&bt_mng->bitmap_lock); - return -1; + return -EIO; } vnet = bt_virnet_create(bt_mng, id); if (unlikely(!vnet)) { - pr_err("bt virnet create failed\n"); + pr_err("bt virnet create failed"); mutex_unlock(&bt_mng->bitmap_lock); - return -1; + return -EIO; } vnet->bt_table_head = bt_mng->devices_table; @@ -444,7 +433,7 @@ static int bt_cmd_create_virnet(struct bt_drv *bt_mng, unsigned long arg) pr_err("bt table add device failed: ret=%d", ret); bt_virnet_destroy(vnet); mutex_unlock(&bt_mng->bitmap_lock); - return -1; // failed to create + return -EIO; // failed to create } bt_set_bit(&bt_mng->bitmap, id); @@ -455,14 +444,14 @@ static int bt_cmd_create_virnet(struct bt_drv *bt_mng, unsigned long arg) memcpy(vp.cfile_name, bt_virnet_get_cdev_name(vnet), sizeof(vp.cfile_name)); - mdelay(100); + mdelay(DELAY_100_MS); size = copy_to_user((void __user *)arg, &vp, sizeof(struct bt_uioc_args)); if (unlikely(size)) { pr_err("copy_to_user failed: left size=%lu", size); - return -1; + return -EIO; } - return 0; + return OK; } static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) @@ -478,13 +467,13 @@ static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) sizeof(struct bt_uioc_args)); if (unlikely(size)) { pr_err("copy_from_user failed: left size=%lu", size); - return -1; + return -EIO; } vnet = bt_table_find(bt_mng->devices_table, vp.ifa_name); if (unlikely(!vnet)) { pr_err("virnet: %s cannot be found in bt table", vp.ifa_name); - return -2; // not found + return -EIO; // not found } mutex_lock(&bt_mng->bitmap_lock); @@ -493,24 +482,24 @@ static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) bt_virnet_destroy(vnet); bt_clear_bit(&bt_mng->bitmap, id); mutex_unlock(&bt_mng->bitmap_lock); - return 0; + return OK; } static int bt_cmd_query_all_virnets(struct bt_drv *bt_mng, unsigned long arg) { WARN_ON(!bt_mng); if (unlikely(put_user(bt_mng->bitmap, (u32 *)arg))) { - pr_err("put_user failed!!\n"); - return -1; + pr_err("put_user failed"); + return -EIO; } - return 0; + return OK; } static int bt_cmd_delete_all_virnets(struct bt_drv *bt_mng, unsigned long arg) { WARN_ON(!bt_mng); bt_table_delete_all(bt_mng); - return 0; + return OK; } static long bt_mng_file_ioctl(struct file *filep, @@ -521,37 +510,23 @@ static long bt_mng_file_ioctl(struct file *filep, struct bt_drv *bt_mng = filep->private_data; - pr_devel("bt mng file ioctl called...\n"); + pr_devel("bt mng file ioctl called"); switch (cmd) { case BT_IOC_CREATE: - { ret = bt_cmd_create_virnet(bt_mng, arg); break; - } - case BT_IOC_DELETE: - { ret = bt_cmd_delete_virnet(bt_mng, arg); break; - } - case BT_IOC_QUERY_ALL: - { ret = bt_cmd_query_all_virnets(bt_mng, arg); break; - } - case BT_IOC_DELETE_ALL: - { ret = bt_cmd_delete_all_virnets(bt_mng, arg); break; - } - default: - { - pr_err("not a valid command\n"); - return -1; - } + pr_err("not a valid command"); + return -ENOIOCTLCMD; } return ret; } @@ -570,16 +545,14 @@ static netdev_tx_t bt_virnet_xmit(struct sk_buff *skb, struct bt_virnet *vnet = NULL; int len = skb->len; - pr_alert("alert: bt virnet_xmit: called...\n"); - + pr_alert("alert: bt virnet_xmit: called"); vnet = bt_table_find(bt_drv->devices_table, dev->name); WARN_ON(!vnet); ret = bt_virnet_produce_data(vnet, (void *)skb); if (unlikely(ret < 0)) { - pr_info("virnet xmit: produce data failed: ring is full\n" - "need to stop queue\n"); + pr_devel("virnet xmit: produce data failed: ring is full, need to stop queue"); netif_stop_queue(vnet->ndev); return NETDEV_TX_BUSY; } @@ -619,7 +592,7 @@ static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn) vnet = bt_table_find(tbl, bt_virnet_get_ndev_name(vn)); if (unlikely(vnet)) { pr_err("found duplicated device"); - return -1; // duplicated + return -ENOIOCTLCMD; // duplicated } mutex_lock(&tbl->tbl_lock); @@ -627,7 +600,7 @@ static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn) ++tbl->num; mutex_unlock(&tbl->tbl_lock); - return 0; + return OK; } static void bt_table_remove_device(struct bt_table *tbl, struct bt_virnet *vn) @@ -699,7 +672,7 @@ static struct bt_ring *__bt_ring_create(int size) struct bt_ring *ring = kmalloc(sizeof(*ring), GFP_KERNEL); if (unlikely(!ring)) { - pr_err("ring create alloc failed: oom\n"); + pr_err("ring create alloc failed: oom"); return NULL; } @@ -710,7 +683,7 @@ static struct bt_ring *__bt_ring_create(int size) ring->tail = 0; ring->data = kmalloc_array(size, sizeof(void *), GFP_KERNEL); if (unlikely(!ring->data)) { - pr_err("ring create alloc data failed: oom\n"); + pr_err("ring create alloc data failed: oom"); kfree(ring); return NULL; } @@ -777,8 +750,8 @@ static int bt_virnet_produce_data(struct bt_virnet *dev, void *data) WARN_ON(!dev); WARN_ON(!data); if (unlikely(bt_ring_is_full(dev->tx_ring))) { - pr_info("ring is full"); - return -1; + pr_devel("ring is full"); + return -ENFILE; } smp_wmb(); // Make sure the write order is correct @@ -786,7 +759,7 @@ static int bt_virnet_produce_data(struct bt_virnet *dev, void *data) smp_wmb(); // Make sure twrite order is correct wake_up(&dev->rx_queue); - return 0; + return OK; } /** @@ -824,17 +797,17 @@ static int bt_cdev_device_create(struct bt_cdev *dev, WARN_ON(!dev); WARN_ON(!cls); - pr_devel("bt cdev_device_create: id=%d\n", id); + pr_devel("bt cdev_device_create: id=%d", id); dev->bt_class = cls; device = device_create(cls, NULL, devno, NULL, "%s%u", BT_DEV_NAME_PREFIX, id); if (IS_ERR(device)) { pr_err("create device failed"); - return -1; + return -EIO; } snprintf(dev->dev_filename, sizeof(dev->dev_filename), "%s%u", BT_DEV_PATH_PREFIX, id); - return 0; + return OK; } static void bt_cdev_device_destroy(struct bt_cdev *dev) @@ -853,17 +826,17 @@ static struct bt_cdev *bt_cdev_create(const struct file_operations *ops, WARN_ON(!ops); - pr_devel("bt cdev create called...\n"); + pr_devel("bt cdev create called"); dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (unlikely(!dev)) { - pr_err("bt cdev_create alloc failed: oom\n"); + pr_err("bt cdev_create alloc failed: oom"); goto err1; } chrdev = cdev_alloc(); if (unlikely(!chrdev)) { - pr_err("bt cdev_create: cdev_alloc() failed: oom\n"); + pr_err("bt cdev_create: cdev_alloc() failed: oom"); goto err2; } @@ -872,12 +845,12 @@ static struct bt_cdev *bt_cdev_create(const struct file_operations *ops, ret = cdev_add(chrdev, MKDEV(BT_DEV_MAJOR, minor), 1); if (unlikely(ret < 0)) { - pr_err("cdev add failed\n"); + pr_err("cdev add failed"); goto err3; } if (unlikely(bt_cdev_device_create(dev, bt_drv->bt_class, minor) < 0)) { - pr_err("bt cdev_device_create failed\n"); + pr_err("bt cdev_device_create failed"); goto err3; } return dev; @@ -921,12 +894,12 @@ static struct bt_io_file *bt_create_io_file(u32 id) struct bt_io_file *file = kmalloc(sizeof(*file), GFP_KERNEL); if (unlikely(!file)) { - pr_err("bt create_io_file alloc failed: oom\n"); + pr_err("bt create_io_file alloc failed: oom"); return NULL; } file->bt_cdev = bt_cdev_create(&bt_io_file_ops, id); if (unlikely(!file->bt_cdev)) { - pr_err("bt create_io_file: create cdev failed\n"); + pr_err("bt create_io_file: create cdev failed"); kfree(file); return NULL; } @@ -937,12 +910,12 @@ static struct bt_io_file *bt_create_io_file(u32 id) static struct bt_io_file **bt_create_io_files(void) { - int i = 0; + int i; struct bt_io_file **all_files = kmalloc(BT_VIRNET_MAX_NUM * sizeof(struct bt_io_file *), - GFP_KERNEL); + GFP_KERNEL); if (unlikely(!all_files)) { - pr_err("bt create_io_files alloc failed: oom\n"); + pr_err("bt create_io_files alloc failed: oom"); return NULL; } for (i = 0; i < BT_VIRNET_MAX_NUM; ++i) @@ -979,13 +952,13 @@ static struct bt_mng_file *bt_create_mng_file(int id) struct bt_mng_file *file = kmalloc(sizeof(*file), GFP_KERNEL); if (unlikely(!file)) { - pr_err("bt create_mng_file: oom\n"); + pr_err("bt create_mng_file: oom"); return NULL; } file->bt_cdev = bt_cdev_create(&bt_mng_file_ops, id); if (unlikely(!file->bt_cdev)) { - pr_err("bt create_mng_file: create cdev failed\n"); + pr_err("bt create_mng_file: create cdev failed"); kfree(file); return NULL; } @@ -1024,7 +997,7 @@ static struct net_device *bt_net_device_create(u32 id) snprintf(ifa_name, sizeof(ifa_name), "%s%d", BT_VIRNET_NAME_PREFIX, id); ndev = alloc_netdev(0, ifa_name, NET_NAME_UNKNOWN, ether_setup); if (unlikely(!ndev)) { - pr_err("alloc_netdev failed\n"); + pr_err("alloc_netdev failed"); return NULL; } @@ -1069,7 +1042,7 @@ static struct bt_virnet *bt_virnet_create(struct bt_drv *bt_mng, u32 id) struct bt_virnet *vnet = kmalloc(sizeof(*vnet), GFP_KERNEL); if (unlikely(!vnet)) { - pr_err("error: bt_virnet init failed\n"); + pr_err("error: bt_virnet init failed"); goto failure1; } @@ -1142,7 +1115,7 @@ static int __init bt_module_init(void) int mid; struct proc_dir_entry *entry = NULL; - pr_devel("bt module_init called...\n"); + pr_devel("bt module_init called"); bt_drv = kmalloc(sizeof(*bt_drv), GFP_KERNEL); if (unlikely(!bt_drv)) { pr_err("module init: alloc struct bt_drv failed: oom"); @@ -1173,11 +1146,11 @@ static int __init bt_module_init(void) mutex_lock(&bt_drv->bitmap_lock); mid = bt_get_unused_id(&bt_drv->bitmap); - pr_info("create mng_file: get unused bit: %d\n", mid); + pr_devel("create mng_file: get unused bit: %d", mid); bt_drv->mng_file = bt_create_mng_file(mid); if (unlikely(!bt_drv->mng_file)) { - pr_err("bt_ctrl_cdev_init(): failed"); + pr_err("bt_ctrl_cdev_init failed"); mutex_unlock(&bt_drv->bitmap_lock); goto failure4; } @@ -1190,7 +1163,7 @@ static int __init bt_module_init(void) goto failure5; } - return 0; + return OK; failure5: bt_delete_mng_file(bt_drv->mng_file); @@ -1210,4 +1183,4 @@ failure1: module_init(bt_module_init); module_exit(bt_module_release); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_LICENSE("GPL"); diff --git a/src/linux/drivers/net/bt/btdev.h b/src/linux/drivers/net/bt/btdev.h index fcf367f..231c7a8 100644 --- a/src/linux/drivers/net/bt/btdev.h +++ b/src/linux/drivers/net/bt/btdev.h @@ -36,6 +36,10 @@ /* must include btdev_user.h first before any macro definition */ #include "btdev_user.h" +#define OK 0 +#define DELAY_100_MS 100 +#define MACADDR_LEN (2 * ETH_ALEN) + #define BT_DEV_MAJOR 125 #define BT_DEV_MINOR 0 #define BT_RING_BUFFER_SIZE 4096 -- Gitee