diff options
author | Ralph Campbell <ralph.campbell@qlogic.com> | 2008-04-17 00:09:30 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2008-04-17 00:09:30 -0400 |
commit | 6bb68835d3eb72cd490056fda75d95493c31461b (patch) | |
tree | f992f93bb4633ae3b9444dc8663a4118a7c924be /drivers/infiniband | |
parent | 9b436eb4f8ec39238582d4fe11b7d20e9ae3c45b (diff) |
IB/ipath: Fix up error handling
This patch makes chip reset more robust and reduces lock contention
between user and kernel TID register updates.
Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6120.c | 79 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_init_chip.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_kernel.h | 2 |
3 files changed, 66 insertions, 17 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c index 907b61b5975a..c8d8f1a2c8fb 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c | |||
@@ -558,12 +558,40 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg, | |||
558 | dd->ipath_hwerrmask); | 558 | dd->ipath_hwerrmask); |
559 | } | 559 | } |
560 | 560 | ||
561 | if (*msg) | 561 | if (hwerrs) { |
562 | /* | ||
563 | * if any set that we aren't ignoring; only | ||
564 | * make the complaint once, in case it's stuck | ||
565 | * or recurring, and we get here multiple | ||
566 | * times. | ||
567 | */ | ||
562 | ipath_dev_err(dd, "%s hardware error\n", msg); | 568 | ipath_dev_err(dd, "%s hardware error\n", msg); |
563 | if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) { | 569 | if (dd->ipath_flags & IPATH_INITTED) { |
570 | ipath_set_linkstate(dd, IPATH_IB_LINKDOWN); | ||
571 | ipath_setup_pe_setextled(dd, | ||
572 | INFINIPATH_IBCS_L_STATE_DOWN, | ||
573 | INFINIPATH_IBCS_LT_STATE_DISABLED); | ||
574 | ipath_dev_err(dd, "Fatal Hardware Error (freeze " | ||
575 | "mode), no longer usable, SN %.16s\n", | ||
576 | dd->ipath_serial); | ||
577 | isfatal = 1; | ||
578 | } | ||
579 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; | ||
580 | /* mark as having had error */ | ||
581 | *dd->ipath_statusp |= IPATH_STATUS_HWERROR; | ||
582 | /* | ||
583 | * mark as not usable, at a minimum until driver | ||
584 | * is reloaded, probably until reboot, since no | ||
585 | * other reset is possible. | ||
586 | */ | ||
587 | dd->ipath_flags &= ~IPATH_INITTED; | ||
588 | } else | ||
589 | *msg = 0; /* recovered from all of them */ | ||
590 | |||
591 | if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg && msg) { | ||
564 | /* | 592 | /* |
565 | * for /sys status file ; if no trailing } is copied, we'll | 593 | * for /sys status file ; if no trailing brace is copied, |
566 | * know it was truncated. | 594 | * we'll know it was truncated. |
567 | */ | 595 | */ |
568 | snprintf(dd->ipath_freezemsg, dd->ipath_freezelen, | 596 | snprintf(dd->ipath_freezemsg, dd->ipath_freezelen, |
569 | "{%s}", msg); | 597 | "{%s}", msg); |
@@ -1127,10 +1155,7 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd) | |||
1127 | INFINIPATH_HWE_RXEMEMPARITYERR_MASK << | 1155 | INFINIPATH_HWE_RXEMEMPARITYERR_MASK << |
1128 | INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT; | 1156 | INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT; |
1129 | 1157 | ||
1130 | dd->ipath_eep_st_masks[2].errs_to_log = | 1158 | dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET; |
1131 | INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET; | ||
1132 | |||
1133 | |||
1134 | dd->delay_mult = 2; /* SDR, 4X, can't change */ | 1159 | dd->delay_mult = 2; /* SDR, 4X, can't change */ |
1135 | } | 1160 | } |
1136 | 1161 | ||
@@ -1204,6 +1229,9 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd) | |||
1204 | u64 val; | 1229 | u64 val; |
1205 | int i; | 1230 | int i; |
1206 | int ret; | 1231 | int ret; |
1232 | u16 cmdval; | ||
1233 | |||
1234 | pci_read_config_word(dd->pcidev, PCI_COMMAND, &cmdval); | ||
1207 | 1235 | ||
1208 | /* Use ERROR so it shows up in logs, etc. */ | 1236 | /* Use ERROR so it shows up in logs, etc. */ |
1209 | ipath_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->ipath_unit); | 1237 | ipath_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->ipath_unit); |
@@ -1231,10 +1259,14 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd) | |||
1231 | ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n", | 1259 | ipath_dev_err(dd, "rewrite of BAR1 failed: %d\n", |
1232 | r); | 1260 | r); |
1233 | /* now re-enable memory access */ | 1261 | /* now re-enable memory access */ |
1262 | pci_write_config_word(dd->pcidev, PCI_COMMAND, cmdval); | ||
1234 | if ((r = pci_enable_device(dd->pcidev))) | 1263 | if ((r = pci_enable_device(dd->pcidev))) |
1235 | ipath_dev_err(dd, "pci_enable_device failed after " | 1264 | ipath_dev_err(dd, "pci_enable_device failed after " |
1236 | "reset: %d\n", r); | 1265 | "reset: %d\n", r); |
1237 | /* whether it worked or not, mark as present, again */ | 1266 | /* |
1267 | * whether it fully enabled or not, mark as present, | ||
1268 | * again (but not INITTED) | ||
1269 | */ | ||
1238 | dd->ipath_flags |= IPATH_PRESENT; | 1270 | dd->ipath_flags |= IPATH_PRESENT; |
1239 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision); | 1271 | val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_revision); |
1240 | if (val == dd->ipath_revision) { | 1272 | if (val == dd->ipath_revision) { |
@@ -1273,6 +1305,11 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr, | |||
1273 | { | 1305 | { |
1274 | u32 __iomem *tidp32 = (u32 __iomem *)tidptr; | 1306 | u32 __iomem *tidp32 = (u32 __iomem *)tidptr; |
1275 | unsigned long flags = 0; /* keep gcc quiet */ | 1307 | unsigned long flags = 0; /* keep gcc quiet */ |
1308 | int tidx; | ||
1309 | spinlock_t *tidlockp; | ||
1310 | |||
1311 | if (!dd->ipath_kregbase) | ||
1312 | return; | ||
1276 | 1313 | ||
1277 | if (pa != dd->ipath_tidinvalid) { | 1314 | if (pa != dd->ipath_tidinvalid) { |
1278 | if (pa & ((1U << 11) - 1)) { | 1315 | if (pa & ((1U << 11) - 1)) { |
@@ -1302,14 +1339,22 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr, | |||
1302 | * call can be done from interrupt level for the port 0 eager TIDs, | 1339 | * call can be done from interrupt level for the port 0 eager TIDs, |
1303 | * so we have to use irqsave locks. | 1340 | * so we have to use irqsave locks. |
1304 | */ | 1341 | */ |
1305 | spin_lock_irqsave(&dd->ipath_tid_lock, flags); | 1342 | /* |
1343 | * Assumes tidptr always > ipath_egrtidbase | ||
1344 | * if type == RCVHQ_RCV_TYPE_EAGER. | ||
1345 | */ | ||
1346 | tidx = tidptr - dd->ipath_egrtidbase; | ||
1347 | |||
1348 | tidlockp = (type == RCVHQ_RCV_TYPE_EAGER && tidx < dd->ipath_rcvegrcnt) | ||
1349 | ? &dd->ipath_kernel_tid_lock : &dd->ipath_user_tid_lock; | ||
1350 | spin_lock_irqsave(tidlockp, flags); | ||
1306 | ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xfeeddeaf); | 1351 | ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xfeeddeaf); |
1307 | if (dd->ipath_kregbase) | 1352 | writel(pa, tidp32); |
1308 | writel(pa, tidp32); | ||
1309 | ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xdeadbeef); | 1353 | ipath_write_kreg(dd, dd->ipath_kregs->kr_scratch, 0xdeadbeef); |
1310 | mmiowb(); | 1354 | mmiowb(); |
1311 | spin_unlock_irqrestore(&dd->ipath_tid_lock, flags); | 1355 | spin_unlock_irqrestore(tidlockp, flags); |
1312 | } | 1356 | } |
1357 | |||
1313 | /** | 1358 | /** |
1314 | * ipath_pe_put_tid_2 - write a TID in chip, Revision 2 or higher | 1359 | * ipath_pe_put_tid_2 - write a TID in chip, Revision 2 or higher |
1315 | * @dd: the infinipath device | 1360 | * @dd: the infinipath device |
@@ -1325,6 +1370,10 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr, | |||
1325 | u32 type, unsigned long pa) | 1370 | u32 type, unsigned long pa) |
1326 | { | 1371 | { |
1327 | u32 __iomem *tidp32 = (u32 __iomem *)tidptr; | 1372 | u32 __iomem *tidp32 = (u32 __iomem *)tidptr; |
1373 | u32 tidx; | ||
1374 | |||
1375 | if (!dd->ipath_kregbase) | ||
1376 | return; | ||
1328 | 1377 | ||
1329 | if (pa != dd->ipath_tidinvalid) { | 1378 | if (pa != dd->ipath_tidinvalid) { |
1330 | if (pa & ((1U << 11) - 1)) { | 1379 | if (pa & ((1U << 11) - 1)) { |
@@ -1344,8 +1393,8 @@ static void ipath_pe_put_tid_2(struct ipath_devdata *dd, u64 __iomem *tidptr, | |||
1344 | else /* for now, always full 4KB page */ | 1393 | else /* for now, always full 4KB page */ |
1345 | pa |= 2 << 29; | 1394 | pa |= 2 << 29; |
1346 | } | 1395 | } |
1347 | if (dd->ipath_kregbase) | 1396 | tidx = tidptr - dd->ipath_egrtidbase; |
1348 | writel(pa, tidp32); | 1397 | writel(pa, tidp32); |
1349 | mmiowb(); | 1398 | mmiowb(); |
1350 | } | 1399 | } |
1351 | 1400 | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index 0db19c1b45c3..8d8e572baf6e 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c | |||
@@ -319,7 +319,7 @@ static int init_chip_first(struct ipath_devdata *dd) | |||
319 | else ipath_dbg("%u 2k piobufs @ %p\n", | 319 | else ipath_dbg("%u 2k piobufs @ %p\n", |
320 | dd->ipath_piobcnt2k, dd->ipath_pio2kbase); | 320 | dd->ipath_piobcnt2k, dd->ipath_pio2kbase); |
321 | 321 | ||
322 | spin_lock_init(&dd->ipath_tid_lock); | 322 | spin_lock_init(&dd->ipath_user_tid_lock); |
323 | spin_lock_init(&dd->ipath_sendctrl_lock); | 323 | spin_lock_init(&dd->ipath_sendctrl_lock); |
324 | spin_lock_init(&dd->ipath_gpio_lock); | 324 | spin_lock_init(&dd->ipath_gpio_lock); |
325 | spin_lock_init(&dd->ipath_eep_st_lock); | 325 | spin_lock_init(&dd->ipath_eep_st_lock); |
diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 56e51cd7d6b9..890599621098 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h | |||
@@ -407,7 +407,7 @@ struct ipath_devdata { | |||
407 | u64 __iomem *ipath_egrtidbase; | 407 | u64 __iomem *ipath_egrtidbase; |
408 | /* lock to workaround chip bug 9437 and others */ | 408 | /* lock to workaround chip bug 9437 and others */ |
409 | spinlock_t ipath_kernel_tid_lock; | 409 | spinlock_t ipath_kernel_tid_lock; |
410 | spinlock_t ipath_tid_lock; | 410 | spinlock_t ipath_user_tid_lock; |
411 | spinlock_t ipath_sendctrl_lock; | 411 | spinlock_t ipath_sendctrl_lock; |
412 | 412 | ||
413 | /* | 413 | /* |