diff options
-rw-r--r-- | drivers/infiniband/hw/qib/qib.h | 8 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_7220.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_iba6120.c | 35 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_iba7220.c | 52 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_iba7322.c | 158 | ||||
-rw-r--r-- | drivers/infiniband/hw/qib/qib_pcie.c | 125 |
6 files changed, 120 insertions, 259 deletions
diff --git a/drivers/infiniband/hw/qib/qib.h b/drivers/infiniband/hw/qib/qib.h index f9e1c69603a5..1167a9c1776b 100644 --- a/drivers/infiniband/hw/qib/qib.h +++ b/drivers/infiniband/hw/qib/qib.h @@ -443,14 +443,12 @@ struct qib_irq_notify; #endif struct qib_msix_entry { - int irq; 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; }; @@ -1434,10 +1432,8 @@ int qib_pcie_ddinit(struct qib_devdata *, struct pci_dev *, const struct pci_device_id *); void qib_pcie_ddcleanup(struct qib_devdata *); int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent); -int qib_reinit_intr(struct qib_devdata *); -void qib_enable_intx(struct qib_devdata *dd); -void qib_nomsi(struct qib_devdata *); -void qib_nomsix(struct qib_devdata *); +void qib_free_irq(struct qib_devdata *dd); +int qib_reinit_intr(struct qib_devdata *dd); void qib_pcie_getcmd(struct qib_devdata *, u16 *, u8 *, u8 *); void qib_pcie_reenable(struct qib_devdata *, u16, u8, u8); /* interrupts for device */ diff --git a/drivers/infiniband/hw/qib/qib_7220.h b/drivers/infiniband/hw/qib/qib_7220.h index a5356cb4252e..4ec3dc1fbfb4 100644 --- a/drivers/infiniband/hw/qib/qib_7220.h +++ b/drivers/infiniband/hw/qib/qib_7220.h @@ -67,7 +67,6 @@ struct qib_chip_specific { u32 lastbuf_for_pio; u32 updthresh; /* current AvailUpdThld */ u32 updthresh_dflt; /* default AvailUpdThld */ - int irq; u8 presets_needed; u8 relock_timer_active; char emsgbuf[128]; diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 3259a60e4f4f..c4a4c57e0f0a 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -245,7 +245,6 @@ struct qib_chip_specific { u64 iblnkerrsnap; u64 ibcctrl; /* shadow for kr_ibcctrl */ u32 lastlinkrecov; /* link recovery issue */ - int irq; u32 cntrnamelen; u32 portcntrnamelen; u32 ncntrs; @@ -1485,15 +1484,6 @@ static void qib_6120_setup_setextled(struct qib_pportdata *ppd, u32 on) spin_unlock_irqrestore(&dd->cspec->gpio_lock, flags); } -static void qib_6120_free_irq(struct qib_devdata *dd) -{ - if (dd->cspec->irq) { - free_irq(dd->cspec->irq, dd); - dd->cspec->irq = 0; - } - qib_nomsi(dd); -} - /** * qib_6120_setup_cleanup - clean up any per-chip chip-specific stuff * @dd: the qlogic_ib device @@ -1502,7 +1492,7 @@ static void qib_6120_free_irq(struct qib_devdata *dd) */ static void qib_6120_setup_cleanup(struct qib_devdata *dd) { - qib_6120_free_irq(dd); + qib_free_irq(dd); kfree(dd->cspec->cntrs); kfree(dd->cspec->portcntrs); if (dd->cspec->dummy_hdrq) { @@ -1706,6 +1696,8 @@ bail: */ static void qib_setup_6120_interrupt(struct qib_devdata *dd) { + int ret; + /* * If the chip supports added error indication via GPIO pins, * enable interrupts on those bits so the interrupt routine @@ -1719,19 +1711,12 @@ static void qib_setup_6120_interrupt(struct qib_devdata *dd) qib_write_kreg(dd, kr_gpio_mask, dd->cspec->gpio_mask); } - if (!dd->cspec->irq) + ret = pci_request_irq(dd->pcidev, 0, qib_6120intr, NULL, dd, + QIB_DRV_NAME); + if (ret) qib_dev_err(dd, - "irq is 0, BIOS error? Interrupts won't work\n"); - else { - int ret; - - ret = request_irq(dd->cspec->irq, qib_6120intr, 0, - QIB_DRV_NAME, dd); - if (ret) - qib_dev_err(dd, - "Couldn't setup interrupt (irq=%d): %d\n", - dd->cspec->irq, ret); - } + "Couldn't setup interrupt (irq=%d): %d\n", + pci_irq_vector(dd->pcidev, 0), ret); } /** @@ -3490,7 +3475,7 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev, dd->f_bringup_serdes = qib_6120_bringup_serdes; dd->f_cleanup = qib_6120_setup_cleanup; dd->f_clear_tids = qib_6120_clear_tids; - dd->f_free_irq = qib_6120_free_irq; + dd->f_free_irq = qib_free_irq; dd->f_get_base_info = qib_6120_get_base_info; dd->f_get_msgheader = qib_6120_get_msgheader; dd->f_getsendbuf = qib_6120_getsendbuf; @@ -3559,8 +3544,6 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev, if (qib_pcie_params(dd, 8, NULL)) qib_dev_err(dd, "Failed to setup PCIe or interrupts; continuing anyway\n"); - dd->cspec->irq = pdev->irq; /* save IRQ */ - /* clear diagctrl register, in case diags were running and crashed */ qib_write_kreg(dd, kr_hwdiagctrl, 0); diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 04bdd3d487b1..78ce79be4120 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -1780,15 +1780,6 @@ static void qib_setup_7220_setextled(struct qib_pportdata *ppd, u32 on) qib_write_kreg(dd, kr_rcvpktledcnt, ledblink); } -static void qib_7220_free_irq(struct qib_devdata *dd) -{ - if (dd->cspec->irq) { - free_irq(dd->cspec->irq, dd); - dd->cspec->irq = 0; - } - qib_nomsi(dd); -} - /* * qib_setup_7220_cleanup - clean up any per-chip chip-specific stuff * @dd: the qlogic_ib device @@ -1798,7 +1789,7 @@ static void qib_7220_free_irq(struct qib_devdata *dd) */ static void qib_setup_7220_cleanup(struct qib_devdata *dd) { - qib_7220_free_irq(dd); + qib_free_irq(dd); kfree(dd->cspec->cntrs); kfree(dd->cspec->portcntrs); } @@ -2026,20 +2017,14 @@ bail: */ static void qib_setup_7220_interrupt(struct qib_devdata *dd) { - if (!dd->cspec->irq) - qib_dev_err(dd, - "irq is 0, BIOS error? Interrupts won't work\n"); - else { - int ret = request_irq(dd->cspec->irq, qib_7220intr, - dd->msi_lo ? 0 : IRQF_SHARED, - QIB_DRV_NAME, dd); + int ret; - if (ret) - qib_dev_err(dd, - "Couldn't setup %s interrupt (irq=%d): %d\n", - dd->msi_lo ? "MSI" : "INTx", - dd->cspec->irq, ret); - } + ret = pci_request_irq(dd->pcidev, 0, qib_7220intr, NULL, dd, + QIB_DRV_NAME); + if (ret) + qib_dev_err(dd, "Couldn't setup %s interrupt (irq=%d): %d\n", + dd->pcidev->msi_enabled ? "MSI" : "INTx", + pci_irq_vector(dd->pcidev, 0), ret); } /** @@ -3302,16 +3287,12 @@ static int qib_7220_intr_fallback(struct qib_devdata *dd) return 0; qib_devinfo(dd->pcidev, - "MSI interrupt not detected, trying INTx interrupts\n"); - qib_7220_free_irq(dd); - qib_enable_intx(dd); - /* - * Some newer kernels require free_irq before disable_msi, - * and irq can be changed during disable and INTx enable - * and we need to therefore use the pcidev->irq value, - * not our saved MSI value. - */ - dd->cspec->irq = dd->pcidev->irq; + "MSI interrupt not detected, trying INTx interrupts\n"); + + qib_free_irq(dd); + dd->msi_lo = 0; + if (pci_alloc_irq_vectors(dd->pcidev, 1, 1, PCI_IRQ_LEGACY) < 0) + qib_dev_err(dd, "Failed to enable INTx\n"); qib_setup_7220_interrupt(dd); return 1; } @@ -4535,7 +4516,7 @@ struct qib_devdata *qib_init_iba7220_funcs(struct pci_dev *pdev, dd->f_bringup_serdes = qib_7220_bringup_serdes; dd->f_cleanup = qib_setup_7220_cleanup; dd->f_clear_tids = qib_7220_clear_tids; - dd->f_free_irq = qib_7220_free_irq; + dd->f_free_irq = qib_free_irq; dd->f_get_base_info = qib_7220_get_base_info; dd->f_get_msgheader = qib_7220_get_msgheader; dd->f_getsendbuf = qib_7220_getsendbuf; @@ -4618,9 +4599,6 @@ struct qib_devdata *qib_init_iba7220_funcs(struct pci_dev *pdev, qib_dev_err(dd, "Failed to setup PCIe or interrupts; continuing anyway\n"); - /* save IRQ for possible later use */ - dd->cspec->irq = pdev->irq; - if (qib_read_kreg64(dd, kr_hwerrstatus) & QLOGIC_IB_HWE_SERDESPLLFAILED) qib_write_kreg(dd, kr_hwerrclear, diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 14cadf6d6214..4d02cffe4e03 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -553,7 +553,6 @@ struct qib_chip_specific { u32 updthresh; /* current AvailUpdThld */ u32 updthresh_dflt; /* default AvailUpdThld */ u32 r1; - int irq; u32 num_msix_entries; u32 sdmabufcnt; 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 *); #ifdef CONFIG_INFINIBAND_QIB_DCA 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 /** @@ -2778,7 +2775,7 @@ static void qib_setup_dca(struct qib_devdata *dd) qib_write_kreg(dd, KREG_IDX(DCACtrlB) + i, cspec->dca_rcvhdr_ctrl[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, @@ -2820,49 +2817,41 @@ static void qib_irq_notifier_release(struct kref *ref) } #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; - int n; + int i; 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 - reset_dca_notifier(dd, &dd->cspec->msix_entries[i]); + reset_dca_notifier(dd, i); #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_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 */ intgranted = qib_read_kreg64(dd, kr_intgranted); if (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) { int i; @@ -3329,22 +3318,20 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data) #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; - 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; if (!m->dca) @@ -3354,7 +3341,7 @@ static void setup_dca_notifier(struct qib_devdata *dd, struct qib_msix_entry *m) int ret; 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.release = qib_irq_notifier_release; 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) { /* Try to get INTx interrupt */ 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) { - qib_dev_err(dd, + qib_dev_err( + dd, "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; - goto bail; + return; } /* Try to get MSIx interrupts */ @@ -3458,10 +3440,6 @@ try_intx: #ifdef CONFIG_INFINIBAND_QIB_DCA int dca = 0; #endif - - dd->cspec->msix_entries[msixnum]. - name[sizeof(dd->cspec->msix_entries[msixnum].name) - 1] - = '\0'; if (i < ARRAY_SIZE(irq_table)) { if (irq_table[i].port) { /* skip if for a non-configured port */ @@ -3475,11 +3453,10 @@ try_intx: #endif lsb = irq_table[i].lsb; 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 { unsigned ctxt; @@ -3495,37 +3472,25 @@ try_intx: #endif lsb = QIB_I_RCVAVAIL_LSB + ctxt; 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) { /* * Shouldn't happen since the enable said we could * have as many as we are trying to setup here. */ 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; } dd->cspec->msix_entries[msixnum].arg = arg; @@ -3559,7 +3524,7 @@ try_intx: dd->cspec->msix_entries[msixnum].mask); } irq_set_affinity_hint( - dd->cspec->msix_entries[msixnum].irq, + pci_irq_vector(dd->pcidev, msixnum), dd->cspec->msix_entries[msixnum].mask); } msixnum++; @@ -3570,7 +3535,6 @@ try_intx: dd->cspec->main_int_mask = mask; tasklet_init(&dd->error_tasklet, qib_error_tasklet, (unsigned long)dd); -bail:; } /** @@ -3674,8 +3638,9 @@ static int qib_do_7322_reset(struct qib_devdata *dd) /* no interrupts till re-initted */ qib_7322_set_intr_state(dd, 0); + qib_7322_free_irq(dd); + if (msix_entries) { - qib_7322_nomsix(dd); /* can be up to 512 bytes, too big for stack */ msix_vecsave = kmalloc(2 * dd->cspec->num_msix_entries * 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_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, "Reset failed to setup PCIe or interrupts; continuing anyway\n"); + dd->cspec->num_msix_entries = msix_entries; qib_setup_7322_interrupt(dd, 1); 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, "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); return 1; } diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index d90403e31a9d..6f4cc268926c 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -193,7 +193,7 @@ void qib_pcie_ddcleanup(struct qib_devdata *dd) * chip reset (the kernel PCI infrastructure doesn't yet handle that * correctly. */ -static void qib_msi_setup(struct qib_devdata *dd, int pos) +static void qib_cache_msi_info(struct qib_devdata *dd, int pos) { struct pci_dev *pdev = dd->pcidev; u16 control; @@ -208,64 +208,39 @@ static void qib_msi_setup(struct qib_devdata *dd, int pos) &dd->msi_data); } -static int qib_allocate_irqs(struct qib_devdata *dd, u32 maxvec) -{ - unsigned int flags = PCI_IRQ_LEGACY; - - /* Check our capabilities */ - if (dd->pcidev->msix_cap) { - flags |= PCI_IRQ_MSIX; - } else { - if (dd->pcidev->msi_cap) { - flags |= PCI_IRQ_MSI; - /* Get msi_lo and msi_hi */ - qib_msi_setup(dd, dd->pcidev->msi_cap); - } - } - - if (!(flags & (PCI_IRQ_MSIX | PCI_IRQ_MSI))) - qib_dev_err(dd, "No PCI MSI or MSIx capability!\n"); - - return pci_alloc_irq_vectors(dd->pcidev, 1, maxvec, flags); -} - int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent) { u16 linkstat, speed; int nvec; int maxvec; - int ret = 0; + unsigned int flags = PCI_IRQ_MSIX | PCI_IRQ_MSI; if (!pci_is_pcie(dd->pcidev)) { qib_dev_err(dd, "Can't find PCI Express capability!\n"); /* set up something... */ dd->lbus_width = 1; dd->lbus_speed = 2500; /* Gen1, 2.5GHz */ - ret = -1; + nvec = -1; goto bail; } + if (dd->flags & QIB_HAS_INTX) + flags |= PCI_IRQ_LEGACY; maxvec = (nent && *nent) ? *nent : 1; - nvec = qib_allocate_irqs(dd, maxvec); - if (nvec < 0) { - ret = nvec; + nvec = pci_alloc_irq_vectors(dd->pcidev, 1, maxvec, flags); + if (nvec < 0) goto bail; - } /* - * If nent exists, make sure to record how many vectors were allocated + * If nent exists, make sure to record how many vectors were allocated. + * If msix_enabled is false, return 0 so the fallback code works + * correctly. */ - if (nent) { - *nent = nvec; + if (nent) + *nent = !dd->pcidev->msix_enabled ? 0 : nvec; - /* - * If we requested (nent) MSIX, but msix_enabled is not set, - * pci_alloc_irq_vectors() enabled INTx. - */ - if (!dd->pcidev->msix_enabled) - qib_dev_err(dd, - "no msix vectors allocated, using INTx\n"); - } + if (dd->pcidev->msi_enabled) + qib_cache_msi_info(dd, dd->pcidev->msi_cap); pcie_capability_read_word(dd->pcidev, PCI_EXP_LNKSTA, &linkstat); /* @@ -306,7 +281,21 @@ bail: /* fill in string, even on errors */ snprintf(dd->lbus_info, sizeof(dd->lbus_info), "PCIe,%uMHz,x%u\n", dd->lbus_speed, dd->lbus_width); - return ret; + return nvec < 0 ? nvec : 0; +} + +/** + * qib_free_irq - Cleanup INTx and MSI interrupts + * @dd: valid pointer to qib dev data + * + * Since cleanup for INTx and MSI interrupts is trivial, have a common + * routine. + * + */ +void qib_free_irq(struct qib_devdata *dd) +{ + pci_free_irq(dd->pcidev, 0, dd); + pci_free_irq_vectors(dd->pcidev); } /* @@ -351,10 +340,10 @@ int qib_reinit_intr(struct qib_devdata *dd) dd->msi_data); ret = 1; bail: - if (!ret && (dd->flags & QIB_HAS_INTX)) { - qib_enable_intx(dd); + qib_free_irq(dd); + + if (!ret && (dd->flags & QIB_HAS_INTX)) ret = 1; - } /* and now set the pci master bit again */ pci_set_master(dd->pcidev); @@ -363,56 +352,6 @@ bail: } /* - * Disable msi interrupt if enabled, and clear msi_lo. - * This is used primarily for the fallback to INTx, but - * is also used in reinit after reset, and during cleanup. - */ -void qib_nomsi(struct qib_devdata *dd) -{ - dd->msi_lo = 0; - pci_free_irq_vectors(dd->pcidev); -} - -/* - * Same as qib_nosmi, but for MSIx. - */ -void qib_nomsix(struct qib_devdata *dd) -{ - pci_free_irq_vectors(dd->pcidev); -} - -/* - * Similar to pci_intx(pdev, 1), except that we make sure - * msi(x) is off. - */ -void qib_enable_intx(struct qib_devdata *dd) -{ - u16 cw, new; - int pos; - struct pci_dev *pdev = dd->pcidev; - - if (pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_LEGACY) < 0) - qib_dev_err(dd, "Failed to enable INTx\n"); - - pos = pdev->msi_cap; - if (pos) { - /* then turn off MSI */ - pci_read_config_word(pdev, pos + PCI_MSI_FLAGS, &cw); - new = cw & ~PCI_MSI_FLAGS_ENABLE; - if (new != cw) - pci_write_config_word(pdev, pos + PCI_MSI_FLAGS, new); - } - pos = pdev->msix_cap; - if (pos) { - /* then turn off MSIx */ - pci_read_config_word(pdev, pos + PCI_MSIX_FLAGS, &cw); - new = cw & ~PCI_MSIX_FLAGS_ENABLE; - if (new != cw) - pci_write_config_word(pdev, pos + PCI_MSIX_FLAGS, new); - } -} - -/* * These two routines are helper routines for the device reset code * to move all the pcie code out of the chip-specific driver code. */ |