diff options
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_intr.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 100 |
1 files changed, 77 insertions, 23 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index 72b9e279d19d..45d033169c6e 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c | |||
@@ -38,10 +38,39 @@ | |||
38 | #include "ipath_common.h" | 38 | #include "ipath_common.h" |
39 | 39 | ||
40 | /* | 40 | /* |
41 | * clear (write) a pio buffer, to clear a parity error. This routine | ||
42 | * should only be called when in freeze mode, and the buffer should be | ||
43 | * canceled afterwards. | ||
44 | */ | ||
45 | static void ipath_clrpiobuf(struct ipath_devdata *dd, u32 pnum) | ||
46 | { | ||
47 | u32 __iomem *pbuf; | ||
48 | u32 dwcnt; /* dword count to write */ | ||
49 | if (pnum < dd->ipath_piobcnt2k) { | ||
50 | pbuf = (u32 __iomem *) (dd->ipath_pio2kbase + pnum * | ||
51 | dd->ipath_palign); | ||
52 | dwcnt = dd->ipath_piosize2k >> 2; | ||
53 | } | ||
54 | else { | ||
55 | pbuf = (u32 __iomem *) (dd->ipath_pio4kbase + | ||
56 | (pnum - dd->ipath_piobcnt2k) * dd->ipath_4kalign); | ||
57 | dwcnt = dd->ipath_piosize4k >> 2; | ||
58 | } | ||
59 | dev_info(&dd->pcidev->dev, | ||
60 | "Rewrite PIO buffer %u, to recover from parity error\n", | ||
61 | pnum); | ||
62 | *pbuf = dwcnt+1; /* no flush required, since already in freeze */ | ||
63 | while(--dwcnt) | ||
64 | *pbuf++ = 0; | ||
65 | } | ||
66 | |||
67 | /* | ||
41 | * Called when we might have an error that is specific to a particular | 68 | * Called when we might have an error that is specific to a particular |
42 | * PIO buffer, and may need to cancel that buffer, so it can be re-used. | 69 | * PIO buffer, and may need to cancel that buffer, so it can be re-used. |
70 | * If rewrite is true, and bits are set in the sendbufferror registers, | ||
71 | * we'll write to the buffer, for error recovery on parity errors. | ||
43 | */ | 72 | */ |
44 | void ipath_disarm_senderrbufs(struct ipath_devdata *dd) | 73 | void ipath_disarm_senderrbufs(struct ipath_devdata *dd, int rewrite) |
45 | { | 74 | { |
46 | u32 piobcnt; | 75 | u32 piobcnt; |
47 | unsigned long sbuf[4]; | 76 | unsigned long sbuf[4]; |
@@ -74,8 +103,11 @@ void ipath_disarm_senderrbufs(struct ipath_devdata *dd) | |||
74 | } | 103 | } |
75 | 104 | ||
76 | for (i = 0; i < piobcnt; i++) | 105 | for (i = 0; i < piobcnt; i++) |
77 | if (test_bit(i, sbuf)) | 106 | if (test_bit(i, sbuf)) { |
107 | if (rewrite) | ||
108 | ipath_clrpiobuf(dd, i); | ||
78 | ipath_disarm_piobufs(dd, i, 1); | 109 | ipath_disarm_piobufs(dd, i, 1); |
110 | } | ||
79 | dd->ipath_lastcancel = jiffies+3; /* no armlaunch for a bit */ | 111 | dd->ipath_lastcancel = jiffies+3; /* no armlaunch for a bit */ |
80 | } | 112 | } |
81 | } | 113 | } |
@@ -114,7 +146,7 @@ static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs) | |||
114 | { | 146 | { |
115 | u64 ignore_this_time = 0; | 147 | u64 ignore_this_time = 0; |
116 | 148 | ||
117 | ipath_disarm_senderrbufs(dd); | 149 | ipath_disarm_senderrbufs(dd, 0); |
118 | if ((errs & E_SUM_LINK_PKTERRS) && | 150 | if ((errs & E_SUM_LINK_PKTERRS) && |
119 | !(dd->ipath_flags & IPATH_LINKACTIVE)) { | 151 | !(dd->ipath_flags & IPATH_LINKACTIVE)) { |
120 | /* | 152 | /* |
@@ -403,10 +435,13 @@ static void handle_supp_msgs(struct ipath_devdata *dd, | |||
403 | * happens so often we never want to count it. | 435 | * happens so often we never want to count it. |
404 | */ | 436 | */ |
405 | if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) { | 437 | if (dd->ipath_lasterror & ~INFINIPATH_E_IBSTATUSCHANGED) { |
406 | ipath_decode_err(msg, sizeof msg, dd->ipath_lasterror & | 438 | int iserr; |
407 | ~INFINIPATH_E_IBSTATUSCHANGED); | 439 | iserr = ipath_decode_err(msg, sizeof msg, |
440 | dd->ipath_lasterror & | ||
441 | ~INFINIPATH_E_IBSTATUSCHANGED); | ||
408 | if (dd->ipath_lasterror & | 442 | if (dd->ipath_lasterror & |
409 | ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL)) | 443 | ~(INFINIPATH_E_RRCVEGRFULL | |
444 | INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS)) | ||
410 | ipath_dev_err(dd, "Suppressed %u messages for " | 445 | ipath_dev_err(dd, "Suppressed %u messages for " |
411 | "fast-repeating errors (%s) (%llx)\n", | 446 | "fast-repeating errors (%s) (%llx)\n", |
412 | supp_msgs, msg, | 447 | supp_msgs, msg, |
@@ -420,8 +455,13 @@ static void handle_supp_msgs(struct ipath_devdata *dd, | |||
420 | * them. So only complain about these at debug | 455 | * them. So only complain about these at debug |
421 | * level. | 456 | * level. |
422 | */ | 457 | */ |
423 | ipath_dbg("Suppressed %u messages for %s\n", | 458 | if (iserr) |
424 | supp_msgs, msg); | 459 | ipath_dbg("Suppressed %u messages for %s\n", |
460 | supp_msgs, msg); | ||
461 | else | ||
462 | ipath_cdbg(ERRPKT, | ||
463 | "Suppressed %u messages for %s\n", | ||
464 | supp_msgs, msg); | ||
425 | } | 465 | } |
426 | } | 466 | } |
427 | } | 467 | } |
@@ -462,7 +502,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
462 | { | 502 | { |
463 | char msg[512]; | 503 | char msg[512]; |
464 | u64 ignore_this_time = 0; | 504 | u64 ignore_this_time = 0; |
465 | int i; | 505 | int i, iserr = 0; |
466 | int chkerrpkts = 0, noprint = 0; | 506 | int chkerrpkts = 0, noprint = 0; |
467 | unsigned supp_msgs; | 507 | unsigned supp_msgs; |
468 | 508 | ||
@@ -502,6 +542,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
502 | } | 542 | } |
503 | 543 | ||
504 | if (supp_msgs == 250000) { | 544 | if (supp_msgs == 250000) { |
545 | int s_iserr; | ||
505 | /* | 546 | /* |
506 | * It's not entirely reasonable assuming that the errors set | 547 | * It's not entirely reasonable assuming that the errors set |
507 | * in the last clear period are all responsible for the | 548 | * in the last clear period are all responsible for the |
@@ -511,17 +552,17 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
511 | dd->ipath_maskederrs |= dd->ipath_lasterror | errs; | 552 | dd->ipath_maskederrs |= dd->ipath_lasterror | errs; |
512 | ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, | 553 | ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, |
513 | ~dd->ipath_maskederrs); | 554 | ~dd->ipath_maskederrs); |
514 | ipath_decode_err(msg, sizeof msg, | 555 | s_iserr = ipath_decode_err(msg, sizeof msg, |
515 | (dd->ipath_maskederrs & ~dd-> | 556 | (dd->ipath_maskederrs & ~dd-> |
516 | ipath_ignorederrs)); | 557 | ipath_ignorederrs)); |
517 | 558 | ||
518 | if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) & | 559 | if ((dd->ipath_maskederrs & ~dd->ipath_ignorederrs) & |
519 | ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL)) | 560 | ~(INFINIPATH_E_RRCVEGRFULL | |
520 | ipath_dev_err(dd, "Disabling error(s) %llx because " | 561 | INFINIPATH_E_RRCVHDRFULL | INFINIPATH_E_PKTERRS)) |
521 | "occurring too frequently (%s)\n", | 562 | ipath_dev_err(dd, "Temporarily disabling " |
522 | (unsigned long long) | 563 | "error(s) %llx reporting; too frequent (%s)\n", |
523 | (dd->ipath_maskederrs & | 564 | (unsigned long long) (dd->ipath_maskederrs & |
524 | ~dd->ipath_ignorederrs), msg); | 565 | ~dd->ipath_ignorederrs), msg); |
525 | else { | 566 | else { |
526 | /* | 567 | /* |
527 | * rcvegrfull and rcvhdrqfull are "normal", | 568 | * rcvegrfull and rcvhdrqfull are "normal", |
@@ -530,8 +571,15 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
530 | * processing them. So only complain about | 571 | * processing them. So only complain about |
531 | * these at debug level. | 572 | * these at debug level. |
532 | */ | 573 | */ |
533 | ipath_dbg("Disabling frequent queue full errors " | 574 | if (s_iserr) |
534 | "(%s)\n", msg); | 575 | ipath_dbg("Temporarily disabling reporting " |
576 | "too frequent queue full errors (%s)\n", | ||
577 | msg); | ||
578 | else | ||
579 | ipath_cdbg(ERRPKT, | ||
580 | "Temporarily disabling reporting too" | ||
581 | " frequent packet errors (%s)\n", | ||
582 | msg); | ||
535 | } | 583 | } |
536 | 584 | ||
537 | /* | 585 | /* |
@@ -589,6 +637,8 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
589 | ipath_stats.sps_crcerrs++; | 637 | ipath_stats.sps_crcerrs++; |
590 | chkerrpkts = 1; | 638 | chkerrpkts = 1; |
591 | } | 639 | } |
640 | iserr = errs & ~(E_SUM_PKTERRS | INFINIPATH_E_PKTERRS); | ||
641 | |||
592 | 642 | ||
593 | /* | 643 | /* |
594 | * We don't want to print these two as they happen, or we can make | 644 | * We don't want to print these two as they happen, or we can make |
@@ -677,8 +727,13 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
677 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_CONF; | 727 | *dd->ipath_statusp &= ~IPATH_STATUS_IB_CONF; |
678 | } | 728 | } |
679 | 729 | ||
680 | if (!noprint && *msg) | 730 | if (!noprint && *msg) { |
681 | ipath_dev_err(dd, "%s error\n", msg); | 731 | if (iserr) |
732 | ipath_dev_err(dd, "%s error\n", msg); | ||
733 | else | ||
734 | dev_info(&dd->pcidev->dev, "%s packet problems\n", | ||
735 | msg); | ||
736 | } | ||
682 | if (dd->ipath_state_wanted & dd->ipath_flags) { | 737 | if (dd->ipath_state_wanted & dd->ipath_flags) { |
683 | ipath_cdbg(VERBOSE, "driver wanted state %x, iflags now %x, " | 738 | ipath_cdbg(VERBOSE, "driver wanted state %x, iflags now %x, " |
684 | "waking\n", dd->ipath_state_wanted, | 739 | "waking\n", dd->ipath_state_wanted, |
@@ -819,11 +874,10 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat) | |||
819 | struct ipath_portdata *pd = dd->ipath_pd[i]; | 874 | struct ipath_portdata *pd = dd->ipath_pd[i]; |
820 | if (portr & (1 << i) && pd && pd->port_cnt && | 875 | if (portr & (1 << i) && pd && pd->port_cnt && |
821 | test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) { | 876 | test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) { |
822 | int rcbit; | ||
823 | clear_bit(IPATH_PORT_WAITING_RCV, | 877 | clear_bit(IPATH_PORT_WAITING_RCV, |
824 | &pd->port_flag); | 878 | &pd->port_flag); |
825 | rcbit = i + INFINIPATH_R_INTRAVAIL_SHIFT; | 879 | clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT, |
826 | clear_bit(1UL << rcbit, &dd->ipath_rcvctrl); | 880 | &dd->ipath_rcvctrl); |
827 | wake_up_interruptible(&pd->port_wait); | 881 | wake_up_interruptible(&pd->port_wait); |
828 | rcvdint = 1; | 882 | rcvdint = 1; |
829 | } | 883 | } |