Commit d79af724 authored by Jason Gunthorpe's avatar Jason Gunthorpe

RDMA/device: Expose ib_device_try_get(()

It turns out future patches need this capability quite widely now, not
just for netlink, so provide two global functions to manage the
registration lock refcount.

This also moves the point the lock becomes 1 to within
ib_register_device() so that the semantics of the public API are very sane
and clear. Calling ib_device_try_get() will fail on devices that are only
allocated but not yet registered.
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Reviewed-by: default avatarSteve Wise <swise@opengridcomputing.com>
Reviewed-by: default avatarParav Pandit <parav@mellanox.com>
parent 09ce351d
......@@ -267,7 +267,6 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,
#endif
struct ib_device *ib_device_get_by_index(u32 ifindex);
void ib_device_put(struct ib_device *device);
/* RDMA device netlink */
void nldev_init(void);
void nldev_exit(void);
......
......@@ -156,19 +156,26 @@ struct ib_device *ib_device_get_by_index(u32 index)
down_read(&lists_rwsem);
device = __ib_device_get_by_index(index);
if (device) {
/* Do not return a device if unregistration has started. */
if (!refcount_inc_not_zero(&device->refcount))
if (!ib_device_try_get(device))
device = NULL;
}
up_read(&lists_rwsem);
return device;
}
/**
* ib_device_put - Release IB device reference
* @device: device whose reference to be released
*
* ib_device_put() releases reference to the IB device to allow it to be
* unregistered and eventually free.
*/
void ib_device_put(struct ib_device *device)
{
if (refcount_dec_and_test(&device->refcount))
complete(&device->unreg_completion);
}
EXPORT_SYMBOL(ib_device_put);
static struct ib_device *__ib_device_get_by_name(const char *name)
{
......@@ -303,7 +310,6 @@ struct ib_device *ib_alloc_device(size_t size)
rwlock_init(&device->client_data_lock);
INIT_LIST_HEAD(&device->client_data_list);
INIT_LIST_HEAD(&device->port_list);
refcount_set(&device->refcount, 1);
init_completion(&device->unreg_completion);
return device;
......@@ -620,6 +626,7 @@ int ib_register_device(struct ib_device *device, const char *name,
goto cg_cleanup;
}
refcount_set(&device->refcount, 1);
device->reg_state = IB_DEV_REGISTERED;
list_for_each_entry(client, &client_list, list)
......
......@@ -2579,9 +2579,10 @@ struct ib_device {
const struct uapi_definition *driver_def;
enum rdma_driver_id driver_id;
/*
* Provides synchronization between device unregistration and netlink
* commands on a device. To be used only by core.
* Positive refcount indicates that the device is currently
* registered and cannot be unregistered.
*/
refcount_t refcount;
struct completion unreg_completion;
......@@ -3926,6 +3927,25 @@ static inline bool ib_access_writable(int access_flags)
int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
struct ib_mr_status *mr_status);
/**
* ib_device_try_get: Hold a registration lock
* device: The device to lock
*
* A device under an active registration lock cannot become unregistered. It
* is only possible to obtain a registration lock on a device that is fully
* registered, otherwise this function returns false.
*
* The registration lock is only necessary for actions which require the
* device to still be registered. Uses that only require the device pointer to
* be valid should use get_device(&ibdev->dev) to hold the memory.
*
*/
static inline bool ib_device_try_get(struct ib_device *dev)
{
return refcount_inc_not_zero(&dev->refcount);
}
void ib_device_put(struct ib_device *device);
struct net_device *ib_get_net_dev_by_params(struct ib_device *dev, u8 port,
u16 pkey, const union ib_gid *gid,
const struct sockaddr *addr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment