1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#include "ipath_kernel.h"
35
36struct infinipath_stats ipath_stats;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
53{
54 u32 val, reg64 = 0;
55 u64 val64;
56 unsigned long t0, t1;
57 u64 ret;
58
59 t0 = jiffies;
60
61
62 if (!(dd->ipath_flags & IPATH_32BITCOUNTERS) &&
63 (creg == dd->ipath_cregs->cr_wordsendcnt ||
64 creg == dd->ipath_cregs->cr_wordrcvcnt ||
65 creg == dd->ipath_cregs->cr_pktsendcnt ||
66 creg == dd->ipath_cregs->cr_pktrcvcnt)) {
67 val64 = ipath_read_creg(dd, creg);
68 val = val64 == ~0ULL ? ~0U : 0;
69 reg64 = 1;
70 } else
71 val64 = val = ipath_read_creg32(dd, creg);
72
73
74
75
76
77
78
79 t1 = jiffies;
80 if (time_before(t0 + HZ, t1) && val == -1) {
81 ipath_dev_err(dd, "Error! Read counter 0x%x timed out\n",
82 creg);
83 ret = 0ULL;
84 goto bail;
85 }
86 if (reg64) {
87 ret = val64;
88 goto bail;
89 }
90
91 if (creg == dd->ipath_cregs->cr_wordsendcnt) {
92 if (val != dd->ipath_lastsword) {
93 dd->ipath_sword += val - dd->ipath_lastsword;
94 dd->ipath_lastsword = val;
95 }
96 val64 = dd->ipath_sword;
97 } else if (creg == dd->ipath_cregs->cr_wordrcvcnt) {
98 if (val != dd->ipath_lastrword) {
99 dd->ipath_rword += val - dd->ipath_lastrword;
100 dd->ipath_lastrword = val;
101 }
102 val64 = dd->ipath_rword;
103 } else if (creg == dd->ipath_cregs->cr_pktsendcnt) {
104 if (val != dd->ipath_lastspkts) {
105 dd->ipath_spkts += val - dd->ipath_lastspkts;
106 dd->ipath_lastspkts = val;
107 }
108 val64 = dd->ipath_spkts;
109 } else if (creg == dd->ipath_cregs->cr_pktrcvcnt) {
110 if (val != dd->ipath_lastrpkts) {
111 dd->ipath_rpkts += val - dd->ipath_lastrpkts;
112 dd->ipath_lastrpkts = val;
113 }
114 val64 = dd->ipath_rpkts;
115 } else if (creg == dd->ipath_cregs->cr_ibsymbolerrcnt) {
116 if (dd->ibdeltainprog)
117 val64 -= val64 - dd->ibsymsnap;
118 val64 -= dd->ibsymdelta;
119 } else if (creg == dd->ipath_cregs->cr_iblinkerrrecovcnt) {
120 if (dd->ibdeltainprog)
121 val64 -= val64 - dd->iblnkerrsnap;
122 val64 -= dd->iblnkerrdelta;
123 } else
124 val64 = (u64) val;
125
126 ret = val64;
127
128bail:
129 return ret;
130}
131
132
133
134
135
136
137
138
139
140
141static void ipath_qcheck(struct ipath_devdata *dd)
142{
143 static u64 last_tot_hdrqfull;
144 struct ipath_portdata *pd = dd->ipath_pd[0];
145 size_t blen = 0;
146 char buf[128];
147 u32 hdrqtail;
148
149 *buf = 0;
150 if (pd->port_hdrqfull != dd->ipath_p0_hdrqfull) {
151 blen = snprintf(buf, sizeof buf, "port 0 hdrqfull %u",
152 pd->port_hdrqfull -
153 dd->ipath_p0_hdrqfull);
154 dd->ipath_p0_hdrqfull = pd->port_hdrqfull;
155 }
156 if (ipath_stats.sps_etidfull != dd->ipath_last_tidfull) {
157 blen += snprintf(buf + blen, sizeof buf - blen,
158 "%srcvegrfull %llu",
159 blen ? ", " : "",
160 (unsigned long long)
161 (ipath_stats.sps_etidfull -
162 dd->ipath_last_tidfull));
163 dd->ipath_last_tidfull = ipath_stats.sps_etidfull;
164 }
165
166
167
168
169
170
171
172
173 if ((ipath_debug & (__IPATH_PKTDBG | __IPATH_DBG)) &&
174 ipath_stats.sps_hdrqfull != last_tot_hdrqfull) {
175 blen += snprintf(buf + blen, sizeof buf - blen,
176 "%shdrqfull %llu (all ports)",
177 blen ? ", " : "",
178 (unsigned long long)
179 (ipath_stats.sps_hdrqfull -
180 last_tot_hdrqfull));
181 last_tot_hdrqfull = ipath_stats.sps_hdrqfull;
182 }
183 if (blen)
184 ipath_dbg("%s\n", buf);
185
186 hdrqtail = ipath_get_hdrqtail(pd);
187 if (pd->port_head != hdrqtail) {
188 if (dd->ipath_lastport0rcv_cnt ==
189 ipath_stats.sps_port0pkts) {
190 ipath_cdbg(PKT, "missing rcv interrupts? "
191 "port0 hd=%x tl=%x; port0pkts %llx; write"
192 " hd (w/intr)\n",
193 pd->port_head, hdrqtail,
194 (unsigned long long)
195 ipath_stats.sps_port0pkts);
196 ipath_write_ureg(dd, ur_rcvhdrhead, hdrqtail |
197 dd->ipath_rhdrhead_intr_off, pd->port_port);
198 }
199 dd->ipath_lastport0rcv_cnt = ipath_stats.sps_port0pkts;
200 }
201}
202
203static void ipath_chk_errormask(struct ipath_devdata *dd)
204{
205 static u32 fixed;
206 u32 ctrl;
207 unsigned long errormask;
208 unsigned long hwerrs;
209
210 if (!dd->ipath_errormask || !(dd->ipath_flags & IPATH_INITTED))
211 return;
212
213 errormask = ipath_read_kreg64(dd, dd->ipath_kregs->kr_errormask);
214
215 if (errormask == dd->ipath_errormask)
216 return;
217 fixed++;
218
219 hwerrs = ipath_read_kreg64(dd, dd->ipath_kregs->kr_hwerrstatus);
220 ctrl = ipath_read_kreg32(dd, dd->ipath_kregs->kr_control);
221
222 ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
223 dd->ipath_errormask);
224
225 if ((hwerrs & dd->ipath_hwerrmask) ||
226 (ctrl & INFINIPATH_C_FREEZEMODE)) {
227
228 ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear, 0ULL);
229 ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear, 0ULL);
230 ipath_write_kreg(dd, dd->ipath_kregs->kr_intclear, 0ULL);
231 dev_info(&dd->pcidev->dev,
232 "errormask fixed(%u) %lx -> %lx, ctrl %x hwerr %lx\n",
233 fixed, errormask, (unsigned long)dd->ipath_errormask,
234 ctrl, hwerrs);
235 } else
236 ipath_dbg("errormask fixed(%u) %lx -> %lx, no freeze\n",
237 fixed, errormask,
238 (unsigned long)dd->ipath_errormask);
239}
240
241
242
243
244
245
246
247
248void ipath_get_faststats(unsigned long opaque)
249{
250 struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
251 int i;
252 static unsigned cnt;
253 unsigned long flags;
254 u64 traffic_wds;
255
256
257
258
259
260 if (!dd->ipath_kregbase || !(dd->ipath_flags & IPATH_INITTED) ||
261 ipath_diag_inuse)
262
263 goto done;
264
265
266
267
268
269
270 traffic_wds = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt) +
271 ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt);
272 spin_lock_irqsave(&dd->ipath_eep_st_lock, flags);
273 traffic_wds -= dd->ipath_traffic_wds;
274 dd->ipath_traffic_wds += traffic_wds;
275 if (traffic_wds >= IPATH_TRAFFIC_ACTIVE_THRESHOLD)
276 atomic_add(5, &dd->ipath_active_time);
277 spin_unlock_irqrestore(&dd->ipath_eep_st_lock, flags);
278
279 if (dd->ipath_flags & IPATH_32BITCOUNTERS) {
280 ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt);
281 ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt);
282 }
283
284 ipath_qcheck(dd);
285
286
287
288
289
290
291
292
293
294
295 if (dd->ipath_lasterror)
296 dd->ipath_lasterror = 0;
297 if (dd->ipath_lasthwerror)
298 dd->ipath_lasthwerror = 0;
299 if (dd->ipath_maskederrs
300 && time_after(jiffies, dd->ipath_unmasktime)) {
301 char ebuf[256];
302 int iserr;
303 iserr = ipath_decode_err(dd, ebuf, sizeof ebuf,
304 dd->ipath_maskederrs);
305 if (dd->ipath_maskederrs &
306 ~(INFINIPATH_E_RRCVEGRFULL | INFINIPATH_E_RRCVHDRFULL |
307 INFINIPATH_E_PKTERRS))
308 ipath_dev_err(dd, "Re-enabling masked errors "
309 "(%s)\n", ebuf);
310 else {
311
312
313
314
315
316
317
318 if (iserr)
319 ipath_dbg(
320 "Re-enabling queue full errors (%s)\n",
321 ebuf);
322 else
323 ipath_cdbg(ERRPKT, "Re-enabling packet"
324 " problem interrupt (%s)\n", ebuf);
325 }
326
327
328 dd->ipath_errormask |= dd->ipath_maskederrs;
329 ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
330 dd->ipath_errormask);
331 dd->ipath_maskederrs = 0;
332 }
333
334
335 if ((++cnt & 0x10)) {
336 for (i = (int) dd->ipath_cfgports; --i >= 0; ) {
337 struct ipath_portdata *pd = dd->ipath_pd[i];
338
339 if (pd && pd->port_lastrcvhdrqtail != -1)
340 pd->port_lastrcvhdrqtail = -1;
341 }
342 }
343
344 ipath_chk_errormask(dd);
345done:
346 mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5);
347}
348