aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorRalph Campbell <ralph.campbell@qlogic.com>2008-04-17 00:09:30 -0400
committerRoland Dreier <rolandd@cisco.com>2008-04-17 00:09:30 -0400
commit6bb68835d3eb72cd490056fda75d95493c31461b (patch)
treef992f93bb4633ae3b9444dc8663a4118a7c924be /drivers/infiniband
parent9b436eb4f8ec39238582d4fe11b7d20e9ae3c45b (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.c79
-rw-r--r--drivers/infiniband/hw/ipath/ipath_init_chip.c2
-rw-r--r--drivers/infiniband/hw/ipath/ipath_kernel.h2
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 /*