RDMA/uverbs: Use cdev_device_add() instead of cdev_add()
authorParav Pandit <parav@mellanox.com>
Wed, 5 Sep 2018 06:47:59 +0000 (09:47 +0300)
committerJason Gunthorpe <jgg@mellanox.com>
Wed, 5 Sep 2018 22:19:25 +0000 (16:19 -0600)
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: Parav Pandit <parav@mellanox.com>
Reviewed-by: Daniel Jurgens <danielj@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/core/uverbs.h
drivers/infiniband/core/uverbs_main.c

index 5df8e54..0288aec 100644 (file)
@@ -100,13 +100,12 @@ struct ib_uverbs_device {
        atomic_t                                refcount;
        int                                     num_comp_vectors;
        struct completion                       comp;
-       struct device                          *dev;
+       struct device                           dev;
        struct ib_device        __rcu          *ib_dev;
        int                                     devnum;
        struct cdev                             cdev;
        struct rb_root                          xrcd_tree;
        struct mutex                            xrcd_tree_mutex;
-       struct kobject                          kobj;
        struct srcu_struct                      disassociate_srcu;
        struct mutex                            lists_mutex; /* protect lists */
        struct list_head                        uverbs_file_list;
index 6d974e2..1d2650f 100644 (file)
@@ -169,20 +169,16 @@ int uverbs_dealloc_mw(struct ib_mw *mw)
        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 =
-               container_of(kobj, struct ib_uverbs_device, kobj);
+                       container_of(device, struct ib_uverbs_device, dev);
 
        uverbs_destroy_api(dev->uapi);
        cleanup_srcu_struct(&dev->disassociate_srcu);
        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)
 {
        struct ib_uverbs_async_event_file *file =
@@ -265,7 +261,7 @@ void ib_uverbs_release_file(struct kref *ref)
        if (atomic_dec_and_test(&file->device->refcount))
                ib_uverbs_comp_dev(file->device);
 
-       kobject_put(&file->device->kobj);
+       put_device(&file->device->dev);
        kfree(file);
 }
 
@@ -838,6 +834,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        if (!atomic_inc_not_zero(&dev->refcount))
                return -ENXIO;
 
+       get_device(&dev->dev);
        srcu_key = srcu_read_lock(&dev->disassociate_srcu);
        mutex_lock(&dev->lists_mutex);
        ib_dev = srcu_dereference(dev->ib_dev,
@@ -877,7 +874,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
        init_rwsem(&file->hw_destroy_rwsem);
 
        filp->private_data = file;
-       kobject_get(&dev->kobj);
        list_add_tail(&file->list, &dev->uverbs_file_list);
        mutex_unlock(&dev->lists_mutex);
        srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
@@ -898,6 +894,7 @@ err:
        if (atomic_dec_and_test(&dev->refcount))
                ib_uverbs_comp_dev(dev);
 
+       put_device(&dev->dev);
        return ret;
 }
 
@@ -953,14 +950,12 @@ static struct ib_client uverbs_client = {
 static ssize_t show_ibdev(struct device *device, struct device_attribute *attr,
                          char *buf)
 {
+       struct ib_uverbs_device *dev =
+                       container_of(device, struct ib_uverbs_device, dev);
        int ret = -ENODEV;
        int srcu_key;
-       struct ib_uverbs_device *dev = dev_get_drvdata(device);
        struct ib_device *ib_dev;
 
-       if (!dev)
-               return -ENODEV;
-
        srcu_key = srcu_read_lock(&dev->disassociate_srcu);
        ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);
        if (ib_dev)
@@ -974,13 +969,12 @@ static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
 static ssize_t show_dev_abi_version(struct device *device,
                                    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 srcu_key;
        struct ib_device *ib_dev;
 
-       if (!dev)
-               return -ENODEV;
        srcu_key = srcu_read_lock(&dev->disassociate_srcu);
        ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);
        if (ib_dev)
@@ -1031,7 +1025,6 @@ static void ib_uverbs_add_one(struct ib_device *device)
        init_completion(&uverbs_dev->comp);
        uverbs_dev->xrcd_tree = RB_ROOT;
        mutex_init(&uverbs_dev->xrcd_tree_mutex);
-       kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype);
        mutex_init(&uverbs_dev->lists_mutex);
        INIT_LIST_HEAD(&uverbs_dev->uverbs_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)
        if (ib_uverbs_create_uapi(device, uverbs_dev))
                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.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,
-                                       uverbs_dev->cdev.dev, uverbs_dev,
-                                       "uverbs%d", uverbs_dev->devnum);
-       if (IS_ERR(uverbs_dev->dev))
+       ret = cdev_device_add(&uverbs_dev->cdev, &uverbs_dev->dev);
+       if (ret)
                goto err_cdev;
 
-       if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev))
-               goto err_class;
-       if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
-               goto err_class;
+       if (device_create_file(&uverbs_dev->dev, &dev_attr_ibdev))
+               goto err_file;
+       if (device_create_file(&uverbs_dev->dev, &dev_attr_abi_version))
+               goto err_file;
 
        ib_set_client_data(device, &uverbs_client, uverbs_dev);
 
        return;
 
-err_class:
-       device_destroy(uverbs_class, uverbs_dev->cdev.dev);
+err_file:
+       cdev_device_del(&uverbs_dev->cdev, &uverbs_dev->dev);
 err_cdev:
        cdev_del(&uverbs_dev->cdev);
+       put_device(&uverbs_dev->dev);
 err_uapi:
        clear_bit(devnum, dev_map);
 err:
        if (atomic_dec_and_test(&uverbs_dev->refcount))
                ib_uverbs_comp_dev(uverbs_dev);
        wait_for_completion(&uverbs_dev->comp);
-       kobject_put(&uverbs_dev->kobj);
        return;
 }
 
@@ -1155,9 +1149,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
        if (!uverbs_dev)
                return;
 
-       dev_set_drvdata(uverbs_dev->dev, NULL);
-       device_destroy(uverbs_class, uverbs_dev->cdev.dev);
-       cdev_del(&uverbs_dev->cdev);
+       cdev_device_del(&uverbs_dev->cdev, &uverbs_dev->dev);
        clear_bit(uverbs_dev->devnum, dev_map);
 
        if (device->disassociate_ucontext) {
@@ -1181,7 +1173,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
        if (wait_clients)
                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)