diff options
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_iba6110.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_iba6110.c | 152 |
1 files changed, 95 insertions, 57 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c index 993482545021..4171198fc202 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6110.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c | |||
@@ -43,6 +43,9 @@ | |||
43 | #include "ipath_kernel.h" | 43 | #include "ipath_kernel.h" |
44 | #include "ipath_registers.h" | 44 | #include "ipath_registers.h" |
45 | 45 | ||
46 | static void ipath_setup_ht_setextled(struct ipath_devdata *, u64, u64); | ||
47 | |||
48 | |||
46 | /* | 49 | /* |
47 | * This lists the InfiniPath registers, in the actual chip layout. | 50 | * This lists the InfiniPath registers, in the actual chip layout. |
48 | * This structure should never be directly accessed. | 51 | * This structure should never be directly accessed. |
@@ -208,8 +211,8 @@ static const struct ipath_kregs ipath_ht_kregs = { | |||
208 | .kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus), | 211 | .kr_serdesstatus = IPATH_KREG_OFFSET(SerdesStatus), |
209 | .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig), | 212 | .kr_xgxsconfig = IPATH_KREG_OFFSET(XGXSConfig), |
210 | /* | 213 | /* |
211 | * These should not be used directly via ipath_read_kreg64(), | 214 | * These should not be used directly via ipath_write_kreg64(), |
212 | * use them with ipath_read_kreg64_port(), | 215 | * use them with ipath_write_kreg64_port(), |
213 | */ | 216 | */ |
214 | .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0), | 217 | .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0), |
215 | .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0) | 218 | .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0) |
@@ -284,6 +287,14 @@ static const struct ipath_cregs ipath_ht_cregs = { | |||
284 | #define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000 | 287 | #define INFINIPATH_EXTS_MEMBIST_ENDTEST 0x0000000000004000 |
285 | #define INFINIPATH_EXTS_MEMBIST_CORRECT 0x0000000000008000 | 288 | #define INFINIPATH_EXTS_MEMBIST_CORRECT 0x0000000000008000 |
286 | 289 | ||
290 | |||
291 | /* TID entries (memory), HT-only */ | ||
292 | #define INFINIPATH_RT_ADDR_MASK 0xFFFFFFFFFFULL /* 40 bits valid */ | ||
293 | #define INFINIPATH_RT_VALID 0x8000000000000000ULL | ||
294 | #define INFINIPATH_RT_ADDR_SHIFT 0 | ||
295 | #define INFINIPATH_RT_BUFSIZE_MASK 0x3FFFULL | ||
296 | #define INFINIPATH_RT_BUFSIZE_SHIFT 48 | ||
297 | |||
287 | /* | 298 | /* |
288 | * masks and bits that are different in different chips, or present only | 299 | * masks and bits that are different in different chips, or present only |
289 | * in one | 300 | * in one |
@@ -402,6 +413,14 @@ static const struct ipath_hwerror_msgs ipath_6110_hwerror_msgs[] = { | |||
402 | INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"), | 413 | INFINIPATH_HWE_MSG(SERDESPLLFAILED, "SerDes PLL"), |
403 | }; | 414 | }; |
404 | 415 | ||
416 | #define TXE_PIO_PARITY ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF | \ | ||
417 | INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) \ | ||
418 | << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT) | ||
419 | #define RXE_EAGER_PARITY (INFINIPATH_HWE_RXEMEMPARITYERR_EAGERTID \ | ||
420 | << INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT) | ||
421 | |||
422 | static int ipath_ht_txe_recover(struct ipath_devdata *); | ||
423 | |||
405 | /** | 424 | /** |
406 | * ipath_ht_handle_hwerrors - display hardware errors. | 425 | * ipath_ht_handle_hwerrors - display hardware errors. |
407 | * @dd: the infinipath device | 426 | * @dd: the infinipath device |
@@ -450,13 +469,12 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, | |||
450 | 469 | ||
451 | /* | 470 | /* |
452 | * make sure we get this much out, unless told to be quiet, | 471 | * make sure we get this much out, unless told to be quiet, |
472 | * it's a parity error we may recover from, | ||
453 | * or it's occurred within the last 5 seconds | 473 | * or it's occurred within the last 5 seconds |
454 | */ | 474 | */ |
455 | if ((hwerrs & ~(dd->ipath_lasthwerror | | 475 | if ((hwerrs & ~(dd->ipath_lasthwerror | TXE_PIO_PARITY | |
456 | ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF | | 476 | RXE_EAGER_PARITY)) || |
457 | INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) | 477 | (ipath_debug & __IPATH_VERBDBG)) |
458 | << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT))) || | ||
459 | (ipath_debug & __IPATH_VERBDBG)) | ||
460 | dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx " | 478 | dev_info(&dd->pcidev->dev, "Hardware error: hwerr=0x%llx " |
461 | "(cleared)\n", (unsigned long long) hwerrs); | 479 | "(cleared)\n", (unsigned long long) hwerrs); |
462 | dd->ipath_lasthwerror |= hwerrs; | 480 | dd->ipath_lasthwerror |= hwerrs; |
@@ -467,7 +485,7 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, | |||
467 | (hwerrs & ~dd->ipath_hwe_bitsextant)); | 485 | (hwerrs & ~dd->ipath_hwe_bitsextant)); |
468 | 486 | ||
469 | ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control); | 487 | ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control); |
470 | if (ctrl & INFINIPATH_C_FREEZEMODE) { | 488 | if ((ctrl & INFINIPATH_C_FREEZEMODE) && !ipath_diag_inuse) { |
471 | /* | 489 | /* |
472 | * parity errors in send memory are recoverable, | 490 | * parity errors in send memory are recoverable, |
473 | * just cancel the send (if indicated in * sendbuffererror), | 491 | * just cancel the send (if indicated in * sendbuffererror), |
@@ -476,50 +494,14 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, | |||
476 | * occur if a processor speculative read is done to the PIO | 494 | * occur if a processor speculative read is done to the PIO |
477 | * buffer while we are sending a packet, for example. | 495 | * buffer while we are sending a packet, for example. |
478 | */ | 496 | */ |
479 | if (hwerrs & ((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF | | 497 | if ((hwerrs & TXE_PIO_PARITY) && ipath_ht_txe_recover(dd)) |
480 | INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) | 498 | hwerrs &= ~TXE_PIO_PARITY; |
481 | << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)) { | 499 | if (hwerrs & RXE_EAGER_PARITY) |
482 | ipath_stats.sps_txeparity++; | 500 | ipath_dev_err(dd, "RXE parity, Eager TID error is not " |
483 | ipath_dbg("Recovering from TXE parity error (%llu), " | 501 | "recoverable\n"); |
484 | "hwerrstatus=%llx\n", | 502 | if (!hwerrs) { |
485 | (unsigned long long) ipath_stats.sps_txeparity, | 503 | ipath_dbg("Clearing freezemode on ignored or " |
486 | (unsigned long long) hwerrs); | 504 | "recovered hardware error\n"); |
487 | ipath_disarm_senderrbufs(dd); | ||
488 | hwerrs &= ~((INFINIPATH_HWE_TXEMEMPARITYERR_PIOBUF | | ||
489 | INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) | ||
490 | << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT); | ||
491 | if (!hwerrs) { /* else leave in freeze mode */ | ||
492 | ipath_write_kreg(dd, | ||
493 | dd->ipath_kregs->kr_control, | ||
494 | dd->ipath_control); | ||
495 | return; | ||
496 | } | ||
497 | } | ||
498 | if (hwerrs) { | ||
499 | /* | ||
500 | * if any set that we aren't ignoring; only | ||
501 | * make the complaint once, in case it's stuck | ||
502 | * or recurring, and we get here multiple | ||
503 | * times. | ||
504 | */ | ||
505 | if (dd->ipath_flags & IPATH_INITTED) { | ||
506 | ipath_dev_err(dd, "Fatal Hardware Error (freeze " | ||
507 | "mode), no longer usable, SN %.16s\n", | ||
508 | dd->ipath_serial); | ||
509 | isfatal = 1; | ||
510 | } | ||
511 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; | ||
512 | /* mark as having had error */ | ||
513 | *dd->ipath_statusp |= IPATH_STATUS_HWERROR; | ||
514 | /* | ||
515 | * mark as not usable, at a minimum until driver | ||
516 | * is reloaded, probably until reboot, since no | ||
517 | * other reset is possible. | ||
518 | */ | ||
519 | dd->ipath_flags &= ~IPATH_INITTED; | ||
520 | } else { | ||
521 | ipath_dbg("Clearing freezemode on ignored hardware " | ||
522 | "error\n"); | ||
523 | ctrl &= ~INFINIPATH_C_FREEZEMODE; | 505 | ctrl &= ~INFINIPATH_C_FREEZEMODE; |
524 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, | 506 | ipath_write_kreg(dd, dd->ipath_kregs->kr_control, |
525 | ctrl); | 507 | ctrl); |
@@ -587,7 +569,39 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, | |||
587 | dd->ipath_hwerrmask); | 569 | dd->ipath_hwerrmask); |
588 | } | 570 | } |
589 | 571 | ||
590 | ipath_dev_err(dd, "%s hardware error\n", msg); | 572 | if (hwerrs) { |
573 | /* | ||
574 | * if any set that we aren't ignoring; only | ||
575 | * make the complaint once, in case it's stuck | ||
576 | * or recurring, and we get here multiple | ||
577 | * times. | ||
578 | * force link down, so switch knows, and | ||
579 | * LEDs are turned off | ||
580 | */ | ||
581 | if (dd->ipath_flags & IPATH_INITTED) { | ||
582 | ipath_set_linkstate(dd, IPATH_IB_LINKDOWN); | ||
583 | ipath_setup_ht_setextled(dd, | ||
584 | INFINIPATH_IBCS_L_STATE_DOWN, | ||
585 | INFINIPATH_IBCS_LT_STATE_DISABLED); | ||
586 | ipath_dev_err(dd, "Fatal Hardware Error (freeze " | ||
587 | "mode), no longer usable, SN %.16s\n", | ||
588 | dd->ipath_serial); | ||
589 | isfatal = 1; | ||
590 | } | ||
591 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; | ||
592 | /* mark as having had error */ | ||
593 | *dd->ipath_statusp |= IPATH_STATUS_HWERROR; | ||
594 | /* | ||
595 | * mark as not usable, at a minimum until driver | ||
596 | * is reloaded, probably until reboot, since no | ||
597 | * other reset is possible. | ||
598 | */ | ||
599 | dd->ipath_flags &= ~IPATH_INITTED; | ||
600 | } | ||
601 | else | ||
602 | *msg = 0; /* recovered from all of them */ | ||
603 | if (*msg) | ||
604 | ipath_dev_err(dd, "%s hardware error\n", msg); | ||
591 | if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) | 605 | if (isfatal && !ipath_diag_inuse && dd->ipath_freezemsg) |
592 | /* | 606 | /* |
593 | * for status file; if no trailing brace is copied, | 607 | * for status file; if no trailing brace is copied, |
@@ -658,7 +672,8 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, | |||
658 | if (n) | 672 | if (n) |
659 | snprintf(name, namelen, "%s", n); | 673 | snprintf(name, namelen, "%s", n); |
660 | 674 | ||
661 | if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 || dd->ipath_minrev > 3)) { | 675 | if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 || |
676 | dd->ipath_minrev > 3)) { | ||
662 | /* | 677 | /* |
663 | * This version of the driver only supports Rev 3.2 and 3.3 | 678 | * This version of the driver only supports Rev 3.2 and 3.3 |
664 | */ | 679 | */ |
@@ -1163,6 +1178,8 @@ static void ipath_ht_init_hwerrors(struct ipath_devdata *dd) | |||
1163 | 1178 | ||
1164 | if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST)) | 1179 | if (!(extsval & INFINIPATH_EXTS_MEMBIST_ENDTEST)) |
1165 | ipath_dev_err(dd, "MemBIST did not complete!\n"); | 1180 | ipath_dev_err(dd, "MemBIST did not complete!\n"); |
1181 | if (extsval & INFINIPATH_EXTS_MEMBIST_CORRECT) | ||
1182 | ipath_dbg("MemBIST corrected\n"); | ||
1166 | 1183 | ||
1167 | ipath_check_htlink(dd); | 1184 | ipath_check_htlink(dd); |
1168 | 1185 | ||
@@ -1366,6 +1383,9 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd, | |||
1366 | u64 __iomem *tidptr, u32 type, | 1383 | u64 __iomem *tidptr, u32 type, |
1367 | unsigned long pa) | 1384 | unsigned long pa) |
1368 | { | 1385 | { |
1386 | if (!dd->ipath_kregbase) | ||
1387 | return; | ||
1388 | |||
1369 | if (pa != dd->ipath_tidinvalid) { | 1389 | if (pa != dd->ipath_tidinvalid) { |
1370 | if (unlikely((pa & ~INFINIPATH_RT_ADDR_MASK))) { | 1390 | if (unlikely((pa & ~INFINIPATH_RT_ADDR_MASK))) { |
1371 | dev_info(&dd->pcidev->dev, | 1391 | dev_info(&dd->pcidev->dev, |
@@ -1382,10 +1402,10 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd, | |||
1382 | pa |= lenvalid | INFINIPATH_RT_VALID; | 1402 | pa |= lenvalid | INFINIPATH_RT_VALID; |
1383 | } | 1403 | } |
1384 | } | 1404 | } |
1385 | if (dd->ipath_kregbase) | 1405 | writeq(pa, tidptr); |
1386 | writeq(pa, tidptr); | ||
1387 | } | 1406 | } |
1388 | 1407 | ||
1408 | |||
1389 | /** | 1409 | /** |
1390 | * ipath_ht_clear_tid - clear all TID entries for a port, expected and eager | 1410 | * ipath_ht_clear_tid - clear all TID entries for a port, expected and eager |
1391 | * @dd: the infinipath device | 1411 | * @dd: the infinipath device |
@@ -1515,7 +1535,7 @@ static int ipath_ht_early_init(struct ipath_devdata *dd) | |||
1515 | INFINIPATH_S_ABORT); | 1535 | INFINIPATH_S_ABORT); |
1516 | 1536 | ||
1517 | ipath_get_eeprom_info(dd); | 1537 | ipath_get_eeprom_info(dd); |
1518 | if(dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' && | 1538 | if (dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' && |
1519 | dd->ipath_serial[1] == '2' && dd->ipath_serial[2] == '8') { | 1539 | dd->ipath_serial[1] == '2' && dd->ipath_serial[2] == '8') { |
1520 | /* | 1540 | /* |
1521 | * Later production QHT7040 has same changes as QHT7140, so | 1541 | * Later production QHT7040 has same changes as QHT7140, so |
@@ -1528,6 +1548,24 @@ static int ipath_ht_early_init(struct ipath_devdata *dd) | |||
1528 | return 0; | 1548 | return 0; |
1529 | } | 1549 | } |
1530 | 1550 | ||
1551 | |||
1552 | static int ipath_ht_txe_recover(struct ipath_devdata *dd) | ||
1553 | { | ||
1554 | int cnt = ++ipath_stats.sps_txeparity; | ||
1555 | if (cnt >= IPATH_MAX_PARITY_ATTEMPTS) { | ||
1556 | if (cnt == IPATH_MAX_PARITY_ATTEMPTS) | ||
1557 | ipath_dev_err(dd, | ||
1558 | "Too many attempts to recover from " | ||
1559 | "TXE parity, giving up\n"); | ||
1560 | return 0; | ||
1561 | } | ||
1562 | dev_info(&dd->pcidev->dev, | ||
1563 | "Recovering from TXE PIO parity error\n"); | ||
1564 | ipath_disarm_senderrbufs(dd, 1); | ||
1565 | return 1; | ||
1566 | } | ||
1567 | |||
1568 | |||
1531 | /** | 1569 | /** |
1532 | * ipath_init_ht_get_base_info - set chip-specific flags for user code | 1570 | * ipath_init_ht_get_base_info - set chip-specific flags for user code |
1533 | * @dd: the infinipath device | 1571 | * @dd: the infinipath device |