summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/core/rdma_core.c26
-rw-r--r--drivers/infiniband/core/uverbs.h12
-rw-r--r--drivers/infiniband/core/uverbs_main.c4
3 files changed, 22 insertions, 20 deletions
diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index a55646cbf9b1..4545c661acaa 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -461,9 +461,9 @@ static int __must_check _rdma_remove_commit_uobject(struct ib_uobject *uobj,
uobj->object = NULL;
- mutex_lock(&ufile->uobjects_lock);
+ spin_lock_irq(&ufile->uobjects_lock);
list_del(&uobj->list);
- mutex_unlock(&ufile->uobjects_lock);
+ spin_unlock_irq(&ufile->uobjects_lock);
/* Pairs with the get in rdma_alloc_commit_uobject() */
uverbs_uobject_put(uobj);
@@ -491,14 +491,14 @@ int rdma_explicit_destroy(struct ib_uobject *uobject)
struct ib_uverbs_file *ufile = uobject->ufile;
/* Cleanup is running. Calling this should have been impossible */
- if (!down_read_trylock(&ufile->cleanup_rwsem)) {
+ if (!down_read_trylock(&ufile->hw_destroy_rwsem)) {
WARN(true, "ib_uverbs: Cleanup is running while removing an uobject\n");
return 0;
}
assert_uverbs_usecnt(uobject, true);
ret = _rdma_remove_commit_uobject(uobject, RDMA_REMOVE_DESTROY);
- up_read(&ufile->cleanup_rwsem);
+ up_read(&ufile->hw_destroy_rwsem);
return ret;
}
@@ -541,7 +541,7 @@ int rdma_alloc_commit_uobject(struct ib_uobject *uobj)
struct ib_uverbs_file *ufile = uobj->ufile;
/* Cleanup is running. Calling this should have been impossible */
- if (!down_read_trylock(&ufile->cleanup_rwsem)) {
+ if (!down_read_trylock(&ufile->hw_destroy_rwsem)) {
int ret;
WARN(true, "ib_uverbs: Cleanup is running while allocating an uobject\n");
@@ -559,13 +559,13 @@ int rdma_alloc_commit_uobject(struct ib_uobject *uobj)
/* kref is held so long as the uobj is on the uobj list. */
uverbs_uobject_get(uobj);
- mutex_lock(&ufile->uobjects_lock);
+ spin_lock_irq(&ufile->uobjects_lock);
list_add(&uobj->list, &ufile->uobjects);
- mutex_unlock(&ufile->uobjects_lock);
+ spin_unlock_irq(&ufile->uobjects_lock);
/* alloc_commit consumes the uobj kref */
uobj->type->type_class->alloc_commit(uobj);
- up_read(&ufile->cleanup_rwsem);
+ up_read(&ufile->hw_destroy_rwsem);
return 0;
}
@@ -681,9 +681,9 @@ void uverbs_close_fd(struct file *f)
struct ib_uobject *uobj = f->private_data;
struct ib_uverbs_file *ufile = uobj->ufile;
- if (down_read_trylock(&ufile->cleanup_rwsem)) {
+ if (down_read_trylock(&ufile->hw_destroy_rwsem)) {
_uverbs_close_fd(uobj);
- up_read(&ufile->cleanup_rwsem);
+ up_read(&ufile->hw_destroy_rwsem);
}
uobj->object = NULL;
@@ -710,7 +710,6 @@ static int __uverbs_cleanup_ufile(struct ib_uverbs_file *ufile,
* We take and release the lock per traversal in order to let
* other threads (which might still use the FDs) chance to run.
*/
- mutex_lock(&ufile->uobjects_lock);
ufile->cleanup_reason = reason;
list_for_each_entry_safe(obj, next_obj, &ufile->uobjects, list) {
/*
@@ -736,7 +735,6 @@ static int __uverbs_cleanup_ufile(struct ib_uverbs_file *ufile,
uverbs_uobject_put(obj);
ret = 0;
}
- mutex_unlock(&ufile->uobjects_lock);
return ret;
}
@@ -751,7 +749,7 @@ void uverbs_cleanup_ufile(struct ib_uverbs_file *ufile, bool device_removed)
* want to hold this forever as the context is going to be destroyed,
* but we'll release it since it causes a "held lock freed" BUG message.
*/
- down_write(&ufile->cleanup_rwsem);
+ down_write(&ufile->hw_destroy_rwsem);
ufile->ucontext->cleanup_retryable = true;
while (!list_empty(&ufile->uobjects))
if (__uverbs_cleanup_ufile(ufile, reason)) {
@@ -766,7 +764,7 @@ void uverbs_cleanup_ufile(struct ib_uverbs_file *ufile, bool device_removed)
if (!list_empty(&ufile->uobjects))
__uverbs_cleanup_ufile(ufile, reason);
- up_write(&ufile->cleanup_rwsem);
+ up_write(&ufile->hw_destroy_rwsem);
}
const struct uverbs_obj_type_class uverbs_fd_class = {
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index d0a1a54275e5..58b16e840e56 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -145,12 +145,16 @@ struct ib_uverbs_file {
struct list_head list;
int is_closed;
- /* locking the uobjects_list */
- struct mutex uobjects_lock;
+ /*
+ * To access the uobjects list hw_destroy_rwsem must be held for write
+ * OR hw_destroy_rwsem held for read AND uobjects_lock held.
+ * hw_destroy_rwsem should be called across any destruction of the HW
+ * object of an associated uobject.
+ */
+ struct rw_semaphore hw_destroy_rwsem;
+ spinlock_t uobjects_lock;
struct list_head uobjects;
- /* protects cleanup process from other actions */
- struct rw_semaphore cleanup_rwsem;
enum rdma_remove_reason cleanup_reason;
struct idr idr;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 8425718bebbd..77faf32fc997 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -889,9 +889,9 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
mutex_init(&file->mutex);
mutex_init(&file->cleanup_mutex);
- mutex_init(&file->uobjects_lock);
+ spin_lock_init(&file->uobjects_lock);
INIT_LIST_HEAD(&file->uobjects);
- init_rwsem(&file->cleanup_rwsem);
+ init_rwsem(&file->hw_destroy_rwsem);
filp->private_data = file;
kobject_get(&dev->kobj);