mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-23 19:43:54 +07:00
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: c5c4d92e70
("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>
This commit is contained in:
parent
0965cc953a
commit
0099103926
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user