aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorArthur Jones <arthur.jones@qlogic.com>2007-07-06 15:48:53 -0400
committerRoland Dreier <rolandd@cisco.com>2007-07-09 23:12:26 -0400
commit3588423fbab1cfaf839e67378897e232a054f317 (patch)
tree4885593a70ef1168a33ec261b1e0fad7f7a6a11c /drivers
parent9ca48655667214be6ebd191628a3c4b5b529a87e (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')
-rw-r--r--drivers/infiniband/hw/ipath/ipath_driver.c23
-rw-r--r--drivers/infiniband/hw/ipath/ipath_intr.c3
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h5
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
107static const struct pci_device_id ipath_pci_tbl[] = { 110static 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
125static 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
123static inline void read_bars(struct ipath_devdata *dd, struct pci_dev *dev, 138static 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
192bail_unlock: 209bail_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
516bail_irqsetup: 536bail_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.