Commit c5c4d92e authored by Parav Pandit's avatar Parav Pandit Committed by Jason Gunthorpe

RDMA/uverbs: Use cdev_device_add() instead of cdev_add()

Instead of doing two step process to add char device and create underlying
device, use cdev_device_add() which does both.

Currently a kobject per uverbs_device is created to keep reference to its
holding ib_uverbs_device in addition to its underlying device 'dev'.

Instead just use uverbs_device->dev to keep a reference to.

With this change there is single reference tracker for ib_uverbs_device
structure.

This allows for subsequent patch to registers group attribute as well
using single API cdev_device_add().
Signed-off-by: default avatarParav Pandit <parav@mellanox.com>
Reviewed-by: default avatarDaniel Jurgens <danielj@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent adee9f3f
...@@ -100,13 +100,12 @@ struct ib_uverbs_device { ...@@ -100,13 +100,12 @@ struct ib_uverbs_device {
atomic_t refcount; atomic_t refcount;
int num_comp_vectors; int num_comp_vectors;
struct completion comp; struct completion comp;
struct device *dev; struct device dev;
struct ib_device __rcu *ib_dev; struct ib_device __rcu *ib_dev;
int devnum; int devnum;
struct cdev cdev; struct cdev cdev;
struct rb_root xrcd_tree; struct rb_root xrcd_tree;
struct mutex xrcd_tree_mutex; struct mutex xrcd_tree_mutex;
struct kobject kobj;
struct srcu_struct disassociate_srcu; struct srcu_struct disassociate_srcu;
struct mutex lists_mutex; /* protect lists */ struct mutex lists_mutex; /* protect lists */
struct list_head uverbs_file_list; struct list_head uverbs_file_list;
......
...@@ -169,20 +169,16 @@ int uverbs_dealloc_mw(struct ib_mw *mw) ...@@ -169,20 +169,16 @@ int uverbs_dealloc_mw(struct ib_mw *mw)
return ret; return ret;
} }
static void ib_uverbs_release_dev(struct kobject *kobj) static void ib_uverbs_release_dev(struct device *device)
{ {
struct ib_uverbs_device *dev = struct ib_uverbs_device *dev =
container_of(kobj, struct ib_uverbs_device, kobj); container_of(device, struct ib_uverbs_device, dev);
uverbs_destroy_api(dev->uapi); uverbs_destroy_api(dev->uapi);
cleanup_srcu_struct(&dev->disassociate_srcu); cleanup_srcu_struct(&dev->disassociate_srcu);
kfree(dev); kfree(dev);
} }
static struct kobj_type ib_uverbs_dev_ktype = {
.release = ib_uverbs_release_dev,
};
static void ib_uverbs_release_async_event_file(struct kref *ref) static void ib_uverbs_release_async_event_file(struct kref *ref)
{ {
struct ib_uverbs_async_event_file *file = struct ib_uverbs_async_event_file *file =
...@@ -265,7 +261,7 @@ void ib_uverbs_release_file(struct kref *ref) ...@@ -265,7 +261,7 @@ void ib_uverbs_release_file(struct kref *ref)
if (atomic_dec_and_test(&file->device->refcount)) if (atomic_dec_and_test(&file->device->refcount))
ib_uverbs_comp_dev(file->device); ib_uverbs_comp_dev(file->device);
kobject_put(&file->device->kobj); put_device(&file->device->dev);
kfree(file); kfree(file);
} }
...@@ -838,6 +834,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) ...@@ -838,6 +834,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
if (!atomic_inc_not_zero(&dev->refcount)) if (!atomic_inc_not_zero(&dev->refcount))
return -ENXIO; return -ENXIO;
get_device(&dev->dev);
srcu_key = srcu_read_lock(&dev->disassociate_srcu); srcu_key = srcu_read_lock(&dev->disassociate_srcu);
mutex_lock(&dev->lists_mutex); mutex_lock(&dev->lists_mutex);
ib_dev = srcu_dereference(dev->ib_dev, ib_dev = srcu_dereference(dev->ib_dev,
...@@ -877,7 +874,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) ...@@ -877,7 +874,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
init_rwsem(&file->hw_destroy_rwsem); init_rwsem(&file->hw_destroy_rwsem);
filp->private_data = file; filp->private_data = file;
kobject_get(&dev->kobj);
list_add_tail(&file->list, &dev->uverbs_file_list); list_add_tail(&file->list, &dev->uverbs_file_list);
mutex_unlock(&dev->lists_mutex); mutex_unlock(&dev->lists_mutex);
srcu_read_unlock(&dev->disassociate_srcu, srcu_key); srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
...@@ -898,6 +894,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) ...@@ -898,6 +894,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
if (atomic_dec_and_test(&dev->refcount)) if (atomic_dec_and_test(&dev->refcount))
ib_uverbs_comp_dev(dev); ib_uverbs_comp_dev(dev);
put_device(&dev->dev);
return ret; return ret;
} }
...@@ -953,14 +950,12 @@ static struct ib_client uverbs_client = { ...@@ -953,14 +950,12 @@ static struct ib_client uverbs_client = {
static ssize_t show_ibdev(struct device *device, struct device_attribute *attr, static ssize_t show_ibdev(struct device *device, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct ib_uverbs_device *dev =
container_of(device, struct ib_uverbs_device, dev);
int ret = -ENODEV; int ret = -ENODEV;
int srcu_key; int srcu_key;
struct ib_uverbs_device *dev = dev_get_drvdata(device);
struct ib_device *ib_dev; struct ib_device *ib_dev;
if (!dev)
return -ENODEV;
srcu_key = srcu_read_lock(&dev->disassociate_srcu); srcu_key = srcu_read_lock(&dev->disassociate_srcu);
ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu); ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);
if (ib_dev) if (ib_dev)
...@@ -974,13 +969,12 @@ static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); ...@@ -974,13 +969,12 @@ static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
static ssize_t show_dev_abi_version(struct device *device, static ssize_t show_dev_abi_version(struct device *device,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct ib_uverbs_device *dev = dev_get_drvdata(device); struct ib_uverbs_device *dev =
container_of(device, struct ib_uverbs_device, dev);
int ret = -ENODEV; int ret = -ENODEV;
int srcu_key; int srcu_key;
struct ib_device *ib_dev; struct ib_device *ib_dev;
if (!dev)
return -ENODEV;
srcu_key = srcu_read_lock(&dev->disassociate_srcu); srcu_key = srcu_read_lock(&dev->disassociate_srcu);
ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu); ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);
if (ib_dev) if (ib_dev)
...@@ -1031,7 +1025,6 @@ static void ib_uverbs_add_one(struct ib_device *device) ...@@ -1031,7 +1025,6 @@ static void ib_uverbs_add_one(struct ib_device *device)
init_completion(&uverbs_dev->comp); init_completion(&uverbs_dev->comp);
uverbs_dev->xrcd_tree = RB_ROOT; uverbs_dev->xrcd_tree = RB_ROOT;
mutex_init(&uverbs_dev->xrcd_tree_mutex); mutex_init(&uverbs_dev->xrcd_tree_mutex);
kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype);
mutex_init(&uverbs_dev->lists_mutex); mutex_init(&uverbs_dev->lists_mutex);
INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list); INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list);
INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list); INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list);
...@@ -1052,40 +1045,41 @@ static void ib_uverbs_add_one(struct ib_device *device) ...@@ -1052,40 +1045,41 @@ static void ib_uverbs_add_one(struct ib_device *device)
if (ib_uverbs_create_uapi(device, uverbs_dev)) if (ib_uverbs_create_uapi(device, uverbs_dev))
goto err_uapi; goto err_uapi;
cdev_init(&uverbs_dev->cdev, NULL); device_initialize(&uverbs_dev->dev);
uverbs_dev->dev.class = uverbs_class;
uverbs_dev->dev.parent = device->dev.parent;
uverbs_dev->dev.devt = base;
uverbs_dev->dev.release = ib_uverbs_release_dev;
dev_set_name(&uverbs_dev->dev, "uverbs%d", uverbs_dev->devnum);
cdev_init(&uverbs_dev->cdev,
device->mmap ? &uverbs_mmap_fops : &uverbs_fops);
uverbs_dev->cdev.owner = THIS_MODULE; uverbs_dev->cdev.owner = THIS_MODULE;
uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
cdev_set_parent(&uverbs_dev->cdev, &uverbs_dev->kobj);
kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
if (cdev_add(&uverbs_dev->cdev, base, 1))
goto err_cdev;
uverbs_dev->dev = device_create(uverbs_class, device->dev.parent, ret = cdev_device_add(&uverbs_dev->cdev, &uverbs_dev->dev);
uverbs_dev->cdev.dev, uverbs_dev, if (ret)
"uverbs%d", uverbs_dev->devnum);
if (IS_ERR(uverbs_dev->dev))
goto err_cdev; goto err_cdev;
if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev)) if (device_create_file(&uverbs_dev->dev, &dev_attr_ibdev))
goto err_class; goto err_file;
if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version)) if (device_create_file(&uverbs_dev->dev, &dev_attr_abi_version))
goto err_class; goto err_file;
ib_set_client_data(device, &uverbs_client, uverbs_dev); ib_set_client_data(device, &uverbs_client, uverbs_dev);
return; return;
err_class: err_file:
device_destroy(uverbs_class, uverbs_dev->cdev.dev); cdev_device_del(&uverbs_dev->cdev, &uverbs_dev->dev);
err_cdev: err_cdev:
cdev_del(&uverbs_dev->cdev); cdev_del(&uverbs_dev->cdev);
put_device(&uverbs_dev->dev);
err_uapi: err_uapi:
clear_bit(devnum, dev_map); clear_bit(devnum, dev_map);
err: err:
if (atomic_dec_and_test(&uverbs_dev->refcount)) if (atomic_dec_and_test(&uverbs_dev->refcount))
ib_uverbs_comp_dev(uverbs_dev); ib_uverbs_comp_dev(uverbs_dev);
wait_for_completion(&uverbs_dev->comp); wait_for_completion(&uverbs_dev->comp);
kobject_put(&uverbs_dev->kobj);
return; return;
} }
...@@ -1155,9 +1149,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data) ...@@ -1155,9 +1149,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
if (!uverbs_dev) if (!uverbs_dev)
return; return;
dev_set_drvdata(uverbs_dev->dev, NULL); cdev_device_del(&uverbs_dev->cdev, &uverbs_dev->dev);
device_destroy(uverbs_class, uverbs_dev->cdev.dev);
cdev_del(&uverbs_dev->cdev);
clear_bit(uverbs_dev->devnum, dev_map); clear_bit(uverbs_dev->devnum, dev_map);
if (device->disassociate_ucontext) { if (device->disassociate_ucontext) {
...@@ -1181,7 +1173,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data) ...@@ -1181,7 +1173,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
if (wait_clients) if (wait_clients)
wait_for_completion(&uverbs_dev->comp); wait_for_completion(&uverbs_dev->comp);
kobject_put(&uverbs_dev->kobj); put_device(&uverbs_dev->dev);
} }
static char *uverbs_devnode(struct device *dev, umode_t *mode) static char *uverbs_devnode(struct device *dev, umode_t *mode)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment