aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDave Olson <dave.olson@qlogic.com>2008-04-17 00:09:30 -0400
committerRoland Dreier <rolandd@cisco.com>2008-04-17 00:09:30 -0400
commit9b436eb4f8ec39238582d4fe11b7d20e9ae3c45b (patch)
tree20e1d881181d110ee7dcef035fb54160f5b4eb83 /drivers
parent1d7c2e529fb6d4143d294ade7d99e29cb6b3775f (diff)
IB/ipath: Fix check for no interrupts to reliably fallback to INTx
Newer HCAs support MSI interrupts and also INTx interrupts. Fix the code so that INTx can be reliably enabled if MSI interrupts are not working. Signed-off-by: Dave Olson <dave.olson@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c23
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c36
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h5
3 files changed, 42 insertions, 22 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 1245180f210c..a3141bbc177a 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -138,19 +138,6 @@ static struct pci_driver ipath_driver = {
138 }, 138 },
139}; 139};
140 140
141static void ipath_check_status(struct work_struct *work)
142{
143 struct ipath_devdata *dd = container_of(work, struct ipath_devdata,
144 status_work.work);
145
146 /*
147 * If we don't have any interrupts, let the user know and
148 * don't bother checking again.
149 */
150 if (dd->ipath_int_counter == 0)
151 dev_err(&dd->pcidev->dev, "No interrupts detected.\n");
152}
153
154static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev, 141static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev,
155 u32 *bar0, u32 *bar1) 142 u32 *bar0, u32 *bar1)
156{ 143{
@@ -218,8 +205,6 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev)
218 dd->pcidev = pdev; 205 dd->pcidev = pdev;
219 pci_set_drvdata(pdev, dd); 206 pci_set_drvdata(pdev, dd);
220 207
221 INIT_DELAYED_WORK(&dd->status_work, ipath_check_status);
222
223 list_add(&dd->ipath_list, &ipath_dev_list); 208 list_add(&dd->ipath_list, &ipath_dev_list);
224 209
225bail_unlock: 210bail_unlock:
@@ -620,9 +605,6 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
620 ipath_diag_add(dd); 605 ipath_diag_add(dd);
621 ipath_register_ib_device(dd); 606 ipath_register_ib_device(dd);
622 607
623 /* Check that card status in STATUS_TIMEOUT seconds. */
624 schedule_delayed_work(&dd->status_work, HZ * STATUS_TIMEOUT);
625
626 goto bail; 608 goto bail;
627 609
628bail_irqsetup: 610bail_irqsetup:
@@ -753,7 +735,6 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev)
753 */ 735 */
754 ipath_shutdown_device(dd); 736 ipath_shutdown_device(dd);
755 737
756 cancel_delayed_work(&dd->status_work);
757 flush_scheduled_work(); 738 flush_scheduled_work();
758 739
759 if (dd->verbs_dev) 740 if (dd->verbs_dev)
@@ -2195,6 +2176,10 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
2195 del_timer_sync(&dd->ipath_stats_timer); 2176 del_timer_sync(&dd->ipath_stats_timer);
2196 dd->ipath_stats_timer_active = 0; 2177 dd->ipath_stats_timer_active = 0;
2197 } 2178 }
2179 if (dd->ipath_intrchk_timer.data) {
2180 del_timer_sync(&dd->ipath_intrchk_timer);
2181 dd->ipath_intrchk_timer.data = 0;
2182 }
2198 2183
2199 /* 2184 /*
2200 * clear all interrupts and errors, so that the next time the driver 2185 * clear all interrupts and errors, so that the next time the driver
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
index 1adafa97e082..0db19c1b45c3 100644
--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
@@ -665,6 +665,28 @@ done:
665 return ret; 665 return ret;
666} 666}
667 667
668static void verify_interrupt(unsigned long opaque)
669{
670 struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
671
672 if (!dd)
673 return; /* being torn down */
674
675 /*
676 * If we don't have any interrupts, let the user know and
677 * don't bother checking again.
678 */
679 if (dd->ipath_int_counter == 0) {
680 if (!dd->ipath_f_intr_fallback(dd))
681 dev_err(&dd->pcidev->dev, "No interrupts detected, "
682 "not usable.\n");
683 else /* re-arm the timer to see if fallback works */
684 mod_timer(&dd->ipath_intrchk_timer, jiffies + HZ/2);
685 } else
686 ipath_cdbg(VERBOSE, "%u interrupts at timer check\n",
687 dd->ipath_int_counter);
688}
689
668/** 690/**
669 * ipath_init_chip - do the actual initialization sequence on the chip 691 * ipath_init_chip - do the actual initialization sequence on the chip
670 * @dd: the infinipath device 692 * @dd: the infinipath device
@@ -968,6 +990,20 @@ done:
968 0ULL); 990 0ULL);
969 /* chip is usable; mark it as initialized */ 991 /* chip is usable; mark it as initialized */
970 *dd->ipath_statusp |= IPATH_STATUS_INITTED; 992 *dd->ipath_statusp |= IPATH_STATUS_INITTED;
993
994 /*
995 * setup to verify we get an interrupt, and fallback
996 * to an alternate if necessary and possible
997 */
998 if (!reinit) {
999 init_timer(&dd->ipath_intrchk_timer);
1000 dd->ipath_intrchk_timer.function =
1001 verify_interrupt;
1002 dd->ipath_intrchk_timer.data =
1003 (unsigned long) dd;
1004 }
1005 dd->ipath_intrchk_timer.expires = jiffies + HZ/2;
1006 add_timer(&dd->ipath_intrchk_timer);
971 } else 1007 } else
972 ipath_dev_err(dd, "No interrupts enabled, couldn't " 1008 ipath_dev_err(dd, "No interrupts enabled, couldn't "
973 "setup interrupt address\n"); 1009 "setup interrupt address\n");
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
index cef3296efb96..56e51cd7d6b9 100644
--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
@@ -426,6 +426,8 @@ struct ipath_devdata {
426 struct class_device *diag_class_dev; 426 struct class_device *diag_class_dev;
427 /* timer used to prevent stats overflow, error throttling, etc. */ 427 /* timer used to prevent stats overflow, error throttling, etc. */
428 struct timer_list ipath_stats_timer; 428 struct timer_list ipath_stats_timer;
429 /* timer to verify interrupts work, and fallback if possible */
430 struct timer_list ipath_intrchk_timer;
429 void *ipath_dummy_hdrq; /* used after port close */ 431 void *ipath_dummy_hdrq; /* used after port close */
430 dma_addr_t ipath_dummy_hdrq_phys; 432 dma_addr_t ipath_dummy_hdrq_phys;
431 433
@@ -629,9 +631,6 @@ struct ipath_devdata {
629 u32 ipath_overrun_thresh_errs; 631 u32 ipath_overrun_thresh_errs;
630 u32 ipath_lli_errs; 632 u32 ipath_lli_errs;
631 633
632 /* status check work */
633 struct delayed_work status_work;
634
635 /* 634 /*
636 * Not all devices managed by a driver instance are the same 635 * Not all devices managed by a driver instance are the same
637 * type, so these fields must be per-device. 636 * type, so these fields must be per-device.