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 ...@@ -5,3 +5,11 @@ config INFINIBAND_QIB
This is a low-level driver for Intel PCIe QLE InfiniBand host This is a low-level driver for Intel PCIe QLE InfiniBand host
channel adapters. This driver does not support the Intel channel adapters. This driver does not support the Intel
HyperTransport card (model QHT7140). 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 { ...@@ -428,9 +428,19 @@ struct qib_verbs_txreq {
#define ACTIVITY_TIMER 5 #define ACTIVITY_TIMER 5
#define MAX_NAME_SIZE 64 #define MAX_NAME_SIZE 64
#ifdef CONFIG_INFINIBAND_QIB_DCA
struct qib_irq_notify;
#endif
struct qib_msix_entry { struct qib_msix_entry {
struct msix_entry msix; struct msix_entry msix;
void *arg; void *arg;
#ifdef CONFIG_INFINIBAND_QIB_DCA
int dca;
int rcv;
struct qib_irq_notify *notifier;
#endif
char name[MAX_NAME_SIZE]; char name[MAX_NAME_SIZE];
cpumask_var_t mask; cpumask_var_t mask;
}; };
...@@ -828,6 +838,9 @@ struct qib_devdata { ...@@ -828,6 +838,9 @@ struct qib_devdata {
struct qib_ctxtdata *); struct qib_ctxtdata *);
void (*f_writescratch)(struct qib_devdata *, u32); void (*f_writescratch)(struct qib_devdata *, u32);
int (*f_tempsense_rd)(struct qib_devdata *, int regnum); 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 */ char *boardname; /* human readable board info */
......
...@@ -3464,6 +3464,13 @@ static int qib_6120_tempsense_rd(struct qib_devdata *dd, int regnum) ...@@ -3464,6 +3464,13 @@ static int qib_6120_tempsense_rd(struct qib_devdata *dd, int regnum)
return -ENXIO; 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 */ /* Dummy function, as 6120 boards never disable EEPROM Write */
static int qib_6120_eeprom_wen(struct qib_devdata *dd, int wen) 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, ...@@ -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_xgxs_reset = qib_6120_xgxs_reset;
dd->f_writescratch = writescratch; dd->f_writescratch = writescratch;
dd->f_tempsense_rd = qib_6120_tempsense_rd; 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. * Do remaining pcie setup and save pcie values in dd.
* Any error printing is already done by the init code. * 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) ...@@ -4513,6 +4513,13 @@ static int qib_7220_tempsense_rd(struct qib_devdata *dd, int regnum)
return ret; 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 */ /* Dummy function, as 7220 boards never disable EEPROM Write */
static int qib_7220_eeprom_wen(struct qib_devdata *dd, int wen) 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, ...@@ -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_xgxs_reset = qib_7220_xgxs_reset;
dd->f_writescratch = writescratch; dd->f_writescratch = writescratch;
dd->f_tempsense_rd = qib_7220_tempsense_rd; 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. * Do remaining pcie setup and save pcie values in dd.
* Any error printing is already done by the init code. * Any error printing is already done by the init code.
......
This diff is collapsed.
...@@ -39,6 +39,9 @@ ...@@ -39,6 +39,9 @@
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/printk.h> #include <linux/printk.h>
#ifdef CONFIG_INFINIBAND_QIB_DCA
#include <linux/dca.h>
#endif
#include "qib.h" #include "qib.h"
#include "qib_common.h" #include "qib_common.h"
...@@ -1158,6 +1161,35 @@ struct pci_driver qib_driver = { ...@@ -1158,6 +1161,35 @@ struct pci_driver qib_driver = {
.err_handler = &qib_pci_err_handler, .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 * Do all the generic driver unit- and chip-independent memory
* allocation and initialization. * allocation and initialization.
...@@ -1182,6 +1214,9 @@ static int __init qlogic_ib_init(void) ...@@ -1182,6 +1214,9 @@ static int __init qlogic_ib_init(void)
*/ */
idr_init(&qib_unit_table); idr_init(&qib_unit_table);
#ifdef CONFIG_INFINIBAND_QIB_DCA
dca_register_notify(&dca_notifier);
#endif
ret = pci_register_driver(&qib_driver); ret = pci_register_driver(&qib_driver);
if (ret < 0) { if (ret < 0) {
pr_err("Unable to register driver: error %d\n", -ret); pr_err("Unable to register driver: error %d\n", -ret);
...@@ -1194,6 +1229,9 @@ static int __init qlogic_ib_init(void) ...@@ -1194,6 +1229,9 @@ static int __init qlogic_ib_init(void)
goto bail; /* all OK */ goto bail; /* all OK */
bail_unit: bail_unit:
#ifdef CONFIG_INFINIBAND_QIB_DCA
dca_unregister_notify(&dca_notifier);
#endif
idr_destroy(&qib_unit_table); idr_destroy(&qib_unit_table);
destroy_workqueue(qib_cq_wq); destroy_workqueue(qib_cq_wq);
bail_dev: bail_dev:
...@@ -1217,6 +1255,9 @@ static void __exit qlogic_ib_cleanup(void) ...@@ -1217,6 +1255,9 @@ static void __exit qlogic_ib_cleanup(void)
"Unable to cleanup counter filesystem: error %d\n", "Unable to cleanup counter filesystem: error %d\n",
-ret); -ret);
#ifdef CONFIG_INFINIBAND_QIB_DCA
dca_unregister_notify(&dca_notifier);
#endif
pci_unregister_driver(&qib_driver); pci_unregister_driver(&qib_driver);
destroy_workqueue(qib_cq_wq); 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