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 446d20763ebb8761a7687448f105fad6aa0a2c26..0a99291484e4ab83481d7c60f48fae0db9c55b59 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); + struct bt_ring *ring; - if (unlikely(!ring)) { - pr_err("ring create alloc failed: oom"); + if (unlikely(size < 0)) return NULL; - } - if (unlikely(size < 0)) + 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 2122b1b5b0531fa660aba4baa4fc293300a70c45..92b4262c9c30bd813ef88c275eab843f299a461c 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))