aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2018-09-17 15:44:46 -0600
committerJason Gunthorpe <jgg@mellanox.com>2018-09-19 10:49:22 -0600
commit0099103926b68e6675a1be4644848f5b1c1b6f97 (patch)
tree7be7fffe0221da2320629c9f3c086cb73f27b8fe /drivers/infiniband/core
parentRDMA/core: Properly return the error code of rdma_set_src_addr_rcu (diff)
downloadlinux-dev-0099103926b68e6675a1be4644848f5b1c1b6f97.tar.xz
linux-dev-0099103926b68e6675a1be4644848f5b1c1b6f97.zip
RDMA/uverbs: Fix error unwind in ib_uverbs_add_one
The error path has several mistakes - cdev_del should not be called if cdev_device_add fails - We must call put_device on all the goto exit paths as that is what frees the uapi, SRCU and the struct itself. While we are here consolidate all the uvdev_dev init that cannot fail at the top. Fixes: c5c4d92e70f3 ("RDMA/uverbs: Use cdev_device_add() instead of cdev_add()") Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> Reviewed-by: Parav Pandit <parav@mellanox.com>
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r--drivers/infiniband/core/uverbs_main.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 176271db9ed7..db6de9157668 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -1028,6 +1028,12 @@ static void ib_uverbs_add_one(struct ib_device *device)
return;
}
+ device_initialize(&uverbs_dev->dev);
+ uverbs_dev->dev.class = uverbs_class;
+ uverbs_dev->dev.parent = device->dev.parent;
+ uverbs_dev->dev.release = ib_uverbs_release_dev;
+ uverbs_dev->groups[0] = &dev_attr_group;
+ uverbs_dev->dev.groups = uverbs_dev->groups;
atomic_set(&uverbs_dev->refcount, 1);
init_completion(&uverbs_dev->comp);
uverbs_dev->xrcd_tree = RB_ROOT;
@@ -1035,6 +1041,8 @@ static void ib_uverbs_add_one(struct ib_device *device)
mutex_init(&uverbs_dev->lists_mutex);
INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list);
INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list);
+ rcu_assign_pointer(uverbs_dev->ib_dev, device);
+ uverbs_dev->num_comp_vectors = device->num_comp_vectors;
devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES);
if (devnum >= IB_UVERBS_MAX_DEVICES)
@@ -1046,19 +1054,10 @@ static void ib_uverbs_add_one(struct ib_device *device)
else
base = IB_UVERBS_BASE_DEV + devnum;
- rcu_assign_pointer(uverbs_dev->ib_dev, device);
- uverbs_dev->num_comp_vectors = device->num_comp_vectors;
-
if (ib_uverbs_create_uapi(device, uverbs_dev))
goto err_uapi;
- 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;
- uverbs_dev->groups[0] = &dev_attr_group;
- uverbs_dev->dev.groups = uverbs_dev->groups;
dev_set_name(&uverbs_dev->dev, "uverbs%d", uverbs_dev->devnum);
cdev_init(&uverbs_dev->cdev,
@@ -1067,20 +1066,18 @@ static void ib_uverbs_add_one(struct ib_device *device)
ret = cdev_device_add(&uverbs_dev->cdev, &uverbs_dev->dev);
if (ret)
- goto err_cdev;
+ goto err_uapi;
ib_set_client_data(device, &uverbs_client, uverbs_dev);
return;
-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);
+ put_device(&uverbs_dev->dev);
return;
}