|
@@ -120,17 +120,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);
|
|
@@ -512,7 +515,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);
|
|
@@ -524,7 +527,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;
|
|
|
}
|
|
|
|
|
@@ -536,15 +539,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);
|
|
|
}
|