diff options
author | Arthur Jones <arthur.jones@qlogic.com> | 2007-07-06 15:48:53 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2007-07-09 23:12:26 -0400 |
commit | 3588423fbab1cfaf839e67378897e232a054f317 (patch) | |
tree | 4885593a70ef1168a33ec261b1e0fad7f7a6a11c /drivers/infiniband | |
parent | 9ca48655667214be6ebd191628a3c4b5b529a87e (diff) |
IB/ipath: Test interrupts at driver startup
All too often, interrupts do not get enabled for our card due to BIOS
misconfiguration and other issues. This patch checks for that
condition on startup and warns the user. This patch is based on work
(check LID availability) by Robert Walsh.
Signed-off-by: Arthur Jones <arthur.jones@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_driver.c | 23 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 3 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 5 |
3 files changed, 31 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index da4a2cfb61b4..e397ec0d388f 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c | |||
@@ -104,6 +104,9 @@ static int __devinit ipath_init_one(struct pci_dev *, | |||
104 | #define PCI_DEVICE_ID_INFINIPATH_HT 0xd | 104 | #define PCI_DEVICE_ID_INFINIPATH_HT 0xd |
105 | #define PCI_DEVICE_ID_INFINIPATH_PE800 0x10 | 105 | #define PCI_DEVICE_ID_INFINIPATH_PE800 0x10 |
106 | 106 | ||
107 | /* Number of seconds before our card status check... */ | ||
108 | #define STATUS_TIMEOUT 60 | ||
109 | |||
107 | static const struct pci_device_id ipath_pci_tbl[] = { | 110 | static const struct pci_device_id ipath_pci_tbl[] = { |
108 | { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) }, | 111 | { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_HT) }, |
109 | { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) }, | 112 | { PCI_DEVICE(PCI_VENDOR_ID_PATHSCALE, PCI_DEVICE_ID_INFINIPATH_PE800) }, |
@@ -119,6 +122,18 @@ static struct pci_driver ipath_driver = { | |||
119 | .id_table = ipath_pci_tbl, | 122 | .id_table = ipath_pci_tbl, |
120 | }; | 123 | }; |
121 | 124 | ||
125 | static void ipath_check_status(struct work_struct *work) | ||
126 | { | ||
127 | struct ipath_devdata *dd = container_of(work, struct ipath_devdata, | ||
128 | status_work.work); | ||
129 | |||
130 | /* | ||
131 | * If we don't have any interrupts, let the user know and | ||
132 | * don't bother checking again. | ||
133 | */ | ||
134 | if (dd->ipath_int_counter == 0) | ||
135 | dev_err(&dd->pcidev->dev, "No interrupts detected.\n"); | ||
136 | } | ||
122 | 137 | ||
123 | static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev, | 138 | static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev, |
124 | u32 *bar0, u32 *bar1) | 139 | u32 *bar0, u32 *bar1) |
@@ -187,6 +202,8 @@ static struct ipath_devdata *ipath_alloc_devdata(struct pci_dev *pdev) | |||
187 | dd->pcidev = pdev; | 202 | dd->pcidev = pdev; |
188 | pci_set_drvdata(pdev, dd); | 203 | pci_set_drvdata(pdev, dd); |
189 | 204 | ||
205 | INIT_DELAYED_WORK(&dd->status_work, ipath_check_status); | ||
206 | |||
190 | list_add(&dd->ipath_list, &ipath_dev_list); | 207 | list_add(&dd->ipath_list, &ipath_dev_list); |
191 | 208 | ||
192 | bail_unlock: | 209 | bail_unlock: |
@@ -511,6 +528,9 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, | |||
511 | ipath_diag_add(dd); | 528 | ipath_diag_add(dd); |
512 | ipath_register_ib_device(dd); | 529 | ipath_register_ib_device(dd); |
513 | 530 | ||
531 | /* Check that card status in STATUS_TIMEOUT seconds. */ | ||
532 | schedule_delayed_work(&dd->status_work, HZ * STATUS_TIMEOUT); | ||
533 | |||
514 | goto bail; | 534 | goto bail; |
515 | 535 | ||
516 | bail_irqsetup: | 536 | bail_irqsetup: |
@@ -638,6 +658,9 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev) | |||
638 | */ | 658 | */ |
639 | ipath_shutdown_device(dd); | 659 | ipath_shutdown_device(dd); |
640 | 660 | ||
661 | cancel_delayed_work(&dd->status_work); | ||
662 | flush_scheduled_work(); | ||
663 | |||
641 | if (dd->verbs_dev) | 664 | if (dd->verbs_dev) |
642 | ipath_unregister_ib_device(dd->verbs_dev); | 665 | ipath_unregister_ib_device(dd->verbs_dev); |
643 | 666 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index ce490235c24f..47aa43428fbf 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c | |||
@@ -1009,6 +1009,9 @@ irqreturn_t ipath_intr(int irq, void *data) | |||
1009 | 1009 | ||
1010 | ipath_stats.sps_ints++; | 1010 | ipath_stats.sps_ints++; |
1011 | 1011 | ||
1012 | if (dd->ipath_int_counter != (u32) -1) | ||
1013 | dd->ipath_int_counter++; | ||
1014 | |||
1012 | if (!(dd->ipath_flags & IPATH_PRESENT)) { | 1015 | if (!(dd->ipath_flags & IPATH_PRESENT)) { |
1013 | /* | 1016 | /* |
1014 | * This return value is not great, but we do not want the | 1017 | * This return value is not great, but we do not want the |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index a27e06297636..3105005fc9d2 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -297,6 +297,8 @@ struct ipath_devdata { | |||
297 | u32 ipath_lastport_piobuf; | 297 | u32 ipath_lastport_piobuf; |
298 | /* is a stats timer active */ | 298 | /* is a stats timer active */ |
299 | u32 ipath_stats_timer_active; | 299 | u32 ipath_stats_timer_active; |
300 | /* number of interrupts for this device -- saturates... */ | ||
301 | u32 ipath_int_counter; | ||
300 | /* dwords sent read from counter */ | 302 | /* dwords sent read from counter */ |
301 | u32 ipath_lastsword; | 303 | u32 ipath_lastsword; |
302 | /* dwords received read from counter */ | 304 | /* dwords received read from counter */ |
@@ -571,6 +573,9 @@ struct ipath_devdata { | |||
571 | u32 ipath_overrun_thresh_errs; | 573 | u32 ipath_overrun_thresh_errs; |
572 | u32 ipath_lli_errs; | 574 | u32 ipath_lli_errs; |
573 | 575 | ||
576 | /* status check work */ | ||
577 | struct delayed_work status_work; | ||
578 | |||
574 | /* | 579 | /* |
575 | * Not all devices managed by a driver instance are the same | 580 | * Not all devices managed by a driver instance are the same |
576 | * type, so these fields must be per-device. | 581 | * type, so these fields must be per-device. |