Commit 8469ba39 authored by Mike Marciniszyn's avatar Mike Marciniszyn Committed by Roland Dreier

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: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarMike 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: default avatarRoland Dreier <roland@purestorage.com>
parent fedaf4ff
......@@ -5,3 +5,11 @@ config INFINIBAND_QIB
This is a low-level driver for Intel PCIe QLE InfiniBand host
channel adapters. This driver does not support the Intel
HyperTransport card (model QHT7140).
config INFINIBAND_QIB_DCA
bool "QIB DCA support"
depends on INFINIBAND_QIB && DCA && SMP && GENERIC_HARDIRQS && !(INFINIBAND_QIB=y && DCA=m)
default y
---help---
Setting this enables DCA support on some Intel chip sets
with the iba7322 HCA.
......@@ -428,9 +428,19 @@ struct qib_verbs_txreq {
#define ACTIVITY_TIMER 5
#define MAX_NAME_SIZE 64
#ifdef CONFIG_INFINIBAND_QIB_DCA
struct qib_irq_notify;
#endif
struct qib_msix_entry {
struct msix_entry msix;
void *arg;
#ifdef CONFIG_INFINIBAND_QIB_DCA
int dca;
int rcv;
struct qib_irq_notify *notifier;
#endif
char name[MAX_NAME_SIZE];
cpumask_var_t mask;
};
......@@ -828,6 +838,9 @@ struct qib_devdata {
struct qib_ctxtdata *);
void (*f_writescratch)(struct qib_devdata *, u32);
int (*f_tempsense_rd)(struct qib_devdata *, int regnum);
#ifdef CONFIG_INFINIBAND_QIB_DCA
int (*f_notify_dca)(struct qib_devdata *, unsigned long event);
#endif
char *boardname; /* human readable board info */
......
......@@ -3464,6 +3464,13 @@ static int qib_6120_tempsense_rd(struct qib_devdata *dd, int regnum)
return -ENXIO;
}
#ifdef CONFIG_INFINIBAND_QIB_DCA
static int qib_6120_notify_dca(struct qib_devdata *dd, unsigned long event)
{
return 0;
}
#endif
/* Dummy function, as 6120 boards never disable EEPROM Write */
static int qib_6120_eeprom_wen(struct qib_devdata *dd, int wen)
{
......@@ -3539,6 +3546,9 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev,
dd->f_xgxs_reset = qib_6120_xgxs_reset;
dd->f_writescratch = writescratch;
dd->f_tempsense_rd = qib_6120_tempsense_rd;
#ifdef CONFIG_INFINIBAND_QIB_DCA
dd->f_notify_dca = qib_6120_notify_dca;
#endif
/*
* Do remaining pcie setup and save pcie values in dd.
* Any error printing is already done by the init code.
......
......@@ -4513,6 +4513,13 @@ static int qib_7220_tempsense_rd(struct qib_devdata *dd, int regnum)
return ret;
}
#ifdef CONFIG_INFINIBAND_QIB_DCA
static int qib_7220_notify_dca(struct qib_devdata *dd, unsigned long event)
{
return 0;
}
#endif
/* Dummy function, as 7220 boards never disable EEPROM Write */
static int qib_7220_eeprom_wen(struct qib_devdata *dd, int wen)
{
......@@ -4587,6 +4594,9 @@ struct qib_devdata *qib_init_iba7220_funcs(struct pci_dev *pdev,
dd->f_xgxs_reset = qib_7220_xgxs_reset;
dd->f_writescratch = writescratch;
dd->f_tempsense_rd = qib_7220_tempsense_rd;
#ifdef CONFIG_INFINIBAND_QIB_DCA
dd->f_notify_dca = qib_7220_notify_dca;
#endif
/*
* Do remaining pcie setup and save pcie values in dd.
* Any error printing is already done by the init code.
......
This diff is collapsed.
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment