]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/staging/rdma/hfi1/platform.c
staging/rdma/hfi1: Fetch platform configuration data from EFI variable
[mirror_ubuntu-focal-kernel.git] / drivers / staging / rdma / hfi1 / platform.c
CommitLineData
8ebd4cf1
EH
1/*
2 *
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
5 *
6 * GPL LICENSE SUMMARY
7 *
8 * Copyright(c) 2015 Intel Corporation.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * BSD LICENSE
20 *
21 * Copyright(c) 2015 Intel Corporation.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 *
27 * - Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 * - Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in
31 * the documentation and/or other materials provided with the
32 * distribution.
33 * - Neither the name of Intel Corporation nor the names of its
34 * contributors may be used to endorse or promote products derived
35 * from this software without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
38 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
39 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
40 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
41 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48 *
49 */
c3838b39 50
8ebd4cf1 51#include "hfi.h"
c3838b39
EH
52#include "efivar.h"
53
54void get_platform_config(struct hfi1_devdata *dd)
55{
56 int ret = 0;
57 unsigned long size = 0;
58 u8 *temp_platform_config = NULL;
59
60 ret = read_hfi1_efi_var(dd, "configuration", &size,
61 (void **)&temp_platform_config);
62 if (ret) {
63 dd_dev_info(dd,
64 "%s: Failed to get platform config from UEFI, falling back to request firmware\n",
65 __func__);
66 /* fall back to request firmware */
67 platform_config_load = 1;
68 goto bail;
69 }
70
71 dd->platform_config.data = temp_platform_config;
72 dd->platform_config.size = size;
73
74bail:
75 /* exit */;
76}
77
78void free_platform_config(struct hfi1_devdata *dd)
79{
80 if (!platform_config_load) {
81 /*
82 * was loaded from EFI, release memory
83 * allocated by read_efi_var
84 */
85 kfree(dd->platform_config.data);
86 }
87 /*
88 * else do nothing, dispose_firmware will release
89 * struct firmware platform_config on driver exit
90 */
91}
8ebd4cf1
EH
92
93int set_qsfp_tx(struct hfi1_pportdata *ppd, int on)
94{
95 u8 tx_ctrl_byte = on ? 0x0 : 0xF;
96 int ret = 0;
97
98 ret = qsfp_write(ppd, ppd->dd->hfi1_id, QSFP_TX_CTRL_BYTE_OFFS,
99 &tx_ctrl_byte, 1);
100 /* we expected 1, so consider 0 an error */
101 if (ret == 0)
102 ret = -EIO;
103 else if (ret == 1)
104 ret = 0;
105 return ret;
106}
107
108static int qual_power(struct hfi1_pportdata *ppd)
109{
110 u32 cable_power_class = 0, power_class_max = 0;
111 u8 *cache = ppd->qsfp_info.cache;
112 int ret = 0;
113
114 ret = get_platform_config_field(
115 ppd->dd, PLATFORM_CONFIG_SYSTEM_TABLE, 0,
116 SYSTEM_TABLE_QSFP_POWER_CLASS_MAX, &power_class_max, 4);
117 if (ret)
118 return ret;
119
120 if (QSFP_HIGH_PWR(cache[QSFP_MOD_PWR_OFFS]) != 4)
121 cable_power_class = QSFP_HIGH_PWR(cache[QSFP_MOD_PWR_OFFS]);
122 else
123 cable_power_class = QSFP_PWR(cache[QSFP_MOD_PWR_OFFS]);
124
125 if (cable_power_class <= 3 && cable_power_class > (power_class_max - 1))
126 ppd->offline_disabled_reason =
127 HFI1_ODR_MASK(OPA_LINKDOWN_REASON_POWER_POLICY);
128 else if (cable_power_class > 4 && cable_power_class > (power_class_max))
129 ppd->offline_disabled_reason =
130 HFI1_ODR_MASK(OPA_LINKDOWN_REASON_POWER_POLICY);
131 /*
132 * cable_power_class will never have value 4 as this simply
133 * means the high power settings are unused
134 */
135
136 if (ppd->offline_disabled_reason ==
137 HFI1_ODR_MASK(OPA_LINKDOWN_REASON_POWER_POLICY)) {
138 dd_dev_info(
139 ppd->dd,
140 "%s: Port disabled due to system power restrictions\n",
141 __func__);
142 ret = -EPERM;
143 }
144 return ret;
145}
146
147static int qual_bitrate(struct hfi1_pportdata *ppd)
148{
149 u16 lss = ppd->link_speed_supported, lse = ppd->link_speed_enabled;
150 u8 *cache = ppd->qsfp_info.cache;
151
152 if ((lss & OPA_LINK_SPEED_25G) && (lse & OPA_LINK_SPEED_25G) &&
153 cache[QSFP_NOM_BIT_RATE_250_OFFS] < 0x64)
154 ppd->offline_disabled_reason =
155 HFI1_ODR_MASK(OPA_LINKDOWN_REASON_LINKSPEED_POLICY);
156
157 if ((lss & OPA_LINK_SPEED_12_5G) && (lse & OPA_LINK_SPEED_12_5G) &&
158 cache[QSFP_NOM_BIT_RATE_100_OFFS] < 0x7D)
159 ppd->offline_disabled_reason =
160 HFI1_ODR_MASK(OPA_LINKDOWN_REASON_LINKSPEED_POLICY);
161
162 if (ppd->offline_disabled_reason ==
163 HFI1_ODR_MASK(OPA_LINKDOWN_REASON_LINKSPEED_POLICY)) {
164 dd_dev_info(
165 ppd->dd,
166 "%s: Cable failed bitrate check, disabling port\n",
167 __func__);
168 return -EPERM;
169 }
170 return 0;
171}
172
173static int set_qsfp_high_power(struct hfi1_pportdata *ppd)
174{
175 u8 cable_power_class = 0, power_ctrl_byte = 0;
176 u8 *cache = ppd->qsfp_info.cache;
177 int ret;
178
179 if (QSFP_HIGH_PWR(cache[QSFP_MOD_PWR_OFFS]) != 4)
180 cable_power_class = QSFP_HIGH_PWR(cache[QSFP_MOD_PWR_OFFS]);
181 else
182 cable_power_class = QSFP_PWR(cache[QSFP_MOD_PWR_OFFS]);
183
184 if (cable_power_class) {
185 power_ctrl_byte = cache[QSFP_PWR_CTRL_BYTE_OFFS];
186
187 power_ctrl_byte |= 1;
188 power_ctrl_byte &= ~(0x2);
189
190 ret = qsfp_write(ppd, ppd->dd->hfi1_id,
191 QSFP_PWR_CTRL_BYTE_OFFS,
192 &power_ctrl_byte, 1);
193 if (ret != 1)
194 return -EIO;
195
196 if (cable_power_class > 3) {
197 /* > power class 4*/
198 power_ctrl_byte |= (1 << 2);
199 ret = qsfp_write(ppd, ppd->dd->hfi1_id,
200 QSFP_PWR_CTRL_BYTE_OFFS,
201 &power_ctrl_byte, 1);
202 if (ret != 1)
203 return -EIO;
204 }
205
206 /* SFF 8679 rev 1.7 LPMode Deassert time */
207 msleep(300);
208 }
209 return 0;
210}
211
212static void apply_rx_cdr(struct hfi1_pportdata *ppd,
213 u32 rx_preset_index,
214 u8 *cdr_ctrl_byte)
215{
216 u32 rx_preset;
217 u8 *cache = ppd->qsfp_info.cache;
218
219 if (!((cache[QSFP_MOD_PWR_OFFS] & 0x4) &&
220 (cache[QSFP_CDR_INFO_OFFS] & 0x40)))
221 return;
222
223 /* rx_preset preset to zero to catch error */
224 get_platform_config_field(
225 ppd->dd, PLATFORM_CONFIG_RX_PRESET_TABLE,
226 rx_preset_index, RX_PRESET_TABLE_QSFP_RX_CDR_APPLY,
227 &rx_preset, 4);
228
229 if (!rx_preset) {
230 dd_dev_info(
231 ppd->dd,
232 "%s: RX_CDR_APPLY is set to disabled\n",
233 __func__);
234 return;
235 }
236 get_platform_config_field(
237 ppd->dd, PLATFORM_CONFIG_RX_PRESET_TABLE,
238 rx_preset_index, RX_PRESET_TABLE_QSFP_RX_CDR,
239 &rx_preset, 4);
240
241 /* Expand cdr setting to all 4 lanes */
242 rx_preset = (rx_preset | (rx_preset << 1) |
243 (rx_preset << 2) | (rx_preset << 3));
244
245 if (rx_preset) {
246 *cdr_ctrl_byte |= rx_preset;
247 } else {
248 *cdr_ctrl_byte &= rx_preset;
249 /* Preserve current TX CDR status */
250 *cdr_ctrl_byte |= (cache[QSFP_CDR_CTRL_BYTE_OFFS] & 0xF0);
251 }
252}
253
254static void apply_tx_cdr(struct hfi1_pportdata *ppd,
255 u32 tx_preset_index,
256 u8 *ctr_ctrl_byte)
257{
258 u32 tx_preset;
259 u8 *cache = ppd->qsfp_info.cache;
260
261 if (!((cache[QSFP_MOD_PWR_OFFS] & 0x8) &&
262 (cache[QSFP_CDR_INFO_OFFS] & 0x80)))
263 return;
264
265 get_platform_config_field(
266 ppd->dd,
267 PLATFORM_CONFIG_TX_PRESET_TABLE, tx_preset_index,
268 TX_PRESET_TABLE_QSFP_TX_CDR_APPLY, &tx_preset, 4);
269
270 if (!tx_preset) {
271 dd_dev_info(
272 ppd->dd,
273 "%s: TX_CDR_APPLY is set to disabled\n",
274 __func__);
275 return;
276 }
277 get_platform_config_field(
278 ppd->dd,
279 PLATFORM_CONFIG_TX_PRESET_TABLE,
280 tx_preset_index,
281 TX_PRESET_TABLE_QSFP_TX_CDR, &tx_preset, 4);
282
283 /* Expand cdr setting to all 4 lanes */
284 tx_preset = (tx_preset | (tx_preset << 1) |
285 (tx_preset << 2) | (tx_preset << 3));
286
287 if (tx_preset)
288 *ctr_ctrl_byte |= (tx_preset << 4);
289 else
290 /* Preserve current/determined RX CDR status */
291 *ctr_ctrl_byte &= ((tx_preset << 4) | 0xF);
292}
293
294static void apply_cdr_settings(
295 struct hfi1_pportdata *ppd, u32 rx_preset_index,
296 u32 tx_preset_index)
297{
298 u8 *cache = ppd->qsfp_info.cache;
299 u8 cdr_ctrl_byte = cache[QSFP_CDR_CTRL_BYTE_OFFS];
300
301 apply_rx_cdr(ppd, rx_preset_index, &cdr_ctrl_byte);
302
303 apply_tx_cdr(ppd, tx_preset_index, &cdr_ctrl_byte);
304
305 qsfp_write(ppd, ppd->dd->hfi1_id, QSFP_CDR_CTRL_BYTE_OFFS,
306 &cdr_ctrl_byte, 1);
307}
308
309static void apply_tx_eq_auto(struct hfi1_pportdata *ppd)
310{
311 u8 *cache = ppd->qsfp_info.cache;
312 u8 tx_eq;
313
314 if (!(cache[QSFP_EQ_INFO_OFFS] & 0x8))
315 return;
316 /* Disable adaptive TX EQ if present */
317 tx_eq = cache[(128 * 3) + 241];
318 tx_eq &= 0xF0;
319 qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 241, &tx_eq, 1);
320}
321
322static void apply_tx_eq_prog(struct hfi1_pportdata *ppd, u32 tx_preset_index)
323{
324 u8 *cache = ppd->qsfp_info.cache;
325 u32 tx_preset;
326 u8 tx_eq;
327
328 if (!(cache[QSFP_EQ_INFO_OFFS] & 0x4))
329 return;
330
331 get_platform_config_field(
332 ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE,
333 tx_preset_index, TX_PRESET_TABLE_QSFP_TX_EQ_APPLY,
334 &tx_preset, 4);
335 if (!tx_preset) {
336 dd_dev_info(
337 ppd->dd,
338 "%s: TX_EQ_APPLY is set to disabled\n",
339 __func__);
340 return;
341 }
342 get_platform_config_field(
343 ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE,
344 tx_preset_index, TX_PRESET_TABLE_QSFP_TX_EQ,
345 &tx_preset, 4);
346
347 if (((cache[(128 * 3) + 224] & 0xF0) >> 4) < tx_preset) {
348 dd_dev_info(
349 ppd->dd,
350 "%s: TX EQ %x unsupported\n",
351 __func__, tx_preset);
352
353 dd_dev_info(
354 ppd->dd,
355 "%s: Applying EQ %x\n",
356 __func__, cache[608] & 0xF0);
357
358 tx_preset = (cache[608] & 0xF0) >> 4;
359 }
360
361 tx_eq = tx_preset | (tx_preset << 4);
362 qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 234, &tx_eq, 1);
363 qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 235, &tx_eq, 1);
364}
365
366static void apply_rx_eq_emp(struct hfi1_pportdata *ppd, u32 rx_preset_index)
367{
368 u32 rx_preset;
369 u8 rx_eq, *cache = ppd->qsfp_info.cache;
370
371 if (!(cache[QSFP_EQ_INFO_OFFS] & 0x2))
372 return;
373 get_platform_config_field(
374 ppd->dd, PLATFORM_CONFIG_RX_PRESET_TABLE,
375 rx_preset_index, RX_PRESET_TABLE_QSFP_RX_EMP_APPLY,
376 &rx_preset, 4);
377
378 if (!rx_preset) {
379 dd_dev_info(
380 ppd->dd,
381 "%s: RX_EMP_APPLY is set to disabled\n",
382 __func__);
383 return;
384 }
385 get_platform_config_field(
386 ppd->dd, PLATFORM_CONFIG_RX_PRESET_TABLE,
387 rx_preset_index, RX_PRESET_TABLE_QSFP_RX_EMP,
388 &rx_preset, 4);
389
390 if ((cache[(128 * 3) + 224] & 0xF) < rx_preset) {
391 dd_dev_info(
392 ppd->dd,
393 "%s: Requested RX EMP %x\n",
394 __func__, rx_preset);
395
396 dd_dev_info(
397 ppd->dd,
398 "%s: Applying supported EMP %x\n",
399 __func__, cache[608] & 0xF);
400
401 rx_preset = cache[608] & 0xF;
402 }
403
404 rx_eq = rx_preset | (rx_preset << 4);
405
406 qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 236, &rx_eq, 1);
407 qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 237, &rx_eq, 1);
408}
409
410static void apply_eq_settings(struct hfi1_pportdata *ppd,
411 u32 rx_preset_index, u32 tx_preset_index)
412{
413 u8 *cache = ppd->qsfp_info.cache;
414
415 /* no point going on w/o a page 3 */
416 if (cache[2] & 4) {
417 dd_dev_info(ppd->dd,
418 "%s: Upper page 03 not present\n",
419 __func__);
420 return;
421 }
422
423 apply_tx_eq_auto(ppd);
424
425 apply_tx_eq_prog(ppd, tx_preset_index);
426
427 apply_rx_eq_emp(ppd, rx_preset_index);
428}
429
430static void apply_rx_amplitude_settings(
431 struct hfi1_pportdata *ppd, u32 rx_preset_index,
432 u32 tx_preset_index)
433{
434 u32 rx_preset;
435 u8 rx_amp = 0, i = 0, preferred = 0, *cache = ppd->qsfp_info.cache;
436
437 /* no point going on w/o a page 3 */
438 if (cache[2] & 4) {
439 dd_dev_info(ppd->dd,
440 "%s: Upper page 03 not present\n",
441 __func__);
442 return;
443 }
444 if (!(cache[QSFP_EQ_INFO_OFFS] & 0x1)) {
445 dd_dev_info(ppd->dd,
446 "%s: RX_AMP_APPLY is set to disabled\n",
447 __func__);
448 return;
449 }
450
451 get_platform_config_field(ppd->dd,
452 PLATFORM_CONFIG_RX_PRESET_TABLE,
453 rx_preset_index,
454 RX_PRESET_TABLE_QSFP_RX_AMP_APPLY,
455 &rx_preset, 4);
456
457 if (!rx_preset) {
458 dd_dev_info(ppd->dd,
459 "%s: RX_AMP_APPLY is set to disabled\n",
460 __func__);
461 return;
462 }
463 get_platform_config_field(ppd->dd,
464 PLATFORM_CONFIG_RX_PRESET_TABLE,
465 rx_preset_index,
466 RX_PRESET_TABLE_QSFP_RX_AMP,
467 &rx_preset, 4);
468
469 dd_dev_info(ppd->dd,
470 "%s: Requested RX AMP %x\n",
471 __func__,
472 rx_preset);
473
474 for (i = 0; i < 4; i++) {
475 if (cache[(128 * 3) + 225] & (1 << i)) {
476 preferred = i;
477 if (preferred == rx_preset)
478 break;
479 }
480 }
481
482 /*
483 * Verify that preferred RX amplitude is not just a
484 * fall through of the default
485 */
486 if (!preferred && !(cache[(128 * 3) + 225] & 0x1)) {
487 dd_dev_info(ppd->dd, "No supported RX AMP, not applying\n");
488 return;
489 }
490
491 dd_dev_info(ppd->dd,
492 "%s: Applying RX AMP %x\n", __func__, preferred);
493
494 rx_amp = preferred | (preferred << 4);
495 qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 238, &rx_amp, 1);
496 qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 239, &rx_amp, 1);
497}
498
499#define OPA_INVALID_INDEX 0xFFF
500
501static void apply_tx_lanes(struct hfi1_pportdata *ppd, u32 config_data,
502 const char *message)
503{
504 u8 i;
505 int ret = HCMD_SUCCESS;
506
507 for (i = 0; i < 4; i++) {
508 ret = load_8051_config(ppd->dd, 0, i, config_data);
509 if (ret != HCMD_SUCCESS) {
510 dd_dev_err(
511 ppd->dd,
512 "%s: %s for lane %u failed\n",
513 message, __func__, i);
514 }
515 }
516}
517
518static void apply_tunings(
519 struct hfi1_pportdata *ppd, u32 tx_preset_index,
520 u8 tuning_method, u32 total_atten, u8 limiting_active)
521{
522 int ret = 0;
523 u32 config_data = 0, tx_preset = 0;
524 u8 precur = 0, attn = 0, postcur = 0, external_device_config = 0;
525 u8 *cache = ppd->qsfp_info.cache;
526
527 read_8051_config(ppd->dd, LINK_OPTIMIZATION_SETTINGS,
528 GENERAL_CONFIG, &config_data);
529 config_data |= limiting_active;
530 ret = load_8051_config(ppd->dd, LINK_OPTIMIZATION_SETTINGS,
531 GENERAL_CONFIG, config_data);
532 if (ret != HCMD_SUCCESS)
533 dd_dev_err(
534 ppd->dd,
535 "%s: Failed to set enable external device config\n",
536 __func__);
537
538 config_data = 0; /* re-init */
539 read_8051_config(ppd->dd, LINK_TUNING_PARAMETERS, GENERAL_CONFIG,
540 &config_data);
541 config_data |= tuning_method;
542 ret = load_8051_config(ppd->dd, LINK_TUNING_PARAMETERS, GENERAL_CONFIG,
543 config_data);
544 if (ret != HCMD_SUCCESS)
545 dd_dev_err(ppd->dd, "%s: Failed to set tuning method\n",
546 __func__);
547
548 external_device_config =
549 ((cache[QSFP_MOD_PWR_OFFS] & 0x4) << 3) |
550 ((cache[QSFP_MOD_PWR_OFFS] & 0x8) << 2) |
551 ((cache[QSFP_EQ_INFO_OFFS] & 0x2) << 1) |
552 (cache[QSFP_EQ_INFO_OFFS] & 0x4);
553
554 config_data = 0; /* re-init */
555 read_8051_config(ppd->dd, DC_HOST_COMM_SETTINGS, GENERAL_CONFIG,
556 &config_data);
557 config_data |= (external_device_config << 24);
558 ret = load_8051_config(ppd->dd, DC_HOST_COMM_SETTINGS, GENERAL_CONFIG,
559 config_data);
560 if (ret != HCMD_SUCCESS)
561 dd_dev_err(
562 ppd->dd,
563 "%s: Failed to set external device config parameters\n",
564 __func__);
565
566 config_data = 0; /* re-init */
567 read_8051_config(ppd->dd, TX_SETTINGS, GENERAL_CONFIG, &config_data);
568 if ((ppd->link_speed_supported & OPA_LINK_SPEED_25G) &&
569 (ppd->link_speed_enabled & OPA_LINK_SPEED_25G))
570 config_data |= 0x02;
571 if ((ppd->link_speed_supported & OPA_LINK_SPEED_12_5G) &&
572 (ppd->link_speed_enabled & OPA_LINK_SPEED_12_5G))
573 config_data |= 0x01;
574 ret = load_8051_config(ppd->dd, TX_SETTINGS, GENERAL_CONFIG,
575 config_data);
576 if (ret != HCMD_SUCCESS)
577 dd_dev_err(
578 ppd->dd,
579 "%s: Failed to set external device config parameters\n",
580 __func__);
581
582 config_data = (total_atten << 8) | (total_atten);
583
584 apply_tx_lanes(ppd, config_data, "Setting channel loss");
585
586 if (tx_preset_index == OPA_INVALID_INDEX)
587 return;
588
589 get_platform_config_field(
590 ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE, tx_preset_index,
591 TX_PRESET_TABLE_PRECUR, &tx_preset, 4);
592 precur = tx_preset;
593
594 get_platform_config_field(
595 ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE,
596 tx_preset_index, TX_PRESET_TABLE_ATTN, &tx_preset, 4);
597 attn = tx_preset;
598
599 get_platform_config_field(
600 ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE,
601 tx_preset_index, TX_PRESET_TABLE_POSTCUR, &tx_preset, 4);
602 postcur = tx_preset;
603
604 config_data = precur | (attn << 8) | (postcur << 16);
605
606 apply_tx_lanes(ppd, config_data, "Applying TX settings");
607}
608
609static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
610 u32 *ptr_rx_preset, u32 *ptr_total_atten)
611{
612 int ret = 0;
613 u16 lss = ppd->link_speed_supported, lse = ppd->link_speed_enabled;
614 u8 *cache = ppd->qsfp_info.cache;
615
616 ppd->qsfp_info.limiting_active = 1;
617
618 ret = set_qsfp_tx(ppd, 0);
619 if (ret)
620 return ret;
621
622 ret = qual_power(ppd);
623 if (ret)
624 return ret;
625
626 ret = qual_bitrate(ppd);
627 if (ret)
628 return ret;
629
630 if (ppd->qsfp_info.reset_needed) {
631 reset_qsfp(ppd);
632 ppd->qsfp_info.reset_needed = 0;
633 refresh_qsfp_cache(ppd, &ppd->qsfp_info);
634 } else {
635 ppd->qsfp_info.reset_needed = 1;
636 }
637
638 ret = set_qsfp_high_power(ppd);
639 if (ret)
640 return ret;
641
642 if (cache[QSFP_EQ_INFO_OFFS] & 0x4) {
643 ret = get_platform_config_field(
644 ppd->dd,
645 PLATFORM_CONFIG_PORT_TABLE, 0,
646 PORT_TABLE_TX_PRESET_IDX_ACTIVE_EQ,
647 ptr_tx_preset, 4);
648 if (ret) {
649 *ptr_tx_preset = OPA_INVALID_INDEX;
650 return ret;
651 }
652 } else {
653 ret = get_platform_config_field(
654 ppd->dd,
655 PLATFORM_CONFIG_PORT_TABLE, 0,
656 PORT_TABLE_TX_PRESET_IDX_ACTIVE_NO_EQ,
657 ptr_tx_preset, 4);
658 if (ret) {
659 *ptr_tx_preset = OPA_INVALID_INDEX;
660 return ret;
661 }
662 }
663
664 ret = get_platform_config_field(
665 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
666 PORT_TABLE_RX_PRESET_IDX, ptr_rx_preset, 4);
667 if (ret) {
668 *ptr_rx_preset = OPA_INVALID_INDEX;
669 return ret;
670 }
671
672 if ((lss & OPA_LINK_SPEED_25G) && (lse & OPA_LINK_SPEED_25G))
673 get_platform_config_field(
674 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
675 PORT_TABLE_LOCAL_ATTEN_25G, ptr_total_atten, 4);
676 else if ((lss & OPA_LINK_SPEED_12_5G) && (lse & OPA_LINK_SPEED_12_5G))
677 get_platform_config_field(
678 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
679 PORT_TABLE_LOCAL_ATTEN_12G, ptr_total_atten, 4);
680
681 apply_cdr_settings(ppd, *ptr_rx_preset, *ptr_tx_preset);
682
683 apply_eq_settings(ppd, *ptr_rx_preset, *ptr_tx_preset);
684
685 apply_rx_amplitude_settings(ppd, *ptr_rx_preset, *ptr_tx_preset);
686
687 ret = set_qsfp_tx(ppd, 1);
688 return ret;
689}
690
691static int tune_qsfp(struct hfi1_pportdata *ppd,
692 u32 *ptr_tx_preset, u32 *ptr_rx_preset,
693 u8 *ptr_tuning_method, u32 *ptr_total_atten)
694{
695 u32 cable_atten = 0, remote_atten = 0, platform_atten = 0;
696 u16 lss = ppd->link_speed_supported, lse = ppd->link_speed_enabled;
697 int ret = 0;
698 u8 *cache = ppd->qsfp_info.cache;
699
700 switch ((cache[QSFP_MOD_TECH_OFFS] & 0xF0) >> 4) {
701 case 0xA ... 0xB:
702 ret = get_platform_config_field(
703 ppd->dd,
704 PLATFORM_CONFIG_PORT_TABLE, 0,
705 PORT_TABLE_LOCAL_ATTEN_25G,
706 &platform_atten, 4);
707 if (ret)
708 return ret;
709
710 if ((lss & OPA_LINK_SPEED_25G) && (lse & OPA_LINK_SPEED_25G))
711 cable_atten = cache[QSFP_CU_ATTEN_12G_OFFS];
712 else if ((lss & OPA_LINK_SPEED_12_5G) &&
713 (lse & OPA_LINK_SPEED_12_5G))
714 cable_atten = cache[QSFP_CU_ATTEN_7G_OFFS];
715
716 /* Fallback to configured attenuation if cable memory is bad */
717 if (cable_atten == 0 || cable_atten > 36) {
718 ret = get_platform_config_field(
719 ppd->dd,
720 PLATFORM_CONFIG_SYSTEM_TABLE, 0,
721 SYSTEM_TABLE_QSFP_ATTENUATION_DEFAULT_25G,
722 &cable_atten, 4);
723 if (ret)
724 return ret;
725 }
726
727 ret = get_platform_config_field(
728 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
729 PORT_TABLE_REMOTE_ATTEN_25G, &remote_atten, 4);
730 if (ret)
731 return ret;
732
733 *ptr_total_atten = platform_atten + cable_atten + remote_atten;
734
735 *ptr_tuning_method = OPA_PASSIVE_TUNING;
736 break;
737 case 0x0 ... 0x9: /* fallthrough */
738 case 0xC: /* fallthrough */
739 case 0xE:
740 ret = tune_active_qsfp(ppd, ptr_tx_preset, ptr_rx_preset,
741 ptr_total_atten);
742 if (ret)
743 return ret;
744
745 *ptr_tuning_method = OPA_ACTIVE_TUNING;
746 break;
747 case 0xD: /* fallthrough */
748 case 0xF:
749 default:
750 dd_dev_info(ppd->dd, "%s: Unknown/unsupported cable\n",
751 __func__);
752 break;
753 }
754 return ret;
755}
756
757/*
758 * This function communicates its success or failure via ppd->driver_link_ready
759 * Thus, it depends on its association with start_link(...) which checks
760 * driver_link_ready before proceeding with the link negotiation and
761 * initialization process.
762 */
763void tune_serdes(struct hfi1_pportdata *ppd)
764{
765 int ret = 0;
766 u32 total_atten = 0;
767 u32 remote_atten = 0, platform_atten = 0;
768 u32 rx_preset_index, tx_preset_index;
769 u8 tuning_method = 0;
770 struct hfi1_devdata *dd = ppd->dd;
771
772 rx_preset_index = OPA_INVALID_INDEX;
773 tx_preset_index = OPA_INVALID_INDEX;
774
775 /* the link defaults to enabled */
776 ppd->link_enabled = 1;
777 /* the driver link ready state defaults to not ready */
778 ppd->driver_link_ready = 0;
779 ppd->offline_disabled_reason = HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE);
780
715c430c
EH
781 /* Skip the tuning for testing (loopback != none) and simulations */
782 if (loopback != LOOPBACK_NONE ||
c3838b39 783 ppd->dd->icode == ICODE_FUNCTIONAL_SIMULATOR) {
8ebd4cf1
EH
784 ppd->driver_link_ready = 1;
785 return;
786 }
787
788 ret = get_platform_config_field(ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
789 PORT_TABLE_PORT_TYPE, &ppd->port_type,
790 4);
791 if (ret)
792 goto bail;
793
794 switch (ppd->port_type) {
795 case PORT_TYPE_DISCONNECTED:
796 ppd->offline_disabled_reason =
797 HFI1_ODR_MASK(OPA_LINKDOWN_REASON_DISCONNECTED);
798 dd_dev_info(dd, "%s: Port disconnected, disabling port\n",
799 __func__);
800 goto bail;
801 case PORT_TYPE_FIXED:
802 /* platform_atten, remote_atten pre-zeroed to catch error */
803 get_platform_config_field(
804 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
805 PORT_TABLE_LOCAL_ATTEN_25G, &platform_atten, 4);
806
807 get_platform_config_field(
808 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
809 PORT_TABLE_REMOTE_ATTEN_25G, &remote_atten, 4);
810
811 total_atten = platform_atten + remote_atten;
812
813 tuning_method = OPA_PASSIVE_TUNING;
814 break;
815 case PORT_TYPE_VARIABLE:
816 if (qsfp_mod_present(ppd)) {
817 /*
818 * platform_atten, remote_atten pre-zeroed to
819 * catch error
820 */
821 get_platform_config_field(
822 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
823 PORT_TABLE_LOCAL_ATTEN_25G,
824 &platform_atten, 4);
825
826 get_platform_config_field(
827 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
828 PORT_TABLE_REMOTE_ATTEN_25G,
829 &remote_atten, 4);
830
831 total_atten = platform_atten + remote_atten;
832
833 tuning_method = OPA_PASSIVE_TUNING;
834 } else
835 ppd->offline_disabled_reason =
836 HFI1_ODR_MASK(OPA_LINKDOWN_REASON_CHASSIS_CONFIG);
837 break;
838 case PORT_TYPE_QSFP:
839 if (qsfp_mod_present(ppd)) {
840 refresh_qsfp_cache(ppd, &ppd->qsfp_info);
841
842 if (ppd->qsfp_info.cache_valid) {
843 ret = tune_qsfp(ppd,
844 &tx_preset_index,
845 &rx_preset_index,
846 &tuning_method,
847 &total_atten);
c3838b39
EH
848
849 /*
850 * We may have modified the QSFP memory, so
851 * update the cache to reflect the changes
852 */
853 refresh_qsfp_cache(ppd, &ppd->qsfp_info);
8ebd4cf1
EH
854 if (ret)
855 goto bail;
856 } else {
857 dd_dev_err(dd,
858 "%s: Reading QSFP memory failed\n",
859 __func__);
860 goto bail;
861 }
862 } else
863 ppd->offline_disabled_reason =
864 HFI1_ODR_MASK(
e1bf0d5e 865 OPA_LINKDOWN_REASON_LOCAL_MEDIA_NOT_INSTALLED);
8ebd4cf1
EH
866 break;
867 default:
868 dd_dev_info(ppd->dd, "%s: Unknown port type\n", __func__);
c3838b39 869 goto bail;
8ebd4cf1
EH
870 }
871 if (ppd->offline_disabled_reason ==
872 HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE))
873 apply_tunings(ppd, tx_preset_index, tuning_method,
874 total_atten,
875 ppd->qsfp_info.limiting_active);
876
c3838b39
EH
877 if (!ret)
878 ppd->driver_link_ready = 1;
8ebd4cf1
EH
879
880 return;
881bail:
882 ppd->driver_link_ready = 0;
883}