diff options
Diffstat (limited to 'drivers/infiniband/hw/ipath/ipath_intr.c')
-rw-r--r-- | drivers/infiniband/hw/ipath/ipath_intr.c | 98 |
1 files changed, 53 insertions, 45 deletions
diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index f4d8aafc6306..6bee53ce5f33 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c | |||
@@ -37,6 +37,50 @@ | |||
37 | #include "ipath_verbs.h" | 37 | #include "ipath_verbs.h" |
38 | #include "ipath_common.h" | 38 | #include "ipath_common.h" |
39 | 39 | ||
40 | /* | ||
41 | * 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. | ||
43 | */ | ||
44 | void ipath_disarm_senderrbufs(struct ipath_devdata *dd) | ||
45 | { | ||
46 | u32 piobcnt; | ||
47 | unsigned long sbuf[4]; | ||
48 | /* | ||
49 | * it's possible that sendbuffererror could have bits set; might | ||
50 | * have already done this as a result of hardware error handling | ||
51 | */ | ||
52 | piobcnt = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; | ||
53 | /* read these before writing errorclear */ | ||
54 | sbuf[0] = ipath_read_kreg64( | ||
55 | dd, dd->ipath_kregs->kr_sendbuffererror); | ||
56 | sbuf[1] = ipath_read_kreg64( | ||
57 | dd, dd->ipath_kregs->kr_sendbuffererror + 1); | ||
58 | if (piobcnt > 128) { | ||
59 | sbuf[2] = ipath_read_kreg64( | ||
60 | dd, dd->ipath_kregs->kr_sendbuffererror + 2); | ||
61 | sbuf[3] = ipath_read_kreg64( | ||
62 | dd, dd->ipath_kregs->kr_sendbuffererror + 3); | ||
63 | } | ||
64 | |||
65 | if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) { | ||
66 | int i; | ||
67 | if (ipath_debug & (__IPATH_PKTDBG|__IPATH_DBG)) { | ||
68 | __IPATH_DBG_WHICH(__IPATH_PKTDBG|__IPATH_DBG, | ||
69 | "SendbufErrs %lx %lx", sbuf[0], | ||
70 | sbuf[1]); | ||
71 | if (ipath_debug & __IPATH_PKTDBG && piobcnt > 128) | ||
72 | printk(" %lx %lx ", sbuf[2], sbuf[3]); | ||
73 | printk("\n"); | ||
74 | } | ||
75 | |||
76 | for (i = 0; i < piobcnt; i++) | ||
77 | if (test_bit(i, sbuf)) | ||
78 | ipath_disarm_piobufs(dd, i, 1); | ||
79 | dd->ipath_lastcancel = jiffies+3; /* no armlaunch for a bit */ | ||
80 | } | ||
81 | } | ||
82 | |||
83 | |||
40 | /* These are all rcv-related errors which we want to count for stats */ | 84 | /* These are all rcv-related errors which we want to count for stats */ |
41 | #define E_SUM_PKTERRS \ | 85 | #define E_SUM_PKTERRS \ |
42 | (INFINIPATH_E_RHDRLEN | INFINIPATH_E_RBADTID | \ | 86 | (INFINIPATH_E_RHDRLEN | INFINIPATH_E_RBADTID | \ |
@@ -68,53 +112,9 @@ | |||
68 | 112 | ||
69 | static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs) | 113 | static u64 handle_e_sum_errs(struct ipath_devdata *dd, ipath_err_t errs) |
70 | { | 114 | { |
71 | unsigned long sbuf[4]; | ||
72 | u64 ignore_this_time = 0; | 115 | u64 ignore_this_time = 0; |
73 | u32 piobcnt; | ||
74 | |||
75 | /* if possible that sendbuffererror could be valid */ | ||
76 | piobcnt = dd->ipath_piobcnt2k + dd->ipath_piobcnt4k; | ||
77 | /* read these before writing errorclear */ | ||
78 | sbuf[0] = ipath_read_kreg64( | ||
79 | dd, dd->ipath_kregs->kr_sendbuffererror); | ||
80 | sbuf[1] = ipath_read_kreg64( | ||
81 | dd, dd->ipath_kregs->kr_sendbuffererror + 1); | ||
82 | if (piobcnt > 128) { | ||
83 | sbuf[2] = ipath_read_kreg64( | ||
84 | dd, dd->ipath_kregs->kr_sendbuffererror + 2); | ||
85 | sbuf[3] = ipath_read_kreg64( | ||
86 | dd, dd->ipath_kregs->kr_sendbuffererror + 3); | ||
87 | } | ||
88 | 116 | ||
89 | if (sbuf[0] || sbuf[1] || (piobcnt > 128 && (sbuf[2] || sbuf[3]))) { | 117 | ipath_disarm_senderrbufs(dd); |
90 | int i; | ||
91 | |||
92 | ipath_cdbg(PKT, "SendbufErrs %lx %lx ", sbuf[0], sbuf[1]); | ||
93 | if (ipath_debug & __IPATH_PKTDBG && piobcnt > 128) | ||
94 | printk("%lx %lx ", sbuf[2], sbuf[3]); | ||
95 | for (i = 0; i < piobcnt; i++) { | ||
96 | if (test_bit(i, sbuf)) { | ||
97 | u32 __iomem *piobuf; | ||
98 | if (i < dd->ipath_piobcnt2k) | ||
99 | piobuf = (u32 __iomem *) | ||
100 | (dd->ipath_pio2kbase + | ||
101 | i * dd->ipath_palign); | ||
102 | else | ||
103 | piobuf = (u32 __iomem *) | ||
104 | (dd->ipath_pio4kbase + | ||
105 | (i - dd->ipath_piobcnt2k) * | ||
106 | dd->ipath_4kalign); | ||
107 | |||
108 | ipath_cdbg(PKT, | ||
109 | "PIObuf[%u] @%p pbc is %x; ", | ||
110 | i, piobuf, readl(piobuf)); | ||
111 | |||
112 | ipath_disarm_piobufs(dd, i, 1); | ||
113 | } | ||
114 | } | ||
115 | if (ipath_debug & __IPATH_PKTDBG) | ||
116 | printk("\n"); | ||
117 | } | ||
118 | if ((errs & E_SUM_LINK_PKTERRS) && | 118 | if ((errs & E_SUM_LINK_PKTERRS) && |
119 | !(dd->ipath_flags & IPATH_LINKACTIVE)) { | 119 | !(dd->ipath_flags & IPATH_LINKACTIVE)) { |
120 | /* | 120 | /* |
@@ -554,6 +554,14 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) | |||
554 | ~(INFINIPATH_E_HARDWARE | | 554 | ~(INFINIPATH_E_HARDWARE | |
555 | INFINIPATH_E_IBSTATUSCHANGED); | 555 | INFINIPATH_E_IBSTATUSCHANGED); |
556 | } | 556 | } |
557 | |||
558 | /* likely due to cancel, so suppress */ | ||
559 | if ((errs & (INFINIPATH_E_SPKTLEN | INFINIPATH_E_SPIOARMLAUNCH)) && | ||
560 | dd->ipath_lastcancel > jiffies) { | ||
561 | ipath_dbg("Suppressed armlaunch/spktlen after error send cancel\n"); | ||
562 | errs &= ~(INFINIPATH_E_SPIOARMLAUNCH | INFINIPATH_E_SPKTLEN); | ||
563 | } | ||
564 | |||
557 | if (!errs) | 565 | if (!errs) |
558 | return 0; | 566 | return 0; |
559 | 567 | ||