aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/qib/qib_init.c
diff options
context:
space:
mode:
authorMike Marciniszyn <mike.marciniszyn@intel.com>2013-05-30 18:25:25 -0400
committerRoland Dreier <roland@purestorage.com>2013-06-21 17:19:38 -0700
commit8469ba39a6b77917e8879680aed17229bf72f263 (patch)
treef064dfaf3387f3ed5d59d69941b90825fe628729 /drivers/infiniband/hw/qib/qib_init.c
parentndisc: Convert use of typedef ctl_table to struct ctl_table (diff)
downloadlinux-dev-8469ba39a6b77917e8879680aed17229bf72f263.tar.xz
linux-dev-8469ba39a6b77917e8879680aed17229bf72f263.zip
IB/qib: Add DCA support
This patch adds DCA cache warming for systems that support DCA. The code uses cpu affinity notification to react to an affinity change from a user mode program like irqbalance and (re-)program the chip accordingly. This notification avoids reading the current cpu on every interrupt. Reviewed-by: Dean Luick <dean.luick@intel.com> Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com> [ Add Kconfig dependency on SMP && GENERIC_HARDIRQS to avoid failure to build due to undefined struct irq_affinity_notify. - Roland ] Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw/qib/qib_init.c')
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index 173f805790da..4b64c885fa0d 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -39,6 +39,9 @@
#include <linux/idr.h>
#include <linux/module.h>
#include <linux/printk.h>
+#ifdef CONFIG_INFINIBAND_QIB_DCA
+#include <linux/dca.h>
+#endif
#include "qib.h"
#include "qib_common.h"
@@ -1158,6 +1161,35 @@ struct pci_driver qib_driver = {
.err_handler = &qib_pci_err_handler,
};
+#ifdef CONFIG_INFINIBAND_QIB_DCA
+
+static int qib_notify_dca(struct notifier_block *, unsigned long, void *);
+static struct notifier_block dca_notifier = {
+ .notifier_call = qib_notify_dca,
+ .next = NULL,
+ .priority = 0
+};
+
+static int qib_notify_dca_device(struct device *device, void *data)
+{
+ struct qib_devdata *dd = dev_get_drvdata(device);
+ unsigned long event = *(unsigned long *)data;
+
+ return dd->f_notify_dca(dd, event);
+}
+
+static int qib_notify_dca(struct notifier_block *nb, unsigned long event,
+ void *p)
+{
+ int rval;
+
+ rval = driver_for_each_device(&qib_driver.driver, NULL,
+ &event, qib_notify_dca_device);
+ return rval ? NOTIFY_BAD : NOTIFY_DONE;
+}
+
+#endif
+
/*
* Do all the generic driver unit- and chip-independent memory
* allocation and initialization.
@@ -1182,6 +1214,9 @@ static int __init qlogic_ib_init(void)
*/
idr_init(&qib_unit_table);
+#ifdef CONFIG_INFINIBAND_QIB_DCA
+ dca_register_notify(&dca_notifier);
+#endif
ret = pci_register_driver(&qib_driver);
if (ret < 0) {
pr_err("Unable to register driver: error %d\n", -ret);
@@ -1194,6 +1229,9 @@ static int __init qlogic_ib_init(void)
goto bail; /* all OK */
bail_unit:
+#ifdef CONFIG_INFINIBAND_QIB_DCA
+ dca_unregister_notify(&dca_notifier);
+#endif
idr_destroy(&qib_unit_table);
destroy_workqueue(qib_cq_wq);
bail_dev:
@@ -1217,6 +1255,9 @@ static void __exit qlogic_ib_cleanup(void)
"Unable to cleanup counter filesystem: error %d\n",
-ret);
+#ifdef CONFIG_INFINIBAND_QIB_DCA
+ dca_unregister_notify(&dca_notifier);
+#endif
pci_unregister_driver(&qib_driver);
destroy_workqueue(qib_cq_wq);