mirror of
https://github.com/openharmony/kernel_linux_common_modules.git
synced 2026-08-26 17:16:37 -04:00
!19 btdev code rectification
Merge pull request !19 from liangbotong/master
This commit is contained in:
@@ -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 <yangyanjun@huawei.com>
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <yangyanjun@huawei.com>
|
||||
*
|
||||
* 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);
|
||||
|
||||
Reference in New Issue
Block a user