diff options
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 23 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_init_chip.c | 36 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 5 |
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 | ||
141 | static 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 | |||
154 | static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev, | 141 | static 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 | ||
225 | bail_unlock: | 210 | bail_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 | ||
628 | bail_irqsetup: | 610 | bail_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 | ||
668 | static 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. |