|
@@ -553,7 +553,6 @@ struct qib_chip_specific {
|
|
u32 updthresh; /* current AvailUpdThld */
|
|
u32 updthresh; /* current AvailUpdThld */
|
|
u32 updthresh_dflt; /* default AvailUpdThld */
|
|
u32 updthresh_dflt; /* default AvailUpdThld */
|
|
u32 r1;
|
|
u32 r1;
|
|
- int irq;
|
|
|
|
u32 num_msix_entries;
|
|
u32 num_msix_entries;
|
|
u32 sdmabufcnt;
|
|
u32 sdmabufcnt;
|
|
u32 lastbuf_for_pio;
|
|
u32 lastbuf_for_pio;
|
|
@@ -756,10 +755,8 @@ static void check_7322_rxe_status(struct qib_pportdata *);
|
|
static u32 __iomem *qib_7322_getsendbuf(struct qib_pportdata *, u64, u32 *);
|
|
static u32 __iomem *qib_7322_getsendbuf(struct qib_pportdata *, u64, u32 *);
|
|
#ifdef CONFIG_INFINIBAND_QIB_DCA
|
|
#ifdef CONFIG_INFINIBAND_QIB_DCA
|
|
static void qib_setup_dca(struct qib_devdata *dd);
|
|
static void qib_setup_dca(struct qib_devdata *dd);
|
|
-static void setup_dca_notifier(struct qib_devdata *dd,
|
|
|
|
- struct qib_msix_entry *m);
|
|
|
|
-static void reset_dca_notifier(struct qib_devdata *dd,
|
|
|
|
- struct qib_msix_entry *m);
|
|
|
|
|
|
+static void setup_dca_notifier(struct qib_devdata *dd, int msixnum);
|
|
|
|
+static void reset_dca_notifier(struct qib_devdata *dd, int msixnum);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -2778,7 +2775,7 @@ static void qib_setup_dca(struct qib_devdata *dd)
|
|
qib_write_kreg(dd, KREG_IDX(DCACtrlB) + i,
|
|
qib_write_kreg(dd, KREG_IDX(DCACtrlB) + i,
|
|
cspec->dca_rcvhdr_ctrl[i]);
|
|
cspec->dca_rcvhdr_ctrl[i]);
|
|
for (i = 0; i < cspec->num_msix_entries; i++)
|
|
for (i = 0; i < cspec->num_msix_entries; i++)
|
|
- setup_dca_notifier(dd, &cspec->msix_entries[i]);
|
|
|
|
|
|
+ setup_dca_notifier(dd, i);
|
|
}
|
|
}
|
|
|
|
|
|
static void qib_irq_notifier_notify(struct irq_affinity_notify *notify,
|
|
static void qib_irq_notifier_notify(struct irq_affinity_notify *notify,
|
|
@@ -2820,49 +2817,41 @@ static void qib_irq_notifier_release(struct kref *ref)
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
-/*
|
|
|
|
- * Disable MSIx interrupt if enabled, call generic MSIx code
|
|
|
|
- * to cleanup, and clear pending MSIx interrupts.
|
|
|
|
- * Used for fallback to INTx, after reset, and when MSIx setup fails.
|
|
|
|
- */
|
|
|
|
-static void qib_7322_nomsix(struct qib_devdata *dd)
|
|
|
|
|
|
+static void qib_7322_free_irq(struct qib_devdata *dd)
|
|
{
|
|
{
|
|
u64 intgranted;
|
|
u64 intgranted;
|
|
- int n;
|
|
|
|
|
|
+ int i;
|
|
|
|
|
|
dd->cspec->main_int_mask = ~0ULL;
|
|
dd->cspec->main_int_mask = ~0ULL;
|
|
- n = dd->cspec->num_msix_entries;
|
|
|
|
- if (n) {
|
|
|
|
- int i;
|
|
|
|
|
|
|
|
- dd->cspec->num_msix_entries = 0;
|
|
|
|
- for (i = 0; i < n; i++) {
|
|
|
|
|
|
+ for (i = 0; i < dd->cspec->num_msix_entries; i++) {
|
|
|
|
+ /* only free IRQs that were allocated */
|
|
|
|
+ if (dd->cspec->msix_entries[i].arg) {
|
|
#ifdef CONFIG_INFINIBAND_QIB_DCA
|
|
#ifdef CONFIG_INFINIBAND_QIB_DCA
|
|
- reset_dca_notifier(dd, &dd->cspec->msix_entries[i]);
|
|
|
|
|
|
+ reset_dca_notifier(dd, i);
|
|
#endif
|
|
#endif
|
|
- irq_set_affinity_hint(
|
|
|
|
- dd->cspec->msix_entries[i].irq, NULL);
|
|
|
|
|
|
+ irq_set_affinity_hint(pci_irq_vector(dd->pcidev, i),
|
|
|
|
+ NULL);
|
|
free_cpumask_var(dd->cspec->msix_entries[i].mask);
|
|
free_cpumask_var(dd->cspec->msix_entries[i].mask);
|
|
- free_irq(dd->cspec->msix_entries[i].irq,
|
|
|
|
- dd->cspec->msix_entries[i].arg);
|
|
|
|
|
|
+ pci_free_irq(dd->pcidev, i,
|
|
|
|
+ dd->cspec->msix_entries[i].arg);
|
|
}
|
|
}
|
|
- qib_nomsix(dd);
|
|
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /* If num_msix_entries was 0, disable the INTx IRQ */
|
|
|
|
+ if (!dd->cspec->num_msix_entries)
|
|
|
|
+ pci_free_irq(dd->pcidev, 0, dd);
|
|
|
|
+ else
|
|
|
|
+ dd->cspec->num_msix_entries = 0;
|
|
|
|
+
|
|
|
|
+ pci_free_irq_vectors(dd->pcidev);
|
|
|
|
+
|
|
/* make sure no MSIx interrupts are left pending */
|
|
/* make sure no MSIx interrupts are left pending */
|
|
intgranted = qib_read_kreg64(dd, kr_intgranted);
|
|
intgranted = qib_read_kreg64(dd, kr_intgranted);
|
|
if (intgranted)
|
|
if (intgranted)
|
|
qib_write_kreg(dd, kr_intgranted, intgranted);
|
|
qib_write_kreg(dd, kr_intgranted, intgranted);
|
|
}
|
|
}
|
|
|
|
|
|
-static void qib_7322_free_irq(struct qib_devdata *dd)
|
|
|
|
-{
|
|
|
|
- if (dd->cspec->irq) {
|
|
|
|
- free_irq(dd->cspec->irq, dd);
|
|
|
|
- dd->cspec->irq = 0;
|
|
|
|
- }
|
|
|
|
- qib_7322_nomsix(dd);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void qib_setup_7322_cleanup(struct qib_devdata *dd)
|
|
static void qib_setup_7322_cleanup(struct qib_devdata *dd)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
@@ -3329,22 +3318,20 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data)
|
|
|
|
|
|
#ifdef CONFIG_INFINIBAND_QIB_DCA
|
|
#ifdef CONFIG_INFINIBAND_QIB_DCA
|
|
|
|
|
|
-static void reset_dca_notifier(struct qib_devdata *dd, struct qib_msix_entry *m)
|
|
|
|
|
|
+static void reset_dca_notifier(struct qib_devdata *dd, int msixnum)
|
|
{
|
|
{
|
|
- if (!m->dca)
|
|
|
|
|
|
+ if (!dd->cspec->msix_entries[msixnum].dca)
|
|
return;
|
|
return;
|
|
- qib_devinfo(dd->pcidev,
|
|
|
|
- "Disabling notifier on HCA %d irq %d\n",
|
|
|
|
- dd->unit,
|
|
|
|
- m->irq);
|
|
|
|
- irq_set_affinity_notifier(
|
|
|
|
- m->irq,
|
|
|
|
- NULL);
|
|
|
|
- m->notifier = NULL;
|
|
|
|
|
|
+
|
|
|
|
+ qib_devinfo(dd->pcidev, "Disabling notifier on HCA %d irq %d\n",
|
|
|
|
+ dd->unit, pci_irq_vector(dd->pcidev, msixnum));
|
|
|
|
+ irq_set_affinity_notifier(pci_irq_vector(dd->pcidev, msixnum), NULL);
|
|
|
|
+ dd->cspec->msix_entries[msixnum].notifier = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
-static void setup_dca_notifier(struct qib_devdata *dd, struct qib_msix_entry *m)
|
|
|
|
|
|
+static void setup_dca_notifier(struct qib_devdata *dd, int msixnum)
|
|
{
|
|
{
|
|
|
|
+ struct qib_msix_entry *m = &dd->cspec->msix_entries[msixnum];
|
|
struct qib_irq_notify *n;
|
|
struct qib_irq_notify *n;
|
|
|
|
|
|
if (!m->dca)
|
|
if (!m->dca)
|
|
@@ -3354,7 +3341,7 @@ static void setup_dca_notifier(struct qib_devdata *dd, struct qib_msix_entry *m)
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
m->notifier = n;
|
|
m->notifier = n;
|
|
- n->notify.irq = m->irq;
|
|
|
|
|
|
+ n->notify.irq = pci_irq_vector(dd->pcidev, msixnum);
|
|
n->notify.notify = qib_irq_notifier_notify;
|
|
n->notify.notify = qib_irq_notifier_notify;
|
|
n->notify.release = qib_irq_notifier_release;
|
|
n->notify.release = qib_irq_notifier_release;
|
|
n->arg = m->arg;
|
|
n->arg = m->arg;
|
|
@@ -3415,22 +3402,17 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend)
|
|
if (!dd->cspec->num_msix_entries) {
|
|
if (!dd->cspec->num_msix_entries) {
|
|
/* Try to get INTx interrupt */
|
|
/* Try to get INTx interrupt */
|
|
try_intx:
|
|
try_intx:
|
|
- if (!dd->pcidev->irq) {
|
|
|
|
- qib_dev_err(dd,
|
|
|
|
- "irq is 0, BIOS error? Interrupts won't work\n");
|
|
|
|
- goto bail;
|
|
|
|
- }
|
|
|
|
- ret = request_irq(dd->pcidev->irq, qib_7322intr,
|
|
|
|
- IRQF_SHARED, QIB_DRV_NAME, dd);
|
|
|
|
|
|
+ ret = pci_request_irq(dd->pcidev, 0, qib_7322intr, NULL, dd,
|
|
|
|
+ QIB_DRV_NAME);
|
|
if (ret) {
|
|
if (ret) {
|
|
- qib_dev_err(dd,
|
|
|
|
|
|
+ qib_dev_err(
|
|
|
|
+ dd,
|
|
"Couldn't setup INTx interrupt (irq=%d): %d\n",
|
|
"Couldn't setup INTx interrupt (irq=%d): %d\n",
|
|
- dd->pcidev->irq, ret);
|
|
|
|
- goto bail;
|
|
|
|
|
|
+ pci_irq_vector(dd->pcidev, 0), ret);
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
- dd->cspec->irq = dd->pcidev->irq;
|
|
|
|
dd->cspec->main_int_mask = ~0ULL;
|
|
dd->cspec->main_int_mask = ~0ULL;
|
|
- goto bail;
|
|
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
/* Try to get MSIx interrupts */
|
|
/* Try to get MSIx interrupts */
|
|
@@ -3458,10 +3440,6 @@ try_intx:
|
|
#ifdef CONFIG_INFINIBAND_QIB_DCA
|
|
#ifdef CONFIG_INFINIBAND_QIB_DCA
|
|
int dca = 0;
|
|
int dca = 0;
|
|
#endif
|
|
#endif
|
|
-
|
|
|
|
- dd->cspec->msix_entries[msixnum].
|
|
|
|
- name[sizeof(dd->cspec->msix_entries[msixnum].name) - 1]
|
|
|
|
- = '\0';
|
|
|
|
if (i < ARRAY_SIZE(irq_table)) {
|
|
if (i < ARRAY_SIZE(irq_table)) {
|
|
if (irq_table[i].port) {
|
|
if (irq_table[i].port) {
|
|
/* skip if for a non-configured port */
|
|
/* skip if for a non-configured port */
|
|
@@ -3475,11 +3453,10 @@ try_intx:
|
|
#endif
|
|
#endif
|
|
lsb = irq_table[i].lsb;
|
|
lsb = irq_table[i].lsb;
|
|
handler = irq_table[i].handler;
|
|
handler = irq_table[i].handler;
|
|
- snprintf(dd->cspec->msix_entries[msixnum].name,
|
|
|
|
- sizeof(dd->cspec->msix_entries[msixnum].name)
|
|
|
|
- - 1,
|
|
|
|
- QIB_DRV_NAME "%d%s", dd->unit,
|
|
|
|
- irq_table[i].name);
|
|
|
|
|
|
+ ret = pci_request_irq(dd->pcidev, msixnum, handler,
|
|
|
|
+ NULL, arg, QIB_DRV_NAME "%d%s",
|
|
|
|
+ dd->unit,
|
|
|
|
+ irq_table[i].name);
|
|
} else {
|
|
} else {
|
|
unsigned ctxt;
|
|
unsigned ctxt;
|
|
|
|
|
|
@@ -3495,37 +3472,25 @@ try_intx:
|
|
#endif
|
|
#endif
|
|
lsb = QIB_I_RCVAVAIL_LSB + ctxt;
|
|
lsb = QIB_I_RCVAVAIL_LSB + ctxt;
|
|
handler = qib_7322pintr;
|
|
handler = qib_7322pintr;
|
|
- snprintf(dd->cspec->msix_entries[msixnum].name,
|
|
|
|
- sizeof(dd->cspec->msix_entries[msixnum].name)
|
|
|
|
- - 1,
|
|
|
|
- QIB_DRV_NAME "%d (kctx)", dd->unit);
|
|
|
|
|
|
+ ret = pci_request_irq(dd->pcidev, msixnum, handler,
|
|
|
|
+ NULL, arg,
|
|
|
|
+ QIB_DRV_NAME "%d (kctx)",
|
|
|
|
+ dd->unit);
|
|
}
|
|
}
|
|
|
|
|
|
- dd->cspec->msix_entries[msixnum].irq = pci_irq_vector(
|
|
|
|
- dd->pcidev, msixnum);
|
|
|
|
- if (dd->cspec->msix_entries[msixnum].irq < 0) {
|
|
|
|
- qib_dev_err(dd,
|
|
|
|
- "Couldn't get MSIx irq (vec=%d): %d\n",
|
|
|
|
- msixnum,
|
|
|
|
- dd->cspec->msix_entries[msixnum].irq);
|
|
|
|
- qib_7322_nomsix(dd);
|
|
|
|
- goto try_intx;
|
|
|
|
- }
|
|
|
|
- ret = request_irq(dd->cspec->msix_entries[msixnum].irq,
|
|
|
|
- handler, 0,
|
|
|
|
- dd->cspec->msix_entries[msixnum].name,
|
|
|
|
- arg);
|
|
|
|
if (ret) {
|
|
if (ret) {
|
|
/*
|
|
/*
|
|
* Shouldn't happen since the enable said we could
|
|
* Shouldn't happen since the enable said we could
|
|
* have as many as we are trying to setup here.
|
|
* have as many as we are trying to setup here.
|
|
*/
|
|
*/
|
|
qib_dev_err(dd,
|
|
qib_dev_err(dd,
|
|
- "Couldn't setup MSIx interrupt (vec=%d, irq=%d): %d\n",
|
|
|
|
- msixnum,
|
|
|
|
- dd->cspec->msix_entries[msixnum].irq,
|
|
|
|
- ret);
|
|
|
|
- qib_7322_nomsix(dd);
|
|
|
|
|
|
+ "Couldn't setup MSIx interrupt (vec=%d, irq=%d): %d\n",
|
|
|
|
+ msixnum,
|
|
|
|
+ pci_irq_vector(dd->pcidev, msixnum),
|
|
|
|
+ ret);
|
|
|
|
+ qib_7322_free_irq(dd);
|
|
|
|
+ pci_alloc_irq_vectors(dd->pcidev, 1, 1,
|
|
|
|
+ PCI_IRQ_LEGACY);
|
|
goto try_intx;
|
|
goto try_intx;
|
|
}
|
|
}
|
|
dd->cspec->msix_entries[msixnum].arg = arg;
|
|
dd->cspec->msix_entries[msixnum].arg = arg;
|
|
@@ -3559,7 +3524,7 @@ try_intx:
|
|
dd->cspec->msix_entries[msixnum].mask);
|
|
dd->cspec->msix_entries[msixnum].mask);
|
|
}
|
|
}
|
|
irq_set_affinity_hint(
|
|
irq_set_affinity_hint(
|
|
- dd->cspec->msix_entries[msixnum].irq,
|
|
|
|
|
|
+ pci_irq_vector(dd->pcidev, msixnum),
|
|
dd->cspec->msix_entries[msixnum].mask);
|
|
dd->cspec->msix_entries[msixnum].mask);
|
|
}
|
|
}
|
|
msixnum++;
|
|
msixnum++;
|
|
@@ -3570,7 +3535,6 @@ try_intx:
|
|
dd->cspec->main_int_mask = mask;
|
|
dd->cspec->main_int_mask = mask;
|
|
tasklet_init(&dd->error_tasklet, qib_error_tasklet,
|
|
tasklet_init(&dd->error_tasklet, qib_error_tasklet,
|
|
(unsigned long)dd);
|
|
(unsigned long)dd);
|
|
-bail:;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -3674,8 +3638,9 @@ static int qib_do_7322_reset(struct qib_devdata *dd)
|
|
/* no interrupts till re-initted */
|
|
/* no interrupts till re-initted */
|
|
qib_7322_set_intr_state(dd, 0);
|
|
qib_7322_set_intr_state(dd, 0);
|
|
|
|
|
|
|
|
+ qib_7322_free_irq(dd);
|
|
|
|
+
|
|
if (msix_entries) {
|
|
if (msix_entries) {
|
|
- qib_7322_nomsix(dd);
|
|
|
|
/* can be up to 512 bytes, too big for stack */
|
|
/* can be up to 512 bytes, too big for stack */
|
|
msix_vecsave = kmalloc(2 * dd->cspec->num_msix_entries *
|
|
msix_vecsave = kmalloc(2 * dd->cspec->num_msix_entries *
|
|
sizeof(u64), GFP_KERNEL);
|
|
sizeof(u64), GFP_KERNEL);
|
|
@@ -3765,11 +3730,11 @@ static int qib_do_7322_reset(struct qib_devdata *dd)
|
|
write_7322_init_portregs(&dd->pport[i]);
|
|
write_7322_init_portregs(&dd->pport[i]);
|
|
write_7322_initregs(dd);
|
|
write_7322_initregs(dd);
|
|
|
|
|
|
- if (qib_pcie_params(dd, dd->lbus_width,
|
|
|
|
- &dd->cspec->num_msix_entries))
|
|
|
|
|
|
+ if (qib_pcie_params(dd, dd->lbus_width, &msix_entries))
|
|
qib_dev_err(dd,
|
|
qib_dev_err(dd,
|
|
"Reset failed to setup PCIe or interrupts; continuing anyway\n");
|
|
"Reset failed to setup PCIe or interrupts; continuing anyway\n");
|
|
|
|
|
|
|
|
+ dd->cspec->num_msix_entries = msix_entries;
|
|
qib_setup_7322_interrupt(dd, 1);
|
|
qib_setup_7322_interrupt(dd, 1);
|
|
|
|
|
|
for (i = 0; i < dd->num_pports; ++i) {
|
|
for (i = 0; i < dd->num_pports; ++i) {
|
|
@@ -5197,8 +5162,9 @@ static int qib_7322_intr_fallback(struct qib_devdata *dd)
|
|
|
|
|
|
qib_devinfo(dd->pcidev,
|
|
qib_devinfo(dd->pcidev,
|
|
"MSIx interrupt not detected, trying INTx interrupts\n");
|
|
"MSIx interrupt not detected, trying INTx interrupts\n");
|
|
- qib_7322_nomsix(dd);
|
|
|
|
- qib_enable_intx(dd);
|
|
|
|
|
|
+ qib_7322_free_irq(dd);
|
|
|
|
+ if (pci_alloc_irq_vectors(dd->pcidev, 1, 1, PCI_IRQ_LEGACY) < 0)
|
|
|
|
+ qib_dev_err(dd, "Failed to enable INTx\n");
|
|
qib_setup_7322_interrupt(dd, 0);
|
|
qib_setup_7322_interrupt(dd, 0);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|