diff --git a/newip/src/linux-5.10/drivers/net/bt/btdev.c b/newip/src/linux-5.10/drivers/net/bt/btdev.c index ce4292974044e5ebfbe90fefd4274f4538c4651f..4eaff9bc7b3f834e1dbb87c57932d19ea437b480 100644 --- a/newip/src/linux-5.10/drivers/net/bt/btdev.c +++ b/newip/src/linux-5.10/drivers/net/bt/btdev.c @@ -1,6 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. + * + * Description: Bluetooth virtual network device used in + * the NewIP over Bluetooth communication scenario. + * + * Author: Yang Yanjun + * + * Data: 2023-03-14 */ #include "btdev.h" @@ -11,6 +18,10 @@ static int bt_seq_show(struct seq_file *m, void *v) { struct bt_virnet *vnet = NULL; + if (unlikely(!bt_drv)) { + pr_err("bt seq show: invalid bt_drv"); + return -EINVAL; + } 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, @@ -31,6 +42,11 @@ static int bt_seq_show(struct seq_file *m, void *v) static int bt_proc_open(struct inode *inode, struct file *file) { pr_devel("bt proc_open"); + if (unlikely(!inode) || unlikely(!file)) { + pr_err("bt proc open: invalid parameter"); + return -EINVAL; + } + return single_open(file, bt_seq_show, PDE_DATA(inode)); } @@ -40,76 +56,85 @@ static struct proc_ops bt_proc_fops = { .proc_lseek = seq_lseek, .proc_release = single_release}; +static int __bt_virnet_open(struct file *filp, struct bt_virnet *vnet) +{ + struct net_device *ndev; + + if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->read_open_limit))) + goto read_twice_already; + } else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->write_open_limit))) + goto write_twice_already; + } else if ((filp->f_flags & O_ACCMODE) == O_RDWR) { + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->read_open_limit))) + goto read_twice_already; + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->write_open_limit))) + goto write_twice_already; + } + + rtnl_lock(); + ndev = vnet->ndev; + if (unlikely(!(ndev->flags & IFF_UP))) { + int 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", ret); + return -EBUSY; + } + } + rtnl_unlock(); + + SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); + filp->private_data = vnet; + return OK; + +read_twice_already: + atomic_inc(&vnet->io_file->read_open_limit); + pr_err("file %s has been opened for read twice already", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + +write_twice_already: + atomic_inc(&vnet->io_file->write_open_limit); + pr_err("file %s has been opened for write twice already", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; +} + static int bt_io_file_open(struct inode *node, struct file *filp) { struct bt_virnet *vnet = NULL; - int ret = OK; + + if (unlikely(!node) || unlikely(!filp)) { + pr_err("bt io file open: invalid parameter"); + return -EINVAL; + } 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", - 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", - 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", - 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", - bt_virnet_get_cdev_name(vnet)); - return -EBUSY; - } - } - - rtnl_lock(); - 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", ret); - return -EBUSY; - } - } - rtnl_unlock(); - - SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); - filp->private_data = vnet; - return OK; - } + if (bt_virnet_get_cdev(vnet) == node->i_cdev) + return __bt_virnet_open(filp, vnet); } - return -EIO; } static int bt_io_file_release(struct inode *node, struct file *filp) { - struct bt_virnet *vnet = filp->private_data; + struct bt_virnet *vnet = NULL; + + if (unlikely(!filp) || unlikely(!filp->private_data)) { + pr_err("bt io file release: invalid parameter"); + return -EINVAL; + } + vnet = filp->private_data; pr_devel("bt io file release called"); if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { @@ -130,12 +155,17 @@ static ssize_t bt_io_file_read(struct file *filp, char __user *buffer, size_t size, loff_t *off) { - struct bt_virnet *vnet = filp->private_data; + struct bt_virnet *vnet = NULL; ssize_t out_sz; struct sk_buff *skb = NULL; pr_devel("bt io file read called"); + if (unlikely(!filp) || unlikely(!buffer) || unlikely(!filp->private_data)) { + pr_devel("bt io file read: invalid parameter"); + return -EINVAL; + } + vnet = filp->private_data; while (unlikely(bt_ring_is_empty(vnet->tx_ring))) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; @@ -146,6 +176,10 @@ static ssize_t bt_io_file_read(struct file *filp, } skb = bt_ring_current(vnet->tx_ring); + if (unlikely(!skb)) { + pr_devel("bt io file read: invalid skb"); + return -EINVAL; + } 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", @@ -174,20 +208,25 @@ static ssize_t bt_io_file_write(struct file *filp, const char __user *buffer, size_t size, loff_t *off) { - struct bt_virnet *vnet = filp->private_data; + struct bt_virnet *vnet = NULL; struct sk_buff *skb = NULL; int ret; int len; ssize_t in_sz; + if (unlikely(!filp) || unlikely(!buffer) || unlikely(!filp->private_data)) { + pr_err("bt io file write: invalid parameter"); + return -EINVAL; + } pr_devel("bt io file write called: %lu bytes", size); + vnet = filp->private_data; in_sz = size + MACADDR_LEN; - skb = netdev_alloc_skb(bt_virnet_get_ndev(vnet), in_sz + 2); + skb = netdev_alloc_skb(bt_virnet_get_ndev(vnet), in_sz + NEWIP_TYPE_SIZE); if (unlikely(!skb)) return -ENOMEM; - skb_reserve(skb, 2); + skb_reserve(skb, NEWIP_TYPE_SIZE); skb_put(skb, in_sz); memset(skb->data, 0, MACADDR_LEN); @@ -212,6 +251,10 @@ static ssize_t bt_io_file_write(struct file *filp, static int bt_virnet_change_mtu(struct net_device *dev, int mtu) { + if (unlikely(!dev) || unlikely(mtu < 0) || unlikely(mtu > BT_MAX_MTU)) { + pr_devel("bt virnet change mtu: invalid parameter"); + return -EINVAL; + } pr_devel("bt virnet change mtu called"); dev->mtu = mtu; return OK; @@ -221,6 +264,10 @@ static int bt_set_mtu(struct net_device *dev, int mtu) { int err = OK; + if (unlikely(mtu < 0) || unlikely(mtu > BT_MAX_MTU)) { + pr_devel("bt set mtu: invalid parameter"); + return -EINVAL; + } pr_devel("bt set_mtu called"); rtnl_lock(); err = dev_set_mtu(dev, mtu); @@ -236,8 +283,6 @@ static int bt_cmd_enable_virnet(struct bt_virnet *vnet, unsigned long arg) { int ret; - WARN_ON(!vnet); - if (unlikely(vnet->state != BT_VIRNET_STATE_DISABLED)) { pr_err("bt enable can only be set at DISABLED state"); return -EINVAL; // enable failed @@ -260,7 +305,6 @@ static int bt_cmd_disable_virnet(struct bt_virnet *vnet, unsigned long arg) { int ret; - WARN_ON(!vnet); if (unlikely(vnet->state != BT_VIRNET_STATE_CONNECTED)) { pr_err("bt disable can only be set at CONNECTED state"); return -EINVAL; @@ -284,8 +328,6 @@ static int bt_cmd_change_mtu(struct bt_virnet *vnet, unsigned long arg) int mtu; int ret; - WARN_ON(!vnet); - if (unlikely(get_user(mtu, (int __user *)arg))) { pr_err("get_user failed"); return -EIO; @@ -325,9 +367,13 @@ static long bt_io_file_ioctl(struct file *filep, unsigned long arg) { long ret; + struct bt_virnet *vnet = NULL; - struct bt_virnet *vnet = filep->private_data; - + if (unlikely(!filep) || unlikely(!filep->private_data)) { + pr_err("bt io file ioctl: invalid parameter"); + return -EINVAL; + } + vnet = filep->private_data; pr_devel("bt io file ioctl called"); switch (cmd) { case BT_IOC_CHANGE_MTU: @@ -352,9 +398,14 @@ static long bt_io_file_ioctl(struct file *filep, static unsigned int bt_io_file_poll(struct file *filp, poll_table *wait) { - struct bt_virnet *vnet = filp->private_data; + struct bt_virnet *vnet = NULL; unsigned int mask = 0; + if (unlikely(!filp) || unlikely(!wait) || unlikely(!filp->private_data)) { + pr_err("bt io file poll: invalid parameter"); + return -EINVAL; + } + vnet = filp->private_data; poll_wait(filp, &vnet->rx_queue, wait); poll_wait(filp, &vnet->tx_queue, wait); @@ -381,6 +432,11 @@ static int bt_mng_file_open(struct inode *node, struct file *filp) { pr_devel("bt mng file open called"); + if (unlikely(!filp)) { + pr_err("bt mng file open: invalid filp"); + return -EINVAL; + } + 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", @@ -393,8 +449,13 @@ static int bt_mng_file_open(struct inode *node, struct file *filp) static int bt_mng_file_release(struct inode *node, struct file *filp) { - struct bt_drv *drv = filp->private_data; + struct bt_drv *drv = NULL; + if (unlikely(!filp) || unlikely(!filp->private_data)) { + pr_err("bt mng file release: invalid parameter"); + return -EINVAL; + } + drv = filp->private_data; pr_devel("bt mng file release called"); atomic_inc(&drv->mng_file->open_limit); @@ -409,31 +470,24 @@ static int bt_cmd_create_virnet(struct bt_drv *bt_mng, unsigned long arg) 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); + id = bt_get_unused_id(bt_mng->bitmap); 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"); - mutex_unlock(&bt_mng->bitmap_lock); - return -EIO; + goto virnet_create_failed; } vnet = bt_virnet_create(bt_mng, id); if (unlikely(!vnet)) { pr_err("bt virnet create failed"); - mutex_unlock(&bt_mng->bitmap_lock); - return -EIO; + goto virnet_create_failed; } - 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 -EIO; // failed to create + goto add_device_failed; } bt_set_bit(&bt_mng->bitmap, id); @@ -449,19 +503,29 @@ static int bt_cmd_create_virnet(struct bt_drv *bt_mng, unsigned long arg) 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 -EIO; + goto copy_to_user_failed; } return OK; + +copy_to_user_failed: + mutex_lock(&bt_mng->bitmap_lock); + bt_clear_bit(&bt_mng->bitmap, id); + +add_device_failed: + bt_virnet_destroy(vnet); + +virnet_create_failed: + mutex_unlock(&bt_mng->bitmap_lock); + return -EIO; } static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) { - int id; + int err; struct bt_virnet *vnet = NULL; struct bt_uioc_args vp; unsigned long size; - - WARN_ON(!bt_mng); + dev_t number; size = copy_from_user(&vp, (void __user *)arg, sizeof(struct bt_uioc_args)); @@ -477,17 +541,17 @@ static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) } mutex_lock(&bt_mng->bitmap_lock); - id = MINOR(bt_virnet_get_cdev_number(vnet)); + err = bt_virnet_get_cdev_number(vnet, &number); + if (likely(!err)) + bt_clear_bit(&bt_mng->bitmap, (u32)MINOR(number)); 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 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"); return -EIO; @@ -497,9 +561,7 @@ static int bt_cmd_query_all_virnets(struct bt_drv *bt_mng, unsigned long arg) 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 OK; + return bt_table_delete_all(bt_mng); } static long bt_mng_file_ioctl(struct file *filep, @@ -507,9 +569,13 @@ static long bt_mng_file_ioctl(struct file *filep, unsigned long arg) { int ret; + struct bt_drv *bt_mng = NULL; - struct bt_drv *bt_mng = filep->private_data; - + if (unlikely(!filep) || unlikely(!filep->private_data)) { + pr_err("bt mng file ioctl: invalid parameter"); + return -EINVAL; + } + bt_mng = filep->private_data; pr_devel("bt mng file ioctl called"); switch (cmd) { case BT_IOC_CREATE: @@ -543,11 +609,18 @@ static netdev_tx_t bt_virnet_xmit(struct sk_buff *skb, { int ret; struct bt_virnet *vnet = NULL; - int len = skb->len; + + if (unlikely(!skb) || unlikely(!dev)) { + pr_err("virnet xmit: invalid parameter"); + return -EINVAL; + } pr_alert("alert: bt virnet_xmit: called"); vnet = bt_table_find(bt_drv->devices_table, dev->name); - WARN_ON(!vnet); + if (unlikely(!vnet)) { + pr_err("virnet xmit: bt_table_find failed"); + return -EINVAL; + } ret = bt_virnet_produce_data(vnet, (void *)skb); @@ -558,7 +631,7 @@ static netdev_tx_t bt_virnet_xmit(struct sk_buff *skb, } vnet->ndev->stats.tx_packets++; - vnet->ndev->stats.tx_bytes += len; + vnet->ndev->stats.tx_bytes += skb->len; return NETDEV_TX_OK; } @@ -586,8 +659,10 @@ static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn) { struct bt_virnet *vnet = NULL; - WARN_ON(!tbl); - WARN_ON(!vn); + if (unlikely(!tbl)) { + pr_err("bt table add device: invalid parameter"); + return -EINVAL; + } vnet = bt_table_find(tbl, bt_virnet_get_ndev_name(vn)); if (unlikely(vnet)) { @@ -605,8 +680,9 @@ 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) { - WARN_ON(!tbl); - WARN_ON(!vn); + if (unlikely(!tbl)) + return; + mutex_lock(&tbl->tbl_lock); list_del(&vn->virnet_entry); --tbl->num; @@ -617,10 +693,10 @@ static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_nam { struct bt_virnet *vnet = NULL; - WARN_ON(!tbl); - - if (unlikely(!ifa_name)) + if (unlikely(!tbl) || unlikely(!ifa_name)) { + pr_err("bt table find: invalid parameter"); return NULL; + } list_for_each_entry(vnet, &tbl->head, virnet_entry) { if (!strcmp(bt_virnet_get_ndev_name(vnet), ifa_name)) @@ -631,25 +707,31 @@ static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_nam static void __bt_table_delete_all(struct bt_drv *drv) { - u32 id; + int err; + dev_t number; struct bt_virnet *vnet = NULL, *tmp_vnet = NULL; - WARN_ON(!drv); + if (unlikely(!bt_drv->devices_table)) + return; + list_for_each_entry_safe(vnet, tmp_vnet, &drv->devices_table->head, virnet_entry) { - id = MINOR(bt_virnet_get_cdev_number(vnet)); + err = bt_virnet_get_cdev_number(vnet, &number); + if (likely(!err)) + bt_clear_bit(&drv->bitmap, (u32)MINOR(number)); 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(struct bt_drv *bt_drv) +static int bt_table_delete_all(struct bt_drv *bt_drv) { - WARN_ON(!bt_drv); + if (unlikely(!bt_drv->devices_table)) + return -EINVAL; + mutex_lock(&bt_drv->bitmap_lock); mutex_lock(&bt_drv->devices_table->tbl_lock); @@ -657,11 +739,11 @@ static void bt_table_delete_all(struct bt_drv *bt_drv) mutex_unlock(&bt_drv->devices_table->tbl_lock); mutex_unlock(&bt_drv->bitmap_lock); + return OK; } static void bt_table_destroy(struct bt_drv *bt_drv) { - WARN_ON(!bt_drv); __bt_table_delete_all(bt_drv); kfree(bt_drv->devices_table); bt_drv->devices_table = NULL; @@ -699,21 +781,22 @@ static struct bt_ring *bt_ring_create(void) static int bt_ring_is_empty(const struct bt_ring *ring) { - WARN_ON(!ring); + if (unlikely(!ring)) + return -EINVAL; + return ring->head == ring->tail; } static int bt_ring_is_full(const struct bt_ring *ring) { - WARN_ON(!ring); + if (unlikely(!ring)) + return -EINVAL; + return (ring->head + 1) % ring->size == ring->tail; } static void bt_ring_produce(struct bt_ring *ring, void *data) { - WARN_ON(!ring); - WARN_ON(!data); - smp_mb(); // Make sure the read and write order is correct ring->data[ring->head] = data; ring->head = (ring->head + 1) % ring->size; @@ -724,14 +807,17 @@ static void *bt_ring_current(struct bt_ring *ring) { void *data = NULL; - WARN_ON(!ring); + if (unlikely(!ring)) + return data; + data = ring->data[ring->tail]; return data; } static void bt_ring_consume(struct bt_ring *ring) { - WARN_ON(!ring); + if (unlikely(!ring)) + return; smp_rmb(); // Make sure the read order is correct ring->tail = (ring->tail + 1) % ring->size; @@ -740,15 +826,15 @@ static void bt_ring_consume(struct bt_ring *ring) static void bt_ring_destroy(struct bt_ring *ring) { - WARN_ON(!ring); + if (unlikely(!ring)) + return; + kfree(ring->data); kfree(ring); } 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_devel("ring is full"); return -ENFILE; @@ -783,7 +869,9 @@ static struct class *bt_dev_class_create(void) static void bt_dev_class_destroy(struct class *cls) { - WARN_ON(!cls); + if (unlikely(!cls)) + return; + class_destroy(cls); } @@ -794,8 +882,10 @@ static int bt_cdev_device_create(struct bt_cdev *dev, struct device *device = NULL; dev_t devno = MKDEV(BT_DEV_MAJOR, id); - WARN_ON(!dev); - WARN_ON(!cls); + if (unlikely(!cls)) { + pr_err("not a valid cls"); + return -EINVAL; + } pr_devel("bt cdev_device_create: id=%d", id); @@ -812,7 +902,6 @@ static int bt_cdev_device_create(struct bt_cdev *dev, static void bt_cdev_device_destroy(struct bt_cdev *dev) { - WARN_ON(!dev); device_destroy(dev->bt_class, dev->cdev->dev); } @@ -824,20 +913,18 @@ static struct bt_cdev *bt_cdev_create(const struct file_operations *ops, struct bt_cdev *dev = NULL; struct cdev *chrdev = NULL; - WARN_ON(!ops); - pr_devel("bt cdev create called"); dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (unlikely(!dev)) { pr_err("bt cdev_create alloc failed: oom"); - goto err1; + goto dev_alloc_failed; } chrdev = cdev_alloc(); if (unlikely(!chrdev)) { pr_err("bt cdev_create: cdev_alloc() failed: oom"); - goto err2; + goto cdev_alloc_failed; } cdev_init(chrdev, ops); @@ -846,22 +933,23 @@ 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"); - goto err3; + goto cdev_add_failed; } if (unlikely(bt_cdev_device_create(dev, bt_drv->bt_class, minor) < 0)) { pr_err("bt cdev_device_create failed"); - goto err3; + goto cdev_device_create_failed; } return dev; -err3: +cdev_device_create_failed: cdev_del(chrdev); -err2: +cdev_add_failed: +cdev_alloc_failed: kfree(dev); -err1: +dev_alloc_failed: return NULL; } @@ -872,17 +960,16 @@ static void bt_cdev_delete(struct bt_cdev *bt_cdev) { dev_t devno; - WARN_ON(!bt_cdev); - if (unlikely(bt_cdev)) { + if (likely(bt_cdev)) { devno = bt_cdev->cdev->dev; - unregister_chrdev(MAJOR(devno), bt_cdev->dev_filename + 5); + /* BT_DEV_PATH_PREFIX + ID --> /dev/btn1 */ + unregister_chrdev(MAJOR(devno), bt_cdev->dev_filename + strlen(BT_DEV_PATH_PREFIX)); bt_cdev_device_destroy(bt_cdev); cdev_del(bt_cdev->cdev); } else { pr_err("bt cdev_delete: cdev is null"); - return; } } @@ -994,6 +1081,10 @@ static struct net_device *bt_net_device_create(u32 id) int err; char ifa_name[IFNAMSIZ]; + if (unlikely(id < 0) || unlikely(id > BT_VIRNET_MAX_NUM)) { + pr_err("bt net device create: invalid id"); + return NULL; + } 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)) { @@ -1022,16 +1113,16 @@ static struct net_device *bt_net_device_create(u32 id) */ static void bt_net_device_destroy(struct net_device *dev) { - WARN_ON(!dev); unregister_netdev(dev); free_netdev(dev); } static struct bt_io_file *bt_get_io_file(struct bt_drv *drv, int id) { - WARN_ON(id < 1); - WARN_ON(id > BT_VIRNET_MAX_NUM); - return drv->io_files[id - 1]; + if (id >= 1 && id <= BT_VIRNET_MAX_NUM) + return drv->io_files[id - 1]; + + return NULL; } /** @@ -1043,25 +1134,25 @@ static struct bt_virnet *bt_virnet_create(struct bt_drv *bt_mng, u32 id) if (unlikely(!vnet)) { pr_err("error: bt_virnet init failed"); - goto failure1; + goto out_of_memory; } vnet->tx_ring = bt_ring_create(); if (unlikely(!vnet->tx_ring)) { pr_err("create ring failed"); - goto failure2; + goto bt_ring_create_failed; } vnet->ndev = bt_net_device_create(id); if (unlikely(!vnet->ndev)) { pr_err("create net device failed"); - goto failure3; + goto net_device_create_failed; } vnet->io_file = bt_get_io_file(bt_mng, id); if (unlikely(!vnet->io_file)) { pr_err("create cdev failed"); - goto failure4; + goto get_io_file_failed; } init_waitqueue_head(&vnet->rx_queue); @@ -1070,22 +1161,21 @@ static struct bt_virnet *bt_virnet_create(struct bt_drv *bt_mng, u32 id) SET_STATE(vnet, BT_VIRNET_STATE_CREATED); return vnet; -failure4: +get_io_file_failed: bt_net_device_destroy(vnet->ndev); -failure3: +net_device_create_failed: bt_ring_destroy(vnet->tx_ring); -failure2: +bt_ring_create_failed: kfree(vnet); -failure1: +out_of_memory: return NULL; } static void bt_virnet_destroy(struct bt_virnet *vnet) { - WARN_ON(!vnet); bt_ring_destroy(vnet->tx_ring); bt_net_device_destroy(vnet->ndev); @@ -1094,16 +1184,19 @@ static void bt_virnet_destroy(struct bt_virnet *vnet) kfree(vnet); } -static void bt_module_release(void) +static void __exit 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); + if (likely(bt_drv)) { + 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); + + kfree(bt_drv); + bt_drv = NULL; + } - kfree(bt_drv); - bt_drv = NULL; + bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); remove_proc_entry("bt_info_proc", NULL); } @@ -1112,47 +1205,48 @@ static void bt_module_release(void) */ static int __init bt_module_init(void) { - int mid; + int mid = 0; struct proc_dir_entry *entry = NULL; 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"); - goto failure1; + goto out_of_memory; } if (unlikely(bt_cdev_region_init(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM) < 0)) { pr_err("bt_cdev_region_init: failed"); - goto failure2; + goto cdev_region_failed; } bt_drv->devices_table = bt_table_init(); if (unlikely(!bt_drv->devices_table)) { pr_err("bt_table_init(): failed"); - goto failure2; + goto table_init_failed; } bt_drv->bt_class = bt_dev_class_create(); - if (IS_ERR(bt_drv->bt_class)) { + if (unlikely(!bt_drv->bt_class)) { pr_err("class create failed"); - goto failure3; + goto class_create_failed; } bt_drv->io_files = bt_create_io_files(); + if (unlikely(!bt_drv->io_files)) { + pr_err("bt_create_io_files: failed"); + goto io_files_create_failed; + } 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_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"); mutex_unlock(&bt_drv->bitmap_lock); - goto failure4; + goto mng_file_create_failed; } bt_set_bit(&bt_drv->bitmap, mid); mutex_unlock(&bt_drv->bitmap_lock); @@ -1160,24 +1254,30 @@ static int __init bt_module_init(void) entry = proc_create_data("bt_info_proc", 0, NULL, &bt_proc_fops, NULL); if (unlikely(!entry)) { pr_err("create proc data failed"); - goto failure5; + goto proc_create_failed; } return OK; -failure5: +proc_create_failed: bt_delete_mng_file(bt_drv->mng_file); -failure4: +mng_file_create_failed: + bt_delete_io_files(bt_drv); + +io_files_create_failed: bt_dev_class_destroy(bt_drv->bt_class); -failure3: +class_create_failed: bt_table_destroy(bt_drv); -failure2: +table_init_failed: + bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); + +cdev_region_failed: kfree(bt_drv); -failure1: +out_of_memory: return -1; } diff --git a/newip/src/linux-5.10/drivers/net/bt/btdev.h b/newip/src/linux-5.10/drivers/net/bt/btdev.h index 4c4d9654d42f261b52f907071f9a62607f5487d5..07a7c2ebdeb238ae4f2b968f997823999753c664 100644 --- a/newip/src/linux-5.10/drivers/net/bt/btdev.h +++ b/newip/src/linux-5.10/drivers/net/bt/btdev.h @@ -1,6 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. + * + * Description: Bluetooth virtual network device used in + * the NewIP over Bluetooth communication scenario. + * + * Author: Yang Yanjun + * + * Data: 2023-03-14 */ #ifndef _BTDEV_H_ @@ -46,7 +53,9 @@ #define STRTOLL_BASE 10 #define BT_DEV_ID_OFFSET (sizeof(BT_DEV_PATH_PREFIX) - 1) #define BT_STATISTIC_KTIME_MAX ULONG_MAX - +#define NEWIP_TYPE_SIZE 2 /* newip type eadd */ +#define BT_MAX_MTU 65535 +#define UNKNOWN_NAME "unknown" /** * for debug */ @@ -111,7 +120,6 @@ struct bt_virnet { 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; @@ -142,13 +150,12 @@ static const char *bt_virnet_state_rep[BT_VIRNET_STAET_NUM] = { /** * inline functions */ -static inline int bt_get_unused_id(const u32 *bitmap) +static inline int bt_get_unused_id(u32 bitmap) { int i; - WARN_ON(!bitmap); for (i = 0; i < BT_VIRNET_MAX_NUM + 1; ++i) { - if (!(*bitmap & (1 << i))) + if (!(bitmap & (1 << i))) return i; } return -1; // all used @@ -156,63 +163,73 @@ static inline int bt_get_unused_id(const u32 *bitmap) static inline void bt_set_bit(u32 *bitmap, u32 idx) { - WARN_ON(!bitmap); - *bitmap |= (1 << idx); + if (bitmap && idx <= BT_VIRNET_MAX_NUM) + *bitmap |= (1 << idx); } static inline void bt_clear_bit(u32 *bitmap, u32 idx) { - WARN_ON(!bitmap); - *bitmap &= ~(1 << idx); + if (bitmap && idx <= BT_VIRNET_MAX_NUM) + *bitmap &= ~(1 << idx); } #define SET_STATE(vn, st) bt_virnet_set_state(vn, st) static inline void bt_virnet_set_state(struct bt_virnet *vn, enum bt_virnet_state state) { - WARN_ON(!vn); vn->state = state; } static inline const struct cdev *bt_virnet_get_cdev(const struct bt_virnet *vn) { - WARN_ON(!vn); + if (unlikely(!vn->io_file) || unlikely(!vn->io_file->bt_cdev)) + return NULL; + return vn->io_file->bt_cdev->cdev; } -static inline const dev_t bt_virnet_get_cdev_number(const struct bt_virnet *vn) +static inline const int bt_virnet_get_cdev_number(const struct bt_virnet *vn, dev_t *number) { - WARN_ON(!vn); - return vn->io_file->bt_cdev->cdev->dev; + if (unlikely(!vn->io_file) || unlikely(!vn->io_file->bt_cdev) || + unlikely(!vn->io_file->bt_cdev->cdev) || unlikely(!number)) + return -EINVAL; + + *number = vn->io_file->bt_cdev->cdev->dev; + return OK; } static inline const char *bt_virnet_get_cdev_name(const struct bt_virnet *vn) { - WARN_ON(!vn); + if (unlikely(!vn->io_file) || unlikely(!vn->io_file->bt_cdev) || + unlikely(!vn->io_file->bt_cdev->dev_filename)) + return UNKNOWN_NAME; + return vn->io_file->bt_cdev->dev_filename; } static inline struct net_device *bt_virnet_get_ndev(const struct bt_virnet *vn) { - WARN_ON(!vn); return vn->ndev; } static inline const char *bt_virnet_get_ndev_name(const struct bt_virnet *vn) { - WARN_ON(!vn); + if (unlikely(!vn->ndev) || unlikely(!vn->ndev->name)) + return UNKNOWN_NAME; + return vn->ndev->name; } static inline const char *bt_virnet_get_state_rep(const struct bt_virnet *vn) { - WARN_ON(!vn); return bt_virnet_state_rep[vn->state]; } static inline int bt_get_total_device(const struct bt_drv *bt_drv) { - WARN_ON(!bt_drv); + if (unlikely(!bt_drv->devices_table)) + return -EINVAL; + return bt_drv->devices_table->num; } @@ -220,7 +237,10 @@ static inline int bt_virnet_get_ring_packets(const struct bt_virnet *vn) { int packets = 0; - WARN_ON(!vn); + if (unlikely(!vn->tx_ring) || unlikely(!vn->tx_ring->head) || + unlikely(!vn->tx_ring->tail)) + return -EINVAL; + packets = vn->tx_ring->head - vn->tx_ring->tail; if (unlikely(packets < 0)) packets += BT_RING_BUFFER_SIZE; @@ -231,7 +251,7 @@ static inline int bt_virnet_get_ring_packets(const struct bt_virnet *vn) 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 *bt_drv); +static int bt_table_delete_all(struct bt_drv *bt_drv); static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_name); static void bt_table_destroy(struct bt_drv *bt_drv); static void bt_delete_io_files(struct bt_drv *bt_mng);