> From: Jason Gunthorpe <jgg@xxxxxxxxxxxx> > > 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: Jason Gunthorpe <jgg@xxxxxxxxxxxx> > --- > drivers/infiniband/core/core_priv.h | 1 - > drivers/infiniband/core/device.c | 6 +++--- > include/rdma/ib_verbs.h | 24 ++++++++++++++++++++++-- > 3 files changed, 25 insertions(+), 6 deletions(-) > > diff --git a/drivers/infiniband/core/core_priv.h > b/drivers/infiniband/core/core_priv.h > index 3cd830d52967eb..616734313f0c69 100644 > --- a/drivers/infiniband/core/core_priv.h > +++ b/drivers/infiniband/core/core_priv.h > @@ -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); > diff --git a/drivers/infiniband/core/device.c > b/drivers/infiniband/core/device.c > index 8872453e26c07c..9b5c72d3c85a88 100644 > --- a/drivers/infiniband/core/device.c > +++ b/drivers/infiniband/core/device.c > @@ -156,8 +156,7 @@ 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); > @@ -169,6 +168,7 @@ void ib_device_put(struct ib_device *device) Please add below hunk comment block for exported symbol. +/** + * 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. + */ > 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 +303,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 +619,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) diff --git > a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index > aa1f126d338350..85e9dab17b9b92 100644 > --- a/include/rdma/ib_verbs.h > +++ b/include/rdma/ib_verbs.h > @@ -2577,9 +2577,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. > + * If positive refcount indicates that the device is currently Positive refcount indicates. Please drop 'If' > + * registered and cannot be unregistered. > */ > refcount_t refcount; > struct completion unreg_completion; > @@ -3924,6 +3925,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); > -- > 2.20.1 Reviewed-by: Parav Pandit <parav@xxxxxxxxxxxx>