mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: 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>
This commit is contained in:
		
							parent
							
								
									adee9f3f3b
								
							
						
					
					
						commit
						c5c4d92e70
					
				
					 2 changed files with 31 additions and 40 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
 | 
			
		|||
	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))
 | 
			
		||||
 | 
			
		||||
	ret = cdev_device_add(&uverbs_dev->cdev, &uverbs_dev->dev);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		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))
 | 
			
		||||
		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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue