Commit c4bc6156 authored by Michael J. Ruhl's avatar Michael J. Ruhl Committed by Doug Ledford

IB/qib: Update QIB to use the latest PCI API

The QIB PCI IRQ code uses an obsolete PCI API.  Updating the code to use
the new PCI IRQ API and any necessary changes because of the new API.
Reviewed-by: default avatarSebastian Sanchez <sebastian.sanchez@intel.com>
Signed-off-by: default avatarMichael J. Ruhl <michael.j.ruhl@intel.com>
Signed-off-by: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 4029e2a3
......@@ -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 */
......
......@@ -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];
......
......@@ -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 @@ static irqreturn_t qib_6120intr(int irq, void *data)
*/
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)
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);
ret = pci_request_irq(dd->pcidev, 0, qib_6120intr, NULL, dd,
QIB_DRV_NAME);
if (ret)
qib_dev_err(dd,
"Couldn't setup interrupt (irq=%d): %d\n",
dd->cspec->irq, ret);
}
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);
......
......@@ -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 @@ static irqreturn_t qib_7220intr(int irq, void *data)
*/
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;
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->msi_lo ? "MSI" : "INTx",
dd->cspec->irq, 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);
}
/**
......@@ -3303,15 +3288,11 @@ static int qib_7220_intr_fallback(struct qib_devdata *dd)
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;
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,
......
......@@ -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,
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 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend)
#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,10 +3453,9 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend)
#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,
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,26 +3472,12 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend)
#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
......@@ -3523,9 +3486,11 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend)
qib_dev_err(dd,
"Couldn't setup MSIx interrupt (vec=%d, irq=%d): %d\n",
msixnum,
dd->cspec->msix_entries[msixnum].irq,
pci_irq_vector(dd->pcidev, msixnum),
ret);
qib_7322_nomsix(dd);
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 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend)
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 @@ static void qib_setup_7322_interrupt(struct qib_devdata *dd, int clearpend)
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;
}
......
......@@ -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 @@ int qib_pcie_params(struct qib_devdata *dd, u32 minw, u32 *nent)
/* 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);
......@@ -362,56 +351,6 @@ int qib_reinit_intr(struct qib_devdata *dd)
return ret;
}
/*
* 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.
......
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