From 0050a26b5be38184624e6ae7ddd34b3d6b493d8c Mon Sep 17 00:00:00 2001 From: yangyanjun Date: Fri, 16 Jun 2023 14:40:27 +0800 Subject: [PATCH] btdev code view problem modification, debug rectification 1. bt_io_file_write function call copy_from_user branch failure need to release skb. 2. The branch that bt_io_file_read fails to call copy_to_user needs to release skb, because skb has been unchained from ring buf. 3. The bt_cmd_peek_packet function only obtains the skb data length. After put_user fails, the skb does not need to be released. 4. The bt_cmd_create_virnet function bt_get_unused_id may return an invalid id, and add the if judgment that the id is less than 0. 5. The branch of bt_cmd_create_virnet function copy_to_user that fails needs to release bt_table_remove_device. 6. bt_table_add_device and bt_table_remove_device functions to tbl->num variable ++ and -- operation to increase the validity judgment, avoid flipping. 7. __bt_ring_create function if (unlikely(size < 0)) branch has memory leaks, modified to determine the validity of the input parameter, and then apply for memory. 8. Both bt_ring_is_empty and bt_ring_is_full return true for invalid branches. 9. bt_virnet_produce_data adds a memory barrier before and after calling bt_ring_produce, and bt_ring_produce already has a memory barrier. Delete the redundant memory barrier. 10. The vnet->tx_queue variable is a redundant operation and has no practical effect. Delete all codes corresponding to the variable to improve the efficiency of receiving and sending packets on the btdev virtual device. bt_virnet_create deletes init_waitqueue_head(&vnet->tx_queue); bt_io_file_poll deletes poll_wait(filp, &vnet->tx_queue, wait); 11. Change the global variable name to g_xxx 12. atomic operation process xx_open_limit variable value changes add annotation 13. debug rectification, the normal path is closed by default (shell can be opened), and the abnormal path is opened by default. At the same time, key information such as btdev interface name printing and data length are added to the interface open, delete, and packet sending functions. Signed-off-by: yangyanjun --- newip/src/linux-5.10/drivers/net/bt/btdev.c | 458 +++++++++++--------- newip/src/linux-5.10/drivers/net/bt/btdev.h | 15 +- 2 files changed, 265 insertions(+), 208 deletions(-) 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 446d207..0a99291 100644 --- a/newip/src/linux-5.10/drivers/net/bt/btdev.c +++ b/newip/src/linux-5.10/drivers/net/bt/btdev.c @@ -10,26 +10,43 @@ * Data: 2023-03-14 */ +#define pr_fmt(fmt) "newip-bt: [%s:%d] " fmt, __func__, __LINE__ + #include "btdev.h" -static struct bt_drv *bt_drv; +#define NDEV_NAME(vnet) bt_virnet_get_ndev_name(vnet) /* btn1/2/3/4/... */ +#define CDEV_NAME(vnet) bt_virnet_get_cdev_name(vnet) /* dev/btdev1/2/3/4/... */ + +/* /sys/module/btdev/parameters/btdev_debug */ +bool g_btdev_debug; +module_param_named(btdev_debug, g_btdev_debug, bool, 0644); + +#define BTDEV_DBG(fmt, ...) \ +do { \ + if (g_btdev_debug) \ + pr_crit(fmt, ##__VA_ARGS__); \ +} while (0) + +#define BTDEV_DBG_ERR(fmt, ...) pr_err(fmt, ##__VA_ARGS__) + +static struct bt_drv *g_bt_drv; 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"); + if (unlikely(!g_bt_drv)) { + BTDEV_DBG_ERR("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, + bt_get_total_device(g_bt_drv), g_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), + list_for_each_entry(vnet, &g_bt_drv->devices_table->head, virnet_entry) { + seq_printf(m, "dev: %12s, interface: %7s, state: %12s, MTU: %4d\n", + CDEV_NAME(vnet), 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, @@ -41,16 +58,15 @@ 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"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } return single_open(file, bt_seq_show, PDE_DATA(inode)); } -static struct proc_ops bt_proc_fops = { +static struct proc_ops g_bt_proc_fops = { .proc_open = bt_proc_open, .proc_read = seq_read, .proc_lseek = seq_lseek, @@ -61,22 +77,22 @@ 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))) + /* Check whether xx_open_limit is equal to 0 after subtracting 1. + * If so, return true + */ + 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))) + 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))) + 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))) + if (unlikely(!atomic_dec_and_test(&vnet->io_file->write_open_limit))) goto write_twice_already; } + /* Set xx_open_limit to 0 when the file is first opened */ rtnl_lock(); ndev = vnet->ndev; if (unlikely(!(ndev->flags & IFF_UP))) { @@ -84,7 +100,7 @@ static int __bt_virnet_open(struct file *filp, struct bt_virnet *vnet) if (unlikely(ret < 0)) { rtnl_unlock(); - pr_err("bt dev_change_flags error: ret=%d", ret); + BTDEV_DBG_ERR("%s dev change flags failed, ret=%d", CDEV_NAME(vnet), ret); return -EBUSY; } } @@ -92,18 +108,20 @@ static int __bt_virnet_open(struct file *filp, struct bt_virnet *vnet) SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); filp->private_data = vnet; + BTDEV_DBG("%s has been opened", CDEV_NAME(vnet)); return OK; + /* If the file is not opened for the first time, an error occurs + * and xx_open_limit is restored to the open state. (set to 0) + */ 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)); + BTDEV_DBG_ERR("%s has been opened for read twice already", 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)); + BTDEV_DBG_ERR("%s has been opened for write twice already", CDEV_NAME(vnet)); return -EBUSY; } @@ -112,13 +130,11 @@ static int bt_io_file_open(struct inode *node, struct file *filp) struct bt_virnet *vnet = NULL; if (unlikely(!node) || unlikely(!filp)) { - pr_err("bt io file open: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } - pr_devel("bt io file open called"); - - list_for_each_entry(vnet, &bt_drv->devices_table->head, virnet_entry) { + list_for_each_entry(vnet, &g_bt_drv->devices_table->head, virnet_entry) { if (bt_virnet_get_cdev(vnet) == node->i_cdev) return __bt_virnet_open(filp, vnet); } @@ -130,13 +146,14 @@ static int bt_io_file_release(struct inode *node, struct file *filp) struct bt_virnet *vnet = NULL; if (unlikely(!filp) || unlikely(!filp->private_data)) { - pr_err("bt io file release: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } vnet = filp->private_data; - pr_devel("bt io file release called"); + BTDEV_DBG("%s has been released", CDEV_NAME(vnet)); + /* Set xx_open_limit to 1 when the file is closed */ 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) { @@ -159,45 +176,52 @@ 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"); - if (unlikely(!filp) || unlikely(!buffer) || unlikely(!filp->private_data)) { - pr_devel("bt io file read: invalid parameter"); + BTDEV_DBG_ERR("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; - if (wait_event_interruptible(vnet->rx_queue, - !bt_ring_is_empty(vnet->tx_ring))) + if (wait_event_interruptible(vnet->rx_queue, !bt_ring_is_empty(vnet->tx_ring))) return -ERESTARTSYS; } skb = bt_ring_current(vnet->tx_ring); if (unlikely(!skb)) { - pr_devel("bt io file read: invalid skb"); + BTDEV_DBG_ERR("%s invalid skb", CDEV_NAME(vnet)); 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", - (long)out_sz, (long)size); + /* Obtain the skb pointer from the ring buf and ask whether the user-state buf + * length can store data in the skb. If the user-state buf length is not enough, + * the skb cannot be released at this time, because the skb is still unchained + * on the ring buf. + */ + BTDEV_DBG_ERR("%s usr-buf too small, skb-len=%ld, usr-buf-len=%ld", + CDEV_NAME(vnet), (long)out_sz, (long)size); return -EINVAL; } bt_ring_consume(vnet->tx_ring); if (copy_to_user(buffer, skb->data + MACADDR_LEN, out_sz)) { - pr_err("io file read: copy_to_user failed"); + /* The skb pointer is obtained from the ring buf and the skb has been unchained + * from the ring buf. In this case, the skb needs to be released when the skb data + * fails to be copied to the user mode. + */ + BTDEV_DBG_ERR("%s copy to user failed", CDEV_NAME(vnet)); + dev_kfree_skb(skb); return -EIO; } - dev_kfree_skb(skb); - skb = NULL; + BTDEV_DBG("read %ld data from %s", (long)out_sz, CDEV_NAME(vnet)); if (unlikely(netif_queue_stopped(vnet->ndev))) { - pr_devel("consume data: wake the queue"); + BTDEV_DBG("consume data: wake the queue"); netif_wake_queue(vnet->ndev); } @@ -215,13 +239,14 @@ static ssize_t bt_io_file_write(struct file *filp, ssize_t in_sz; if (unlikely(!filp) || unlikely(!buffer) || unlikely(!filp->private_data)) { - pr_err("bt io file write: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } - pr_devel("bt io file write called: %lu bytes", size); + vnet = filp->private_data; in_sz = size + MACADDR_LEN; + /* Ethernet head length: DMAC(6B) + SMAC(6B) + eth-type(2B) */ skb = netdev_alloc_skb(bt_virnet_get_ndev(vnet), in_sz + NEWIP_TYPE_SIZE); if (unlikely(!skb)) return -ENOMEM; @@ -230,8 +255,11 @@ static ssize_t bt_io_file_write(struct file *filp, skb_put(skb, in_sz); memset(skb->data, 0, MACADDR_LEN); - if (copy_from_user(skb->data + MACADDR_LEN, buffer, size)) + if (copy_from_user(skb->data + MACADDR_LEN, buffer, size)) { + BTDEV_DBG_ERR("%s copy from user failed", CDEV_NAME(vnet)); + dev_kfree_skb(skb); return -EIO; + } len = skb->len; skb->dev = bt_virnet_get_ndev(vnet); @@ -239,9 +267,11 @@ static ssize_t bt_io_file_write(struct file *filp, ret = netif_rx_ni(skb); if (ret == NET_RX_SUCCESS) { + BTDEV_DBG("write %lu bytes data to %s", size, CDEV_NAME(vnet)); vnet->ndev->stats.rx_packets++; vnet->ndev->stats.rx_bytes += len; } else { + BTDEV_DBG_ERR("failed to write %lu bytes data to %s", size, CDEV_NAME(vnet)); vnet->ndev->stats.rx_errors++; vnet->ndev->stats.rx_dropped++; } @@ -252,10 +282,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"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } - pr_devel("bt virnet change mtu called"); + BTDEV_DBG("change %s mtu %u to %u", dev->name, dev->mtu, mtu); dev->mtu = mtu; return OK; } @@ -265,16 +295,17 @@ 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"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } - pr_devel("bt set_mtu called"); + 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(); + if (err < 0) + BTDEV_DBG_ERR("failed to set %s mtu to %d, err=%d", dev->name, mtu, err); + else + BTDEV_DBG("set %s mtu to %d", dev->name, mtu); return err; } @@ -284,19 +315,19 @@ static int bt_cmd_enable_virnet(struct bt_virnet *vnet, unsigned long arg) int ret; if (unlikely(vnet->state != BT_VIRNET_STATE_DISABLED)) { - pr_err("bt enable can only be set at DISABLED state"); + BTDEV_DBG_ERR("%s enable can only be set at disabled state", CDEV_NAME(vnet)); return -EINVAL; // enable failed } rtnl_lock(); ret = dev_change_flags(vnet->ndev, vnet->ndev->flags | IFF_UP, NULL); + rtnl_unlock(); if (unlikely(ret < 0)) { - rtnl_unlock(); - pr_err("bt cmd enable virnet: dev_change_flags error: ret=%d", ret); + BTDEV_DBG_ERR("%s dev change flags failed, ret=%d", CDEV_NAME(vnet), ret); return -EIO; } - rtnl_unlock(); + BTDEV_DBG("%s has been enabled", CDEV_NAME(vnet)); SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); return OK; } @@ -306,19 +337,19 @@ static int bt_cmd_disable_virnet(struct bt_virnet *vnet, unsigned long arg) int ret; if (unlikely(vnet->state != BT_VIRNET_STATE_CONNECTED)) { - pr_err("bt disable can only be set at CONNECTED state"); + BTDEV_DBG_ERR("%s disable can only be set at connected state", CDEV_NAME(vnet)); return -EINVAL; } rtnl_lock(); ret = dev_change_flags(vnet->ndev, vnet->ndev->flags & ~IFF_UP, NULL); + rtnl_unlock(); if (unlikely(ret < 0)) { - rtnl_unlock(); - pr_err("bt cmd disable virnet: dev_change_flags error: ret=%d", ret); + BTDEV_DBG_ERR("%s dev change flags failed, ret=%d", CDEV_NAME(vnet), ret); return -EIO; } - rtnl_unlock(); + BTDEV_DBG("%s has been disabled", CDEV_NAME(vnet)); SET_STATE(vnet, BT_VIRNET_STATE_DISABLED); return OK; } @@ -329,36 +360,46 @@ static int bt_cmd_change_mtu(struct bt_virnet *vnet, unsigned long arg) int ret; if (unlikely(get_user(mtu, (int __user *)arg))) { - pr_err("get_user failed"); + BTDEV_DBG_ERR("%s get user failed", NDEV_NAME(vnet)); return -EIO; } ret = bt_set_mtu(vnet->ndev, mtu); - if (unlikely(ret < 0)) { - pr_err("bt_dev_ioctl: changed mtu failed"); + BTDEV_DBG_ERR("%s changed mtu to %d failed", NDEV_NAME(vnet), mtu); return -EIO; } + + BTDEV_DBG("%s changed mtu to %d", NDEV_NAME(vnet), mtu); 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"); + u32 len; + struct sk_buff *skb; if (unlikely(bt_ring_is_empty(vnet->tx_ring))) { - pr_err("bt peek packet ring is empty"); + BTDEV_DBG_ERR("%s ring is empty", NDEV_NAME(vnet)); return -EAGAIN; } + /* The user state retrieves the data length from the ring buf, rather than + * unchain the skb from the ring buf, so there is no need to release the skb + */ skb = bt_ring_current(vnet->tx_ring); - if (unlikely(put_user(skb->len - MACADDR_LEN, (int __user *)arg))) { - pr_err("put_user failed"); + if (unlikely(!skb)) { + BTDEV_DBG_ERR("%s invalid skb", NDEV_NAME(vnet)); + return -EINVAL; + } + + len = skb->len - MACADDR_LEN; + if (unlikely(put_user(len, (int __user *)arg))) { + BTDEV_DBG_ERR("%s put_user failed", NDEV_NAME(vnet)); return -EIO; } + BTDEV_DBG("%s get packet len is %u", NDEV_NAME(vnet), len); return OK; } @@ -370,11 +411,10 @@ static long bt_io_file_ioctl(struct file *filep, struct bt_virnet *vnet = NULL; if (unlikely(!filep) || unlikely(!filep->private_data)) { - pr_err("bt io file ioctl: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } vnet = filep->private_data; - pr_devel("bt io file ioctl called"); switch (cmd) { case BT_IOC_CHANGE_MTU: ret = bt_cmd_change_mtu(vnet, arg); @@ -389,7 +429,7 @@ static long bt_io_file_ioctl(struct file *filep, ret = bt_cmd_peek_packet(vnet, arg); break; default: - pr_err("not a valid cmd"); + BTDEV_DBG_ERR("not a valid cmd(%u)", cmd); return -ENOIOCTLCMD; } @@ -402,12 +442,11 @@ static unsigned int bt_io_file_poll(struct file *filp, poll_table *wait) unsigned int mask = 0; if (unlikely(!filp) || unlikely(!wait) || unlikely(!filp->private_data)) { - pr_err("bt io file poll: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } vnet = filp->private_data; 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; @@ -418,7 +457,7 @@ static unsigned int bt_io_file_poll(struct file *filp, poll_table *wait) return mask; } -static const struct file_operations bt_io_file_ops = { +static const struct file_operations g_bt_io_file_ops = { .owner = THIS_MODULE, .open = bt_io_file_open, .release = bt_io_file_release, @@ -430,20 +469,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"); - if (unlikely(!filp)) { - pr_err("bt mng file open: invalid filp"); + BTDEV_DBG_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", - bt_drv->mng_file->bt_cdev->dev_filename); + /* Check whether open_limit is equal to 0 after subtracting 1. If so, return true */ + if (unlikely(!atomic_dec_and_test(&g_bt_drv->mng_file->open_limit))) { + /* If the file is not opened for the first time, an error occurs + * and open_limit is restored to the open state. (set to 0) + */ + atomic_inc(&g_bt_drv->mng_file->open_limit); + BTDEV_DBG_ERR("file %s has been opened already", + g_bt_drv->mng_file->bt_cdev->dev_filename); return -EBUSY; } - filp->private_data = bt_drv; + + /* open_limit becomes 0 after the file is first opened */ + filp->private_data = g_bt_drv; + + BTDEV_DBG("%s has been opened", g_bt_drv->mng_file->bt_cdev->dev_filename); return OK; } @@ -452,13 +497,15 @@ static int bt_mng_file_release(struct inode *node, struct file *filp) struct bt_drv *drv = NULL; if (unlikely(!filp) || unlikely(!filp->private_data)) { - pr_err("bt mng file release: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } drv = filp->private_data; - pr_devel("bt mng file release called"); + /* Set open_limit to 1 when the file is closed */ atomic_inc(&drv->mng_file->open_limit); + + BTDEV_DBG("%s has been released", g_bt_drv->mng_file->bt_cdev->dev_filename); return OK; } @@ -472,43 +519,44 @@ 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_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"); + if ((unlikely(bt_mng->devices_table->num >= BT_VIRNET_MAX_NUM)) || + (unlikely(id < 0))) { + BTDEV_DBG_ERR("reach the limit of max virnets"); goto virnet_create_failed; } vnet = bt_virnet_create(bt_mng, id); if (unlikely(!vnet)) { - pr_err("bt virnet create failed"); + BTDEV_DBG_ERR("bt virnet create failed"); goto virnet_create_failed; } ret = bt_table_add_device(bt_mng->devices_table, vnet); if (unlikely(ret < 0)) { - pr_err("bt table add device failed: ret=%d", ret); + BTDEV_DBG_ERR("bt table add device failed: ret=%d", ret); goto add_device_failed; } 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)); + memcpy(vp.ifa_name, NDEV_NAME(vnet), sizeof(vp.ifa_name)); + memcpy(vp.cfile_name, CDEV_NAME(vnet), sizeof(vp.cfile_name)); 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); + BTDEV_DBG_ERR("copy_to_user failed: left size=%lu", size); goto copy_to_user_failed; } + + BTDEV_DBG("%s has been created", NDEV_NAME(vnet)); return OK; copy_to_user_failed: mutex_lock(&bt_mng->bitmap_lock); + bt_table_remove_device(bt_mng->devices_table, vnet); bt_clear_bit(&bt_mng->bitmap, id); add_device_failed: @@ -530,16 +578,17 @@ static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) 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); + BTDEV_DBG_ERR("copy_from_user failed: left size=%lu", size); 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); + BTDEV_DBG_ERR("virnet: %s cannot be found in bt table", vp.ifa_name); return -EIO; // not found } + BTDEV_DBG("%s has been deleted", NDEV_NAME(vnet)); mutex_lock(&bt_mng->bitmap_lock); err = bt_virnet_get_cdev_number(vnet, &number); if (likely(!err)) @@ -553,7 +602,7 @@ static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) static int bt_cmd_query_all_virnets(struct bt_drv *bt_mng, unsigned long arg) { if (unlikely(put_user(bt_mng->bitmap, (u32 *)arg))) { - pr_err("put_user failed"); + BTDEV_DBG_ERR("put_user failed"); return -EIO; } return OK; @@ -572,11 +621,11 @@ static long bt_mng_file_ioctl(struct file *filep, struct bt_drv *bt_mng = NULL; if (unlikely(!filep) || unlikely(!filep->private_data)) { - pr_err("bt mng file ioctl: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } bt_mng = filep->private_data; - pr_devel("bt mng file ioctl called"); + switch (cmd) { case BT_IOC_CREATE: ret = bt_cmd_create_virnet(bt_mng, arg); @@ -591,13 +640,13 @@ static long bt_mng_file_ioctl(struct file *filep, ret = bt_cmd_delete_all_virnets(bt_mng, arg); break; default: - pr_err("not a valid command"); + BTDEV_DBG_ERR("not a valid cmd(%u)", cmd); return -ENOIOCTLCMD; } return ret; } -static const struct file_operations bt_mng_file_ops = { +static const struct file_operations g_bt_mng_file_ops = { .owner = THIS_MODULE, .open = bt_mng_file_open, .release = bt_mng_file_release, @@ -611,21 +660,21 @@ static netdev_tx_t bt_virnet_xmit(struct sk_buff *skb, struct bt_virnet *vnet = NULL; if (unlikely(!skb) || unlikely(!dev)) { - pr_err("virnet xmit: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } - pr_alert("alert: bt virnet_xmit: called"); - vnet = bt_table_find(bt_drv->devices_table, dev->name); + vnet = bt_table_find(g_bt_drv->devices_table, dev->name); if (unlikely(!vnet)) { - pr_err("virnet xmit: bt_table_find failed"); + BTDEV_DBG_ERR("bt_table_find %s failed", NDEV_NAME(vnet)); return -EINVAL; } ret = bt_virnet_produce_data(vnet, (void *)skb); if (unlikely(ret < 0)) { - pr_devel("virnet xmit: produce data failed: ring is full, need to stop queue"); + BTDEV_DBG("%s produce data failed: ring is full, need to stop queue", + NDEV_NAME(vnet)); netif_stop_queue(vnet->ndev); return NETDEV_TX_BUSY; } @@ -633,10 +682,11 @@ static netdev_tx_t bt_virnet_xmit(struct sk_buff *skb, vnet->ndev->stats.tx_packets++; vnet->ndev->stats.tx_bytes += skb->len; + BTDEV_DBG("%s send success, skb-len=%u", NDEV_NAME(vnet), skb->len); return NETDEV_TX_OK; } -static const struct net_device_ops bt_virnet_ops = { +static const struct net_device_ops g_bt_virnet_ops = { .ndo_start_xmit = bt_virnet_xmit, .ndo_change_mtu = bt_virnet_change_mtu}; @@ -645,7 +695,7 @@ static struct bt_table *bt_table_init(void) struct bt_table *tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); if (unlikely(!tbl)) { - pr_err("alloc struct bt_table failed: oom"); + BTDEV_DBG_ERR("alloc failed"); return NULL; } @@ -660,19 +710,21 @@ static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn) struct bt_virnet *vnet = NULL; if (unlikely(!tbl)) { - pr_err("bt table add device: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return -EINVAL; } - vnet = bt_table_find(tbl, bt_virnet_get_ndev_name(vn)); + vnet = bt_table_find(tbl, NDEV_NAME(vn)); if (unlikely(vnet)) { - pr_err("found duplicated device"); + BTDEV_DBG_ERR("found duplicated device %s", NDEV_NAME(vn)); return -ENOIOCTLCMD; // duplicated } + BTDEV_DBG("%s has been added", NDEV_NAME(vn)); mutex_lock(&tbl->tbl_lock); list_add_tail(&vn->virnet_entry, &tbl->head); - ++tbl->num; + if (tbl->num < UINT32_MAX) + ++tbl->num; mutex_unlock(&tbl->tbl_lock); return OK; @@ -683,9 +735,11 @@ static void bt_table_remove_device(struct bt_table *tbl, struct bt_virnet *vn) if (unlikely(!tbl)) return; + BTDEV_DBG("%s has been removed", NDEV_NAME(vn)); mutex_lock(&tbl->tbl_lock); list_del(&vn->virnet_entry); - --tbl->num; + if (tbl->num) + --tbl->num; mutex_unlock(&tbl->tbl_lock); } @@ -694,14 +748,15 @@ static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_nam struct bt_virnet *vnet = NULL; if (unlikely(!tbl) || unlikely(!ifa_name)) { - pr_err("bt table find: invalid parameter"); + BTDEV_DBG_ERR("invalid parameter"); return NULL; } list_for_each_entry(vnet, &tbl->head, virnet_entry) { - if (!strcmp(bt_virnet_get_ndev_name(vnet), ifa_name)) + if (!strcmp(NDEV_NAME(vnet), ifa_name)) return vnet; } + return NULL; } @@ -711,7 +766,7 @@ static void __bt_table_delete_all(struct bt_drv *drv) dev_t number; struct bt_virnet *vnet = NULL, *tmp_vnet = NULL; - if (unlikely(!bt_drv->devices_table)) + if (unlikely(!g_bt_drv->devices_table)) return; list_for_each_entry_safe(vnet, @@ -722,6 +777,7 @@ static void __bt_table_delete_all(struct bt_drv *drv) if (likely(!err)) bt_clear_bit(&drv->bitmap, (u32)MINOR(number)); list_del(&vnet->virnet_entry); + BTDEV_DBG("%s has been deleted", NDEV_NAME(vnet)); bt_virnet_destroy(vnet); } drv->devices_table->num = 0; @@ -751,21 +807,22 @@ static void bt_table_destroy(struct bt_drv *drv) 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"); - return NULL; - } + struct bt_ring *ring; if (unlikely(size < 0)) return NULL; + ring = kmalloc(sizeof(*ring), GFP_KERNEL); + if (unlikely(!ring)) { + BTDEV_DBG_ERR("ring alloc failed"); + 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"); + BTDEV_DBG_ERR("ring data allocfailed"); kfree(ring); return NULL; } @@ -782,7 +839,7 @@ static struct bt_ring *bt_ring_create(void) static int bt_ring_is_empty(const struct bt_ring *ring) { if (unlikely(!ring)) - return -EINVAL; + return TRUE; return ring->head == ring->tail; } @@ -790,7 +847,7 @@ static int bt_ring_is_empty(const struct bt_ring *ring) static int bt_ring_is_full(const struct bt_ring *ring) { if (unlikely(!ring)) - return -EINVAL; + return TRUE; return (ring->head + 1) % ring->size == ring->tail; } @@ -836,14 +893,12 @@ static void bt_ring_destroy(struct bt_ring *ring) static int bt_virnet_produce_data(struct bt_virnet *dev, void *data) { if (unlikely(bt_ring_is_full(dev->tx_ring))) { - pr_devel("ring is full"); + BTDEV_DBG("ring is full"); return -ENFILE; } - smp_wmb(); // Make sure the write order is correct + /* There is a memory barrier inside the function */ bt_ring_produce(dev->tx_ring, data); - smp_wmb(); // Make sure twrite order is correct - wake_up(&dev->rx_queue); return OK; } @@ -861,7 +916,7 @@ static struct class *bt_dev_class_create(void) struct class *cls = class_create(THIS_MODULE, "bt"); if (IS_ERR(cls)) { - pr_err("create struct class failed"); + BTDEV_DBG_ERR("create struct class failed"); return NULL; } return cls; @@ -889,26 +944,25 @@ static int bt_cdev_device_create(struct bt_cdev *dev, int ret; if (unlikely(!cls)) { - pr_err("not a valid cls"); + BTDEV_DBG_ERR("not a valid class"); return -EINVAL; } - 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"); + BTDEV_DBG_ERR("create device failed, id=%d", id); return -EIO; } ret = snprintf(dev->dev_filename, sizeof(dev->dev_filename), "%s%u", BT_DEV_PATH_PREFIX, id); if (ret < 0) { - pr_devel("bt cdev device create: snprintf failed\n"); + BTDEV_DBG_ERR("snprintf failed, id=%d", id); bt_cdev_device_destroy(dev); return -EFAULT; } + + BTDEV_DBG("%s has been created", dev->dev_filename); return OK; } @@ -920,17 +974,15 @@ static struct bt_cdev *bt_cdev_create(const struct file_operations *ops, struct bt_cdev *dev = NULL; struct cdev *chrdev = NULL; - pr_devel("bt cdev create called"); - dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (unlikely(!dev)) { - pr_err("bt cdev_create alloc failed: oom"); + BTDEV_DBG_ERR("dev alloc failed, id=%d", id); goto dev_alloc_failed; } chrdev = cdev_alloc(); if (unlikely(!chrdev)) { - pr_err("bt cdev_create: cdev_alloc() failed: oom"); + BTDEV_DBG_ERR("cdev alloc failed, id=%d", id); goto cdev_alloc_failed; } @@ -939,14 +991,15 @@ 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"); + BTDEV_DBG_ERR("cdev add failed, id=%d", id); goto cdev_add_failed; } - if (unlikely(bt_cdev_device_create(dev, bt_drv->bt_class, minor) < 0)) { - pr_err("bt cdev_device_create failed"); + if (unlikely(bt_cdev_device_create(dev, g_bt_drv->bt_class, minor) < 0)) { + BTDEV_DBG_ERR("bt cdev device create failed, id=%d", id); goto cdev_device_create_failed; } + return dev; cdev_device_create_failed: @@ -970,13 +1023,13 @@ static void bt_cdev_delete(struct bt_cdev *bt_cdev) if (likely(bt_cdev)) { devno = bt_cdev->cdev->dev; - /* BT_DEV_PATH_PREFIX + ID --> /dev/btn1 */ + /* BT_DEV_PATH_PREFIX + ID --> /dev/btdev1 */ 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"); + BTDEV_DBG_ERR("cdev is null"); } } @@ -988,12 +1041,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"); + BTDEV_DBG_ERR("file alloc failed, id=%d", id); return NULL; } - file->bt_cdev = bt_cdev_create(&bt_io_file_ops, id); + file->bt_cdev = bt_cdev_create(&g_bt_io_file_ops, id); if (unlikely(!file->bt_cdev)) { - pr_err("bt create_io_file: create cdev failed"); + BTDEV_DBG_ERR("create cdev failed, id=%d", id); kfree(file); return NULL; } @@ -1009,7 +1062,7 @@ static struct bt_io_file **bt_create_io_files(void) GFP_KERNEL); if (unlikely(!all_files)) { - pr_err("bt create_io_files alloc failed: oom"); + BTDEV_DBG_ERR("all_files alloc failed"); return NULL; } for (i = 0; i < BT_VIRNET_MAX_NUM; ++i) @@ -1046,19 +1099,20 @@ 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"); + BTDEV_DBG_ERR("file alloc failed"); return NULL; } - file->bt_cdev = bt_cdev_create(&bt_mng_file_ops, id); + file->bt_cdev = bt_cdev_create(&g_bt_mng_file_ops, id); if (unlikely(!file->bt_cdev)) { - pr_err("bt create_mng_file: create cdev failed"); + BTDEV_DBG_ERR("create cdev failed"); kfree(file); return NULL; } atomic_set(&file->open_limit, 1); + BTDEV_DBG("mng file has been created"); return file; } @@ -1089,21 +1143,21 @@ static struct net_device *bt_net_device_create(u32 id) char ifa_name[IFNAMSIZ]; if (unlikely(id < 0) || unlikely(id > BT_VIRNET_MAX_NUM)) { - pr_err("bt net device create: invalid id"); + BTDEV_DBG_ERR("invalid id"); return NULL; } err = snprintf(ifa_name, sizeof(ifa_name), "%s%d", BT_VIRNET_NAME_PREFIX, id); if (err < 0) { - pr_err("bt net device create: snprintf failed"); + BTDEV_DBG_ERR("snprintf failed, id=%d", id); return NULL; } ndev = alloc_netdev(0, ifa_name, NET_NAME_UNKNOWN, ether_setup); if (unlikely(!ndev)) { - pr_err("alloc_netdev failed"); + BTDEV_DBG_ERR("%s ndev alloc failed", ifa_name); return NULL; } - ndev->netdev_ops = &bt_virnet_ops; + ndev->netdev_ops = &g_bt_virnet_ops; ndev->flags |= IFF_NOARP; ndev->flags &= ~IFF_BROADCAST & ~IFF_MULTICAST; ndev->min_mtu = 1; @@ -1111,11 +1165,12 @@ static struct net_device *bt_net_device_create(u32 id) err = register_netdev(ndev); if (unlikely(err)) { - pr_err("create net_device failed"); + BTDEV_DBG_ERR("%s register netdev failed", ifa_name); free_netdev(ndev); return NULL; } + BTDEV_DBG("%s has been created", ifa_name); return ndev; } @@ -1124,6 +1179,7 @@ static struct net_device *bt_net_device_create(u32 id) */ static void bt_net_device_destroy(struct net_device *dev) { + BTDEV_DBG("%s has been destroyed", dev->name); unregister_netdev(dev); free_netdev(dev); } @@ -1144,32 +1200,32 @@ 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"); + BTDEV_DBG_ERR("invalid parameter"); goto out_of_memory; } vnet->tx_ring = bt_ring_create(); if (unlikely(!vnet->tx_ring)) { - pr_err("create ring failed"); + BTDEV_DBG_ERR("create ring failed"); goto bt_ring_create_failed; } vnet->ndev = bt_net_device_create(id); if (unlikely(!vnet->ndev)) { - pr_err("create net device failed"); + BTDEV_DBG_ERR("create net device failed"); 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"); + BTDEV_DBG_ERR("create cdev failed"); goto get_io_file_failed; } init_waitqueue_head(&vnet->rx_queue); - init_waitqueue_head(&vnet->tx_queue); SET_STATE(vnet, BT_VIRNET_STATE_CREATED); + BTDEV_DBG("%s has been created", CDEV_NAME(vnet)); return vnet; get_io_file_failed: @@ -1187,6 +1243,7 @@ out_of_memory: static void bt_virnet_destroy(struct bt_virnet *vnet) { + BTDEV_DBG("%s has been destroyed", NDEV_NAME(vnet)); bt_ring_destroy(vnet->tx_ring); bt_net_device_destroy(vnet->ndev); @@ -1197,18 +1254,19 @@ static void bt_virnet_destroy(struct bt_virnet *vnet) static void __exit bt_module_release(void) { - 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); + if (likely(g_bt_drv)) { + bt_table_destroy(g_bt_drv); + bt_delete_io_files(g_bt_drv); + bt_delete_mng_file(g_bt_drv->mng_file); + bt_dev_class_destroy(g_bt_drv->bt_class); - kfree(bt_drv); - bt_drv = NULL; + kfree(g_bt_drv); + g_bt_drv = NULL; } bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); remove_proc_entry("bt_info_proc", NULL); + BTDEV_DBG("success"); } /** @@ -1219,74 +1277,74 @@ static int __init bt_module_init(void) 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"); + g_bt_drv = kmalloc(sizeof(*g_bt_drv), GFP_KERNEL); + if (unlikely(!g_bt_drv)) { + BTDEV_DBG_ERR("bt_drv alloc failed"); 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"); + BTDEV_DBG_ERR("bt cdev region init failed"); goto cdev_region_failed; } - bt_drv->devices_table = bt_table_init(); - if (unlikely(!bt_drv->devices_table)) { - pr_err("bt_table_init(): failed"); + g_bt_drv->devices_table = bt_table_init(); + if (unlikely(!g_bt_drv->devices_table)) { + BTDEV_DBG_ERR("bt table init failed"); goto table_init_failed; } - bt_drv->bt_class = bt_dev_class_create(); - if (unlikely(!bt_drv->bt_class)) { - pr_err("class create failed"); + g_bt_drv->bt_class = bt_dev_class_create(); + if (unlikely(!g_bt_drv->bt_class)) { + BTDEV_DBG_ERR("class create failed"); 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"); + g_bt_drv->io_files = bt_create_io_files(); + if (unlikely(!g_bt_drv->io_files)) { + BTDEV_DBG_ERR("bt create io files failed"); goto io_files_create_failed; } - mutex_init(&bt_drv->bitmap_lock); - bt_drv->bitmap = 0; + mutex_init(&g_bt_drv->bitmap_lock); + g_bt_drv->bitmap = 0; - mutex_lock(&bt_drv->bitmap_lock); - 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); + mutex_lock(&g_bt_drv->bitmap_lock); + g_bt_drv->mng_file = bt_create_mng_file(mid); + if (unlikely(!g_bt_drv->mng_file)) { + BTDEV_DBG_ERR("bt create mng file failed"); + mutex_unlock(&g_bt_drv->bitmap_lock); goto mng_file_create_failed; } - bt_set_bit(&bt_drv->bitmap, mid); - mutex_unlock(&bt_drv->bitmap_lock); + bt_set_bit(&g_bt_drv->bitmap, mid); + mutex_unlock(&g_bt_drv->bitmap_lock); - entry = proc_create_data("bt_info_proc", 0, NULL, &bt_proc_fops, NULL); + entry = proc_create_data("bt_info_proc", 0, NULL, &g_bt_proc_fops, NULL); if (unlikely(!entry)) { - pr_err("create proc data failed"); + BTDEV_DBG_ERR("create proc data failed"); goto proc_create_failed; } + BTDEV_DBG("success"); return OK; proc_create_failed: - bt_delete_mng_file(bt_drv->mng_file); + bt_delete_mng_file(g_bt_drv->mng_file); mng_file_create_failed: - bt_delete_io_files(bt_drv); + bt_delete_io_files(g_bt_drv); io_files_create_failed: - bt_dev_class_destroy(bt_drv->bt_class); + bt_dev_class_destroy(g_bt_drv->bt_class); class_create_failed: - bt_table_destroy(bt_drv); + bt_table_destroy(g_bt_drv); table_init_failed: bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); cdev_region_failed: - kfree(bt_drv); + kfree(g_bt_drv); 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 2122b1b..92b4262 100644 --- a/newip/src/linux-5.10/drivers/net/bt/btdev.h +++ b/newip/src/linux-5.10/drivers/net/bt/btdev.h @@ -39,11 +39,14 @@ #include #include #include +#include /* must include btdev_user.h first before any macro definition */ #include "btdev_user.h" #define OK 0 +#define TRUE 1 +#define FALSE 0 #define DELAY_100_MS 100 #define MACADDR_LEN (2 * ETH_ALEN) @@ -56,10 +59,6 @@ #define NEWIP_TYPE_SIZE 2 /* newip type eadd */ #define BT_MAX_MTU 65535 #define UNKNOWN_NAME "unknown" -/** - * for debug - */ -#define DEBUG /** * ring buffer @@ -122,7 +121,7 @@ struct bt_virnet { struct list_head virnet_entry; enum bt_virnet_state state; struct semaphore sem; - wait_queue_head_t rx_queue, tx_queue; + wait_queue_head_t rx_queue; }; /** @@ -140,7 +139,7 @@ struct bt_drv { /** * state to string */ -static const char *bt_virnet_state_rep[BT_VIRNET_STAET_NUM] = { +static const char *g_bt_virnet_state_rep[BT_VIRNET_STAET_NUM] = { "CREATED", "CONNECTED", "DISCONNECTED", @@ -222,7 +221,7 @@ static inline const char *bt_virnet_get_ndev_name(const struct bt_virnet *vn) static inline const char *bt_virnet_get_state_rep(const struct bt_virnet *vn) { - return bt_virnet_state_rep[vn->state]; + return g_bt_virnet_state_rep[vn->state]; } static inline int bt_get_total_device(const struct bt_drv *drv) @@ -239,7 +238,7 @@ static inline int bt_virnet_get_ring_packets(const struct bt_virnet *vn) if (unlikely(!vn->tx_ring) || unlikely(!vn->tx_ring->head) || unlikely(!vn->tx_ring->tail)) - return -EINVAL; + return 0; packets = vn->tx_ring->head - vn->tx_ring->tail; if (unlikely(packets < 0))