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