aboutsummaryrefslogtreecommitdiff
path: root/drivers/infiniband/sw/rdmavt/cq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/sw/rdmavt/cq.c')
-rw-r--r--drivers/infiniband/sw/rdmavt/cq.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/drivers/infiniband/sw/rdmavt/cq.c b/drivers/infiniband/sw/rdmavt/cq.c
index 88fa4d44ab5f..76a86f805233 100644
--- a/drivers/infiniband/sw/rdmavt/cq.c
+++ b/drivers/infiniband/sw/rdmavt/cq.c
@@ -121,17 +121,20 @@ void rvt_cq_enter(struct rvt_cq *cq, struct ib_wc *entry, bool solicited)
if (cq->notify == IB_CQ_NEXT_COMP ||
(cq->notify == IB_CQ_SOLICITED &&
(solicited || entry->status != IB_WC_SUCCESS))) {
+ struct kthread_worker *worker;
+
/*
* This will cause send_complete() to be called in
* another thread.
*/
- spin_lock(&cq->rdi->n_cqs_lock);
- if (likely(cq->rdi->worker)) {
+ rcu_read_lock();
+ worker = rcu_dereference(cq->rdi->worker);
+ if (likely(worker)) {
cq->notify = RVT_CQ_NONE;
cq->triggered++;
- kthread_queue_work(cq->rdi->worker, &cq->comptask);
+ kthread_queue_work(worker, &cq->comptask);
}
- spin_unlock(&cq->rdi->n_cqs_lock);
+ rcu_read_unlock();
}
spin_unlock_irqrestore(&cq->lock, flags);
@@ -513,7 +516,7 @@ int rvt_driver_cq_init(struct rvt_dev_info *rdi)
int cpu;
struct kthread_worker *worker;
- if (rdi->worker)
+ if (rcu_access_pointer(rdi->worker))
return 0;
spin_lock_init(&rdi->n_cqs_lock);
@@ -525,7 +528,7 @@ int rvt_driver_cq_init(struct rvt_dev_info *rdi)
return PTR_ERR(worker);
set_user_nice(worker->task, MIN_NICE);
- rdi->worker = worker;
+ RCU_INIT_POINTER(rdi->worker, worker);
return 0;
}
@@ -537,15 +540,19 @@ void rvt_cq_exit(struct rvt_dev_info *rdi)
{
struct kthread_worker *worker;
- /* block future queuing from send_complete() */
- spin_lock_irq(&rdi->n_cqs_lock);
- worker = rdi->worker;
+ if (!rcu_access_pointer(rdi->worker))
+ return;
+
+ spin_lock(&rdi->n_cqs_lock);
+ worker = rcu_dereference_protected(rdi->worker,
+ lockdep_is_held(&rdi->n_cqs_lock));
if (!worker) {
- spin_unlock_irq(&rdi->n_cqs_lock);
+ spin_unlock(&rdi->n_cqs_lock);
return;
}
- rdi->worker = NULL;
- spin_unlock_irq(&rdi->n_cqs_lock);
+ RCU_INIT_POINTER(rdi->worker, NULL);
+ spin_unlock(&rdi->n_cqs_lock);
+ synchronize_rcu();
kthread_destroy_worker(worker);
}