aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw
diff options
context:
space:
mode:
authorMike Marciniszyn <mike.marciniszyn@intel.com>2013-06-04 15:05:37 -0400
committerRoland Dreier <roland@purestorage.com>2013-06-21 20:19:49 -0400
commit85caafe307a06e4f9993c8f3c994a07374c07831 (patch)
treec17964cc02d75f2bb6f827eed9daeec719b85d17 /drivers/infiniband/hw
parentc804f07248895ff9c9dccb6cda703068a0657b6c (diff)
IB/qib: Optimize CQ callbacks
The current workqueue implemention has the following performance deficiencies on QDR HCAs: - The CQ call backs tend to run on the CPUs processing the receive queues - The single thread queue isn't optimal for multiple HCAs This patch adds a dedicated per HCA bound thread to process CQ callbacks. Reviewed-by: Ramkrishna Vepa <ramkrishna.vepa@intel.com> Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r--drivers/infiniband/hw/qib/qib.h5
-rw-r--r--drivers/infiniband/hw/qib/qib_cq.c67
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c18
-rw-r--r--drivers/infiniband/hw/qib/qib_verbs.h10
4 files changed, 76 insertions, 24 deletions
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h
index 2ee82e6550c7..3a78b92cbd4e 100644
--- a/drivers/infiniband/hw/qib/qib.h
+++ b/drivers/infiniband/hw/qib/qib.h
@@ -1,7 +1,7 @@
1#ifndef _QIB_KERNEL_H 1#ifndef _QIB_KERNEL_H
2#define _QIB_KERNEL_H 2#define _QIB_KERNEL_H
3/* 3/*
4 * Copyright (c) 2012 Intel Corporation. All rights reserved. 4 * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved.
5 * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. 5 * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved.
6 * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. 6 * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
7 * 7 *
@@ -51,6 +51,7 @@
51#include <linux/completion.h> 51#include <linux/completion.h>
52#include <linux/kref.h> 52#include <linux/kref.h>
53#include <linux/sched.h> 53#include <linux/sched.h>
54#include <linux/kthread.h>
54 55
55#include "qib_common.h" 56#include "qib_common.h"
56#include "qib_verbs.h" 57#include "qib_verbs.h"
@@ -1090,6 +1091,8 @@ struct qib_devdata {
1090 u16 psxmitwait_check_rate; 1091 u16 psxmitwait_check_rate;
1091 /* high volume overflow errors defered to tasklet */ 1092 /* high volume overflow errors defered to tasklet */
1092 struct tasklet_struct error_tasklet; 1093 struct tasklet_struct error_tasklet;
1094 /* per device cq worker */
1095 struct kthread_worker *worker;
1093 1096
1094 int assigned_node_id; /* NUMA node closest to HCA */ 1097 int assigned_node_id; /* NUMA node closest to HCA */
1095}; 1098};
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}
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index e02217b5c46d..ff36903474ea 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -97,8 +97,6 @@ unsigned qib_wc_pat = 1; /* default (1) is to use PAT, not MTRR */
97module_param_named(wc_pat, qib_wc_pat, uint, S_IRUGO); 97module_param_named(wc_pat, qib_wc_pat, uint, S_IRUGO);
98MODULE_PARM_DESC(wc_pat, "enable write-combining via PAT mechanism"); 98MODULE_PARM_DESC(wc_pat, "enable write-combining via PAT mechanism");
99 99
100struct workqueue_struct *qib_cq_wq;
101
102static void verify_interrupt(unsigned long); 100static void verify_interrupt(unsigned long);
103 101
104static struct idr qib_unit_table; 102static struct idr qib_unit_table;
@@ -445,6 +443,7 @@ static int loadtime_init(struct qib_devdata *dd)
445 dd->intrchk_timer.function = verify_interrupt; 443 dd->intrchk_timer.function = verify_interrupt;
446 dd->intrchk_timer.data = (unsigned long) dd; 444 dd->intrchk_timer.data = (unsigned long) dd;
447 445
446 ret = qib_cq_init(dd);
448done: 447done:
449 return ret; 448 return ret;
450} 449}
@@ -1215,12 +1214,6 @@ static int __init qlogic_ib_init(void)
1215 if (ret) 1214 if (ret)
1216 goto bail; 1215 goto bail;
1217 1216
1218 qib_cq_wq = create_singlethread_workqueue("qib_cq");
1219 if (!qib_cq_wq) {
1220 ret = -ENOMEM;
1221 goto bail_dev;
1222 }
1223
1224 /* 1217 /*
1225 * These must be called before the driver is registered with 1218 * These must be called before the driver is registered with
1226 * the PCI subsystem. 1219 * the PCI subsystem.
@@ -1233,7 +1226,7 @@ static int __init qlogic_ib_init(void)
1233 ret = pci_register_driver(&qib_driver); 1226 ret = pci_register_driver(&qib_driver);
1234 if (ret < 0) { 1227 if (ret < 0) {
1235 pr_err("Unable to register driver: error %d\n", -ret); 1228 pr_err("Unable to register driver: error %d\n", -ret);
1236 goto bail_unit; 1229 goto bail_dev;
1237 } 1230 }
1238 1231
1239 /* not fatal if it doesn't work */ 1232 /* not fatal if it doesn't work */
@@ -1241,13 +1234,11 @@ static int __init qlogic_ib_init(void)
1241 pr_err("Unable to register ipathfs\n"); 1234 pr_err("Unable to register ipathfs\n");
1242 goto bail; /* all OK */ 1235 goto bail; /* all OK */
1243 1236
1244bail_unit: 1237bail_dev:
1245#ifdef CONFIG_INFINIBAND_QIB_DCA 1238#ifdef CONFIG_INFINIBAND_QIB_DCA
1246 dca_unregister_notify(&dca_notifier); 1239 dca_unregister_notify(&dca_notifier);
1247#endif 1240#endif
1248 idr_destroy(&qib_unit_table); 1241 idr_destroy(&qib_unit_table);
1249 destroy_workqueue(qib_cq_wq);
1250bail_dev:
1251 qib_dev_cleanup(); 1242 qib_dev_cleanup();
1252bail: 1243bail:
1253 return ret; 1244 return ret;
@@ -1273,8 +1264,6 @@ static void __exit qlogic_ib_cleanup(void)
1273#endif 1264#endif
1274 pci_unregister_driver(&qib_driver); 1265 pci_unregister_driver(&qib_driver);
1275 1266
1276 destroy_workqueue(qib_cq_wq);
1277
1278 qib_cpulist_count = 0; 1267 qib_cpulist_count = 0;
1279 kfree(qib_cpulist); 1268 kfree(qib_cpulist);
1280 1269
@@ -1365,6 +1354,7 @@ static void cleanup_device_data(struct qib_devdata *dd)
1365 } 1354 }
1366 kfree(tmp); 1355 kfree(tmp);
1367 kfree(dd->boardname); 1356 kfree(dd->boardname);
1357 qib_cq_exit(dd);
1368} 1358}
1369 1359
1370/* 1360/*
diff --git a/drivers/infiniband/hw/qib/qib_verbs.h b/drivers/infiniband/hw/qib/qib_verbs.h
index aff8b2c17886..86c2cb3c9caf 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.h
+++ b/drivers/infiniband/hw/qib/qib_verbs.h
@@ -41,6 +41,7 @@
41#include <linux/interrupt.h> 41#include <linux/interrupt.h>
42#include <linux/kref.h> 42#include <linux/kref.h>
43#include <linux/workqueue.h> 43#include <linux/workqueue.h>
44#include <linux/kthread.h>
44#include <linux/completion.h> 45#include <linux/completion.h>
45#include <rdma/ib_pack.h> 46#include <rdma/ib_pack.h>
46#include <rdma/ib_user_verbs.h> 47#include <rdma/ib_user_verbs.h>
@@ -267,7 +268,8 @@ struct qib_cq_wc {
267 */ 268 */
268struct qib_cq { 269struct qib_cq {
269 struct ib_cq ibcq; 270 struct ib_cq ibcq;
270 struct work_struct comptask; 271 struct kthread_work comptask;
272 struct qib_devdata *dd;
271 spinlock_t lock; /* protect changes in this struct */ 273 spinlock_t lock; /* protect changes in this struct */
272 u8 notify; 274 u8 notify;
273 u8 triggered; 275 u8 triggered;
@@ -832,8 +834,6 @@ static inline int qib_send_ok(struct qib_qp *qp)
832 !(qp->s_flags & QIB_S_ANY_WAIT_SEND)); 834 !(qp->s_flags & QIB_S_ANY_WAIT_SEND));
833} 835}
834 836
835extern struct workqueue_struct *qib_cq_wq;
836
837/* 837/*
838 * This must be called with s_lock held. 838 * This must be called with s_lock held.
839 */ 839 */
@@ -972,6 +972,10 @@ int qib_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr);
972 972
973int qib_destroy_srq(struct ib_srq *ibsrq); 973int qib_destroy_srq(struct ib_srq *ibsrq);
974 974
975int qib_cq_init(struct qib_devdata *dd);
976
977void qib_cq_exit(struct qib_devdata *dd);
978
975void qib_cq_enter(struct qib_cq *cq, struct ib_wc *entry, int sig); 979void qib_cq_enter(struct qib_cq *cq, struct ib_wc *entry, int sig);
976 980
977int qib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); 981int qib_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry);