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
					
				| @ -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 @@ 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)) | ||||
| 
 | ||||
| 	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 New Issue
	
	Block a user