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 <linux/delay.h>
35#include <linux/pci.h>
36#include <linux/vmalloc.h>
37
38#include "qib.h"
39#include "qib_qsfp.h"
40
41
42
43
44
45#define QSFP_MAX_RETRY 4
46
47static int qsfp_read(struct qib_pportdata *ppd, int addr, void *bp, int len)
48{
49 struct qib_devdata *dd = ppd->dd;
50 u32 out, mask;
51 int ret, cnt, pass = 0;
52 int stuck = 0;
53 u8 *buff = bp;
54
55 ret = mutex_lock_interruptible(&dd->eep_lock);
56 if (ret)
57 goto no_unlock;
58
59 if (dd->twsi_eeprom_dev == QIB_TWSI_NO_DEV) {
60 ret = -ENXIO;
61 goto bail;
62 }
63
64
65
66
67
68
69
70
71 mask = QSFP_GPIO_MOD_SEL_N | QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
72 out = QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
73 if (ppd->hw_pidx) {
74 mask <<= QSFP_GPIO_PORT2_SHIFT;
75 out <<= QSFP_GPIO_PORT2_SHIFT;
76 }
77
78 dd->f_gpio_mod(dd, out, mask, mask);
79
80
81
82
83
84 msleep(20);
85
86
87 ret = qib_twsi_reset(dd);
88 if (ret) {
89 qib_dev_porterr(dd, ppd->port,
90 "QSFP interface Reset for read failed\n");
91 ret = -EIO;
92 stuck = 1;
93 goto deselect;
94 }
95
96
97
98 cnt = 0;
99 while (cnt < len) {
100 unsigned in_page;
101 int wlen = len - cnt;
102
103 in_page = addr % QSFP_PAGESIZE;
104 if ((in_page + wlen) > QSFP_PAGESIZE)
105 wlen = QSFP_PAGESIZE - in_page;
106 ret = qib_twsi_blk_rd(dd, QSFP_DEV, addr, buff + cnt, wlen);
107
108 if (ret && cnt == 0 && ++pass < QSFP_MAX_RETRY)
109 continue;
110 if (ret) {
111
112 ret = -EIO;
113 goto deselect;
114 }
115 addr += wlen;
116 cnt += wlen;
117 }
118 ret = cnt;
119
120deselect:
121
122
123
124
125
126 udelay(10);
127
128 dd->f_gpio_mod(dd, mask, mask, mask);
129
130
131
132
133
134
135 if (stuck)
136 qib_dev_err(dd, "QSFP interface bus stuck non-idle\n");
137
138 if (pass >= QSFP_MAX_RETRY && ret)
139 qib_dev_porterr(dd, ppd->port, "QSFP failed even retrying\n");
140 else if (pass)
141 qib_dev_porterr(dd, ppd->port, "QSFP retries: %d\n", pass);
142
143 msleep(20);
144
145bail:
146 mutex_unlock(&dd->eep_lock);
147
148no_unlock:
149 return ret;
150}
151
152
153
154
155
156
157static int qib_qsfp_write(struct qib_pportdata *ppd, int addr, void *bp,
158 int len)
159{
160 struct qib_devdata *dd = ppd->dd;
161 u32 out, mask;
162 int ret, cnt;
163 u8 *buff = bp;
164
165 ret = mutex_lock_interruptible(&dd->eep_lock);
166 if (ret)
167 goto no_unlock;
168
169 if (dd->twsi_eeprom_dev == QIB_TWSI_NO_DEV) {
170 ret = -ENXIO;
171 goto bail;
172 }
173
174
175
176
177
178
179
180
181 mask = QSFP_GPIO_MOD_SEL_N | QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
182 out = QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
183 if (ppd->hw_pidx) {
184 mask <<= QSFP_GPIO_PORT2_SHIFT;
185 out <<= QSFP_GPIO_PORT2_SHIFT;
186 }
187 dd->f_gpio_mod(dd, out, mask, mask);
188
189
190
191
192
193 msleep(20);
194
195
196 ret = qib_twsi_reset(dd);
197 if (ret) {
198 qib_dev_porterr(dd, ppd->port,
199 "QSFP interface Reset for write failed\n");
200 ret = -EIO;
201 goto deselect;
202 }
203
204
205
206 cnt = 0;
207 while (cnt < len) {
208 unsigned in_page;
209 int wlen = len - cnt;
210
211 in_page = addr % QSFP_PAGESIZE;
212 if ((in_page + wlen) > QSFP_PAGESIZE)
213 wlen = QSFP_PAGESIZE - in_page;
214 ret = qib_twsi_blk_wr(dd, QSFP_DEV, addr, buff + cnt, wlen);
215 if (ret) {
216
217 ret = -EIO;
218 goto deselect;
219 }
220 addr += wlen;
221 cnt += wlen;
222 }
223 ret = cnt;
224
225deselect:
226
227
228
229
230
231 udelay(10);
232
233 dd->f_gpio_mod(dd, mask, mask, mask);
234
235
236
237
238
239 msleep(20);
240
241bail:
242 mutex_unlock(&dd->eep_lock);
243
244no_unlock:
245 return ret;
246}
247
248
249
250
251
252
253static int qsfp_cks(struct qib_pportdata *ppd, int first, int next)
254{
255 int ret;
256 u16 cks;
257 u8 bval;
258
259 cks = 0;
260 while (first < next) {
261 ret = qsfp_read(ppd, first, &bval, 1);
262 if (ret < 0)
263 goto bail;
264 cks += bval;
265 ++first;
266 }
267 ret = cks & 0xFF;
268bail:
269 return ret;
270
271}
272
273int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, struct qib_qsfp_cache *cp)
274{
275 int ret;
276 int idx;
277 u16 cks;
278 u8 peek[4];
279
280
281 memset(cp, 0, sizeof(*cp));
282
283 if (!qib_qsfp_mod_present(ppd)) {
284 ret = -ENODEV;
285 goto bail;
286 }
287
288 ret = qsfp_read(ppd, 0, peek, 3);
289 if (ret < 0)
290 goto bail;
291 if ((peek[0] & 0xFE) != 0x0C)
292 qib_dev_porterr(ppd->dd, ppd->port,
293 "QSFP byte0 is 0x%02X, S/B 0x0C/D\n", peek[0]);
294
295 if ((peek[2] & 4) == 0) {
296
297
298
299
300 u8 poke = 0;
301
302 ret = qib_qsfp_write(ppd, 127, &poke, 1);
303 udelay(50);
304 if (ret != 1) {
305 qib_dev_porterr(ppd->dd, ppd->port,
306 "Failed QSFP Page set\n");
307 goto bail;
308 }
309 }
310
311 ret = qsfp_read(ppd, QSFP_MOD_ID_OFFS, &cp->id, 1);
312 if (ret < 0)
313 goto bail;
314 if ((cp->id & 0xFE) != 0x0C)
315 qib_dev_porterr(ppd->dd, ppd->port,
316 "QSFP ID byte is 0x%02X, S/B 0x0C/D\n", cp->id);
317 cks = cp->id;
318
319 ret = qsfp_read(ppd, QSFP_MOD_PWR_OFFS, &cp->pwr, 1);
320 if (ret < 0)
321 goto bail;
322 cks += cp->pwr;
323
324 ret = qsfp_cks(ppd, QSFP_MOD_PWR_OFFS + 1, QSFP_MOD_LEN_OFFS);
325 if (ret < 0)
326 goto bail;
327 cks += ret;
328
329 ret = qsfp_read(ppd, QSFP_MOD_LEN_OFFS, &cp->len, 1);
330 if (ret < 0)
331 goto bail;
332 cks += cp->len;
333
334 ret = qsfp_read(ppd, QSFP_MOD_TECH_OFFS, &cp->tech, 1);
335 if (ret < 0)
336 goto bail;
337 cks += cp->tech;
338
339 ret = qsfp_read(ppd, QSFP_VEND_OFFS, &cp->vendor, QSFP_VEND_LEN);
340 if (ret < 0)
341 goto bail;
342 for (idx = 0; idx < QSFP_VEND_LEN; ++idx)
343 cks += cp->vendor[idx];
344
345 ret = qsfp_read(ppd, QSFP_IBXCV_OFFS, &cp->xt_xcv, 1);
346 if (ret < 0)
347 goto bail;
348 cks += cp->xt_xcv;
349
350 ret = qsfp_read(ppd, QSFP_VOUI_OFFS, &cp->oui, QSFP_VOUI_LEN);
351 if (ret < 0)
352 goto bail;
353 for (idx = 0; idx < QSFP_VOUI_LEN; ++idx)
354 cks += cp->oui[idx];
355
356 ret = qsfp_read(ppd, QSFP_PN_OFFS, &cp->partnum, QSFP_PN_LEN);
357 if (ret < 0)
358 goto bail;
359 for (idx = 0; idx < QSFP_PN_LEN; ++idx)
360 cks += cp->partnum[idx];
361
362 ret = qsfp_read(ppd, QSFP_REV_OFFS, &cp->rev, QSFP_REV_LEN);
363 if (ret < 0)
364 goto bail;
365 for (idx = 0; idx < QSFP_REV_LEN; ++idx)
366 cks += cp->rev[idx];
367
368 ret = qsfp_read(ppd, QSFP_ATTEN_OFFS, &cp->atten, QSFP_ATTEN_LEN);
369 if (ret < 0)
370 goto bail;
371 for (idx = 0; idx < QSFP_ATTEN_LEN; ++idx)
372 cks += cp->atten[idx];
373
374 ret = qsfp_cks(ppd, QSFP_ATTEN_OFFS + QSFP_ATTEN_LEN, QSFP_CC_OFFS);
375 if (ret < 0)
376 goto bail;
377 cks += ret;
378
379 cks &= 0xFF;
380 ret = qsfp_read(ppd, QSFP_CC_OFFS, &cp->cks1, 1);
381 if (ret < 0)
382 goto bail;
383 if (cks != cp->cks1)
384 qib_dev_porterr(ppd->dd, ppd->port,
385 "QSFP cks1 is %02X, computed %02X\n", cp->cks1,
386 cks);
387
388
389 ret = qsfp_cks(ppd, QSFP_CC_OFFS + 1, QSFP_SN_OFFS);
390 if (ret < 0)
391 goto bail;
392 cks = ret;
393
394 ret = qsfp_read(ppd, QSFP_SN_OFFS, &cp->serial, QSFP_SN_LEN);
395 if (ret < 0)
396 goto bail;
397 for (idx = 0; idx < QSFP_SN_LEN; ++idx)
398 cks += cp->serial[idx];
399
400 ret = qsfp_read(ppd, QSFP_DATE_OFFS, &cp->date, QSFP_DATE_LEN);
401 if (ret < 0)
402 goto bail;
403 for (idx = 0; idx < QSFP_DATE_LEN; ++idx)
404 cks += cp->date[idx];
405
406 ret = qsfp_read(ppd, QSFP_LOT_OFFS, &cp->lot, QSFP_LOT_LEN);
407 if (ret < 0)
408 goto bail;
409 for (idx = 0; idx < QSFP_LOT_LEN; ++idx)
410 cks += cp->lot[idx];
411
412 ret = qsfp_cks(ppd, QSFP_LOT_OFFS + QSFP_LOT_LEN, QSFP_CC_EXT_OFFS);
413 if (ret < 0)
414 goto bail;
415 cks += ret;
416
417 ret = qsfp_read(ppd, QSFP_CC_EXT_OFFS, &cp->cks2, 1);
418 if (ret < 0)
419 goto bail;
420 cks &= 0xFF;
421 if (cks != cp->cks2)
422 qib_dev_porterr(ppd->dd, ppd->port,
423 "QSFP cks2 is %02X, computed %02X\n", cp->cks2,
424 cks);
425 return 0;
426
427bail:
428 cp->id = 0;
429 return ret;
430}
431
432const char * const qib_qsfp_devtech[16] = {
433 "850nm VCSEL", "1310nm VCSEL", "1550nm VCSEL", "1310nm FP",
434 "1310nm DFB", "1550nm DFB", "1310nm EML", "1550nm EML",
435 "Cu Misc", "1490nm DFB", "Cu NoEq", "Cu Eq",
436 "Undef", "Cu Active BothEq", "Cu FarEq", "Cu NearEq"
437};
438
439#define QSFP_DUMP_CHUNK 16
440#define QSFP_DEFAULT_HDR_CNT 224
441
442static const char *pwr_codes = "1.5W2.0W2.5W3.5W";
443
444int qib_qsfp_mod_present(struct qib_pportdata *ppd)
445{
446 u32 mask;
447 int ret;
448
449 mask = QSFP_GPIO_MOD_PRS_N <<
450 (ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT);
451 ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
452
453 return !((ret & mask) >>
454 ((ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT) + 3));
455}
456
457
458
459
460
461void qib_qsfp_init(struct qib_qsfp_data *qd,
462 void (*fevent)(struct work_struct *))
463{
464 u32 mask, highs;
465
466 struct qib_devdata *dd = qd->ppd->dd;
467
468
469 INIT_WORK(&qd->work, fevent);
470
471
472
473
474
475
476 mask = QSFP_GPIO_MOD_SEL_N | QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
477 highs = mask - QSFP_GPIO_MOD_RST_N;
478 if (qd->ppd->hw_pidx) {
479 mask <<= QSFP_GPIO_PORT2_SHIFT;
480 highs <<= QSFP_GPIO_PORT2_SHIFT;
481 }
482 dd->f_gpio_mod(dd, highs, mask, mask);
483 udelay(20);
484
485 dd->f_gpio_mod(dd, mask, mask, mask);
486}
487
488int qib_qsfp_dump(struct qib_pportdata *ppd, char *buf, int len)
489{
490 struct qib_qsfp_cache cd;
491 u8 bin_buff[QSFP_DUMP_CHUNK];
492 char lenstr[6];
493 int sofar, ret;
494 int bidx = 0;
495
496 sofar = 0;
497 ret = qib_refresh_qsfp_cache(ppd, &cd);
498 if (ret < 0)
499 goto bail;
500
501 lenstr[0] = ' ';
502 lenstr[1] = '\0';
503 if (QSFP_IS_CU(cd.tech))
504 sprintf(lenstr, "%dM ", cd.len);
505
506 sofar += scnprintf(buf + sofar, len - sofar, "PWR:%.3sW\n", pwr_codes +
507 (QSFP_PWR(cd.pwr) * 4));
508
509 sofar += scnprintf(buf + sofar, len - sofar, "TECH:%s%s\n", lenstr,
510 qib_qsfp_devtech[cd.tech >> 4]);
511
512 sofar += scnprintf(buf + sofar, len - sofar, "Vendor:%.*s\n",
513 QSFP_VEND_LEN, cd.vendor);
514
515 sofar += scnprintf(buf + sofar, len - sofar, "OUI:%06X\n",
516 QSFP_OUI(cd.oui));
517
518 sofar += scnprintf(buf + sofar, len - sofar, "Part#:%.*s\n",
519 QSFP_PN_LEN, cd.partnum);
520 sofar += scnprintf(buf + sofar, len - sofar, "Rev:%.*s\n",
521 QSFP_REV_LEN, cd.rev);
522 if (QSFP_IS_CU(cd.tech))
523 sofar += scnprintf(buf + sofar, len - sofar, "Atten:%d, %d\n",
524 QSFP_ATTEN_SDR(cd.atten),
525 QSFP_ATTEN_DDR(cd.atten));
526 sofar += scnprintf(buf + sofar, len - sofar, "Serial:%.*s\n",
527 QSFP_SN_LEN, cd.serial);
528 sofar += scnprintf(buf + sofar, len - sofar, "Date:%.*s\n",
529 QSFP_DATE_LEN, cd.date);
530 sofar += scnprintf(buf + sofar, len - sofar, "Lot:%.*s\n",
531 QSFP_LOT_LEN, cd.lot);
532
533 while (bidx < QSFP_DEFAULT_HDR_CNT) {
534 int iidx;
535
536 ret = qsfp_read(ppd, bidx, bin_buff, QSFP_DUMP_CHUNK);
537 if (ret < 0)
538 goto bail;
539 for (iidx = 0; iidx < ret; ++iidx) {
540 sofar += scnprintf(buf + sofar, len-sofar, " %02X",
541 bin_buff[iidx]);
542 }
543 sofar += scnprintf(buf + sofar, len - sofar, "\n");
544 bidx += QSFP_DUMP_CHUNK;
545 }
546 ret = sofar;
547bail:
548 return ret;
549}
550