aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/qib/qib_cq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_cq.c')
-rw-r--r--drivers/infiniband/hw/qib/qib_cq.c67
1 files changed, 61 insertions, 6 deletions
diff --git a/drivers/infiniband/hw/qib/qib_cq.c b/drivers/infiniband/hw/qib/qib_cq.c
index 5246aa486bbe..ab4e11cfab15 100644
--- a/drivers/infiniband/hw/qib/qib_cq.c
+++ b/drivers/infiniband/hw/qib/qib_cq.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * Copyright (c) 2013 Intel Corporation. All rights reserved.
2 * Copyright (c) 2006, 2007, 2008, 2010 QLogic Corporation. All rights reserved. 3 * Copyright (c) 2006, 2007, 2008, 2010 QLogic Corporation. All rights reserved.
3 * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. 4 * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
4 * 5 *
@@ -34,8 +35,10 @@
34#include <linux/err.h> 35#include <linux/err.h>
35#include <linux/slab.h> 36#include <linux/slab.h>
36#include <linux/vmalloc.h> 37#include <linux/vmalloc.h>
38#include <linux/kthread.h>
37 39
38#include "qib_verbs.h" 40#include "qib_verbs.h"
41#include "qib.h"
39 42
40/** 43/**
41 * qib_cq_enter - add a new entry to the completion queue 44 * qib_cq_enter - add a new entry to the completion queue
@@ -102,13 +105,18 @@ void qib_cq_enter(struct qib_cq *cq, struct ib_wc *entry, int solicited)
102 if (cq->notify == IB_CQ_NEXT_COMP || 105 if (cq->notify == IB_CQ_NEXT_COMP ||
103 (cq->notify == IB_CQ_SOLICITED && 106 (cq->notify == IB_CQ_SOLICITED &&
104 (solicited || entry->status != IB_WC_SUCCESS))) { 107 (solicited || entry->status != IB_WC_SUCCESS))) {
105 cq->notify = IB_CQ_NONE; 108 struct kthread_worker *worker;
106 cq->triggered++;
107 /* 109 /*
108 * This will cause send_complete() to be called in 110 * This will cause send_complete() to be called in
109 * another thread. 111 * another thread.
110 */ 112 */
111 queue_work(qib_cq_wq, &cq->comptask); 113 smp_rmb();
114 worker = cq->dd->worker;
115 if (likely(worker)) {
116 cq->notify = IB_CQ_NONE;
117 cq->triggered++;
118 queue_kthread_work(worker, &cq->comptask);
119 }
112 } 120 }
113 121
114 spin_unlock_irqrestore(&cq->lock, flags); 122 spin_unlock_irqrestore(&cq->lock, flags);
@@ -163,7 +171,7 @@ bail:
163 return npolled; 171 return npolled;
164} 172}
165 173
166static void send_complete(struct work_struct *work) 174static void send_complete(struct kthread_work *work)
167{ 175{
168 struct qib_cq *cq = container_of(work, struct qib_cq, comptask); 176 struct qib_cq *cq = container_of(work, struct qib_cq, comptask);
169 177
@@ -287,11 +295,12 @@ struct ib_cq *qib_create_cq(struct ib_device *ibdev, int entries,
287 * The number of entries should be >= the number requested or return 295 * The number of entries should be >= the number requested or return
288 * an error. 296 * an error.
289 */ 297 */
298 cq->dd = dd_from_dev(dev);
290 cq->ibcq.cqe = entries; 299 cq->ibcq.cqe = entries;
291 cq->notify = IB_CQ_NONE; 300 cq->notify = IB_CQ_NONE;
292 cq->triggered = 0; 301 cq->triggered = 0;
293 spin_lock_init(&cq->lock); 302 spin_lock_init(&cq->lock);
294 INIT_WORK(&cq->comptask, send_complete); 303 init_kthread_work(&cq->comptask, send_complete);
295 wc->head = 0; 304 wc->head = 0;
296 wc->tail = 0; 305 wc->tail = 0;
297 cq->queue = wc; 306 cq->queue = wc;
@@ -323,7 +332,7 @@ int qib_destroy_cq(struct ib_cq *ibcq)
323 struct qib_ibdev *dev = to_idev(ibcq->device); 332 struct qib_ibdev *dev = to_idev(ibcq->device);
324 struct qib_cq *cq = to_icq(ibcq); 333 struct qib_cq *cq = to_icq(ibcq);
325 334
326 flush_work(&cq->comptask); 335 flush_kthread_work(&cq->comptask);
327 spin_lock(&dev->n_cqs_lock); 336 spin_lock(&dev->n_cqs_lock);
328 dev->n_cqs_allocated--; 337 dev->n_cqs_allocated--;
329 spin_unlock(&dev->n_cqs_lock); 338 spin_unlock(&dev->n_cqs_lock);
@@ -483,3 +492,49 @@ bail_free:
483bail: 492bail:
484 return ret; 493 return ret;
485} 494}
495
496int qib_cq_init(struct qib_devdata *dd)
497{
498 int ret = 0;
499 int cpu;
500 struct task_struct *task;
501
502 if (dd->worker)
503 return 0;
504 dd->worker = kzalloc(sizeof(*dd->worker), GFP_KERNEL);
505 if (!dd->worker)
506 return -ENOMEM;
507 init_kthread_worker(dd->worker);
508 task = kthread_create_on_node(
509 kthread_worker_fn,
510 dd->worker,
511 dd->assigned_node_id,
512 "qib_cq%d", dd->unit);
513 if (IS_ERR(task))
514 goto task_fail;
515 cpu = cpumask_first(cpumask_of_node(dd->assigned_node_id));
516 kthread_bind(task, cpu);
517 wake_up_process(task);
518out:
519 return ret;
520task_fail:
521 ret = PTR_ERR(task);
522 kfree(dd->worker);
523 dd->worker = NULL;
524 goto out;
525}
526
527void qib_cq_exit(struct qib_devdata *dd)
528{
529 struct kthread_worker *worker;
530
531 worker = dd->worker;
532 if (!worker)
533 return;
534 /* blocks future queuing from send_complete() */
535 dd->worker = NULL;
536 smp_wmb();
537 flush_kthread_worker(worker);
538 kthread_stop(worker->task);
539 kfree(worker);
540}