Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
0002 /*
0003  * Copyright(c) 2015, 2016 Intel Corporation.
0004  */
0005 
0006 #include <linux/firmware.h>
0007 
0008 #include "hfi.h"
0009 #include "efivar.h"
0010 #include "eprom.h"
0011 
0012 #define DEFAULT_PLATFORM_CONFIG_NAME "hfi1_platform.dat"
0013 
0014 static int validate_scratch_checksum(struct hfi1_devdata *dd)
0015 {
0016     u64 checksum = 0, temp_scratch = 0;
0017     int i, j, version;
0018 
0019     temp_scratch = read_csr(dd, ASIC_CFG_SCRATCH);
0020     version = (temp_scratch & BITMAP_VERSION_SMASK) >> BITMAP_VERSION_SHIFT;
0021 
0022     /* Prevent power on default of all zeroes from passing checksum */
0023     if (!version) {
0024         dd_dev_err(dd, "%s: Config bitmap uninitialized\n", __func__);
0025         dd_dev_err(dd,
0026                "%s: Please update your BIOS to support active channels\n",
0027                __func__);
0028         return 0;
0029     }
0030 
0031     /*
0032      * ASIC scratch 0 only contains the checksum and bitmap version as
0033      * fields of interest, both of which are handled separately from the
0034      * loop below, so skip it
0035      */
0036     checksum += version;
0037     for (i = 1; i < ASIC_NUM_SCRATCH; i++) {
0038         temp_scratch = read_csr(dd, ASIC_CFG_SCRATCH + (8 * i));
0039         for (j = sizeof(u64); j != 0; j -= 2) {
0040             checksum += (temp_scratch & 0xFFFF);
0041             temp_scratch >>= 16;
0042         }
0043     }
0044 
0045     while (checksum >> 16)
0046         checksum = (checksum & CHECKSUM_MASK) + (checksum >> 16);
0047 
0048     temp_scratch = read_csr(dd, ASIC_CFG_SCRATCH);
0049     temp_scratch &= CHECKSUM_SMASK;
0050     temp_scratch >>= CHECKSUM_SHIFT;
0051 
0052     if (checksum + temp_scratch == 0xFFFF)
0053         return 1;
0054 
0055     dd_dev_err(dd, "%s: Configuration bitmap corrupted\n", __func__);
0056     return 0;
0057 }
0058 
0059 static void save_platform_config_fields(struct hfi1_devdata *dd)
0060 {
0061     struct hfi1_pportdata *ppd = dd->pport;
0062     u64 temp_scratch = 0, temp_dest = 0;
0063 
0064     temp_scratch = read_csr(dd, ASIC_CFG_SCRATCH_1);
0065 
0066     temp_dest = temp_scratch &
0067             (dd->hfi1_id ? PORT1_PORT_TYPE_SMASK :
0068              PORT0_PORT_TYPE_SMASK);
0069     ppd->port_type = temp_dest >>
0070              (dd->hfi1_id ? PORT1_PORT_TYPE_SHIFT :
0071               PORT0_PORT_TYPE_SHIFT);
0072 
0073     temp_dest = temp_scratch &
0074             (dd->hfi1_id ? PORT1_LOCAL_ATTEN_SMASK :
0075              PORT0_LOCAL_ATTEN_SMASK);
0076     ppd->local_atten = temp_dest >>
0077                (dd->hfi1_id ? PORT1_LOCAL_ATTEN_SHIFT :
0078                 PORT0_LOCAL_ATTEN_SHIFT);
0079 
0080     temp_dest = temp_scratch &
0081             (dd->hfi1_id ? PORT1_REMOTE_ATTEN_SMASK :
0082              PORT0_REMOTE_ATTEN_SMASK);
0083     ppd->remote_atten = temp_dest >>
0084                 (dd->hfi1_id ? PORT1_REMOTE_ATTEN_SHIFT :
0085                  PORT0_REMOTE_ATTEN_SHIFT);
0086 
0087     temp_dest = temp_scratch &
0088             (dd->hfi1_id ? PORT1_DEFAULT_ATTEN_SMASK :
0089              PORT0_DEFAULT_ATTEN_SMASK);
0090     ppd->default_atten = temp_dest >>
0091                  (dd->hfi1_id ? PORT1_DEFAULT_ATTEN_SHIFT :
0092                   PORT0_DEFAULT_ATTEN_SHIFT);
0093 
0094     temp_scratch = read_csr(dd, dd->hfi1_id ? ASIC_CFG_SCRATCH_3 :
0095                 ASIC_CFG_SCRATCH_2);
0096 
0097     ppd->tx_preset_eq = (temp_scratch & TX_EQ_SMASK) >> TX_EQ_SHIFT;
0098     ppd->tx_preset_noeq = (temp_scratch & TX_NO_EQ_SMASK) >> TX_NO_EQ_SHIFT;
0099     ppd->rx_preset = (temp_scratch & RX_SMASK) >> RX_SHIFT;
0100 
0101     ppd->max_power_class = (temp_scratch & QSFP_MAX_POWER_SMASK) >>
0102                 QSFP_MAX_POWER_SHIFT;
0103 
0104     ppd->config_from_scratch = true;
0105 }
0106 
0107 void get_platform_config(struct hfi1_devdata *dd)
0108 {
0109     int ret = 0;
0110     u8 *temp_platform_config = NULL;
0111     u32 esize;
0112     const struct firmware *platform_config_file = NULL;
0113 
0114     if (is_integrated(dd)) {
0115         if (validate_scratch_checksum(dd)) {
0116             save_platform_config_fields(dd);
0117             return;
0118         }
0119     } else {
0120         ret = eprom_read_platform_config(dd,
0121                          (void **)&temp_platform_config,
0122                          &esize);
0123         if (!ret) {
0124             /* success */
0125             dd->platform_config.data = temp_platform_config;
0126             dd->platform_config.size = esize;
0127             return;
0128         }
0129     }
0130     dd_dev_err(dd,
0131            "%s: Failed to get platform config, falling back to sub-optimal default file\n",
0132            __func__);
0133 
0134     ret = request_firmware(&platform_config_file,
0135                    DEFAULT_PLATFORM_CONFIG_NAME,
0136                    &dd->pcidev->dev);
0137     if (ret) {
0138         dd_dev_err(dd,
0139                "%s: No default platform config file found\n",
0140                __func__);
0141         return;
0142     }
0143 
0144     /*
0145      * Allocate separate memory block to store data and free firmware
0146      * structure. This allows free_platform_config to treat EPROM and
0147      * fallback configs in the same manner.
0148      */
0149     dd->platform_config.data = kmemdup(platform_config_file->data,
0150                        platform_config_file->size,
0151                        GFP_KERNEL);
0152     dd->platform_config.size = platform_config_file->size;
0153     release_firmware(platform_config_file);
0154 }
0155 
0156 void free_platform_config(struct hfi1_devdata *dd)
0157 {
0158     /* Release memory allocated for eprom or fallback file read. */
0159     kfree(dd->platform_config.data);
0160     dd->platform_config.data = NULL;
0161 }
0162 
0163 void get_port_type(struct hfi1_pportdata *ppd)
0164 {
0165     int ret;
0166     u32 temp;
0167 
0168     ret = get_platform_config_field(ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
0169                     PORT_TABLE_PORT_TYPE, &temp,
0170                     4);
0171     if (ret) {
0172         ppd->port_type = PORT_TYPE_UNKNOWN;
0173         return;
0174     }
0175     ppd->port_type = temp;
0176 }
0177 
0178 int set_qsfp_tx(struct hfi1_pportdata *ppd, int on)
0179 {
0180     u8 tx_ctrl_byte = on ? 0x0 : 0xF;
0181     int ret = 0;
0182 
0183     ret = qsfp_write(ppd, ppd->dd->hfi1_id, QSFP_TX_CTRL_BYTE_OFFS,
0184              &tx_ctrl_byte, 1);
0185     /* we expected 1, so consider 0 an error */
0186     if (ret == 0)
0187         ret = -EIO;
0188     else if (ret == 1)
0189         ret = 0;
0190     return ret;
0191 }
0192 
0193 static int qual_power(struct hfi1_pportdata *ppd)
0194 {
0195     u32 cable_power_class = 0, power_class_max = 0;
0196     u8 *cache = ppd->qsfp_info.cache;
0197     int ret = 0;
0198 
0199     ret = get_platform_config_field(
0200         ppd->dd, PLATFORM_CONFIG_SYSTEM_TABLE, 0,
0201         SYSTEM_TABLE_QSFP_POWER_CLASS_MAX, &power_class_max, 4);
0202     if (ret)
0203         return ret;
0204 
0205     cable_power_class = get_qsfp_power_class(cache[QSFP_MOD_PWR_OFFS]);
0206 
0207     if (cable_power_class > power_class_max)
0208         ppd->offline_disabled_reason =
0209             HFI1_ODR_MASK(OPA_LINKDOWN_REASON_POWER_POLICY);
0210 
0211     if (ppd->offline_disabled_reason ==
0212             HFI1_ODR_MASK(OPA_LINKDOWN_REASON_POWER_POLICY)) {
0213         dd_dev_err(
0214             ppd->dd,
0215             "%s: Port disabled due to system power restrictions\n",
0216             __func__);
0217         ret = -EPERM;
0218     }
0219     return ret;
0220 }
0221 
0222 static int qual_bitrate(struct hfi1_pportdata *ppd)
0223 {
0224     u16 lss = ppd->link_speed_supported, lse = ppd->link_speed_enabled;
0225     u8 *cache = ppd->qsfp_info.cache;
0226 
0227     if ((lss & OPA_LINK_SPEED_25G) && (lse & OPA_LINK_SPEED_25G) &&
0228         cache[QSFP_NOM_BIT_RATE_250_OFFS] < 0x64)
0229         ppd->offline_disabled_reason =
0230                HFI1_ODR_MASK(OPA_LINKDOWN_REASON_LINKSPEED_POLICY);
0231 
0232     if ((lss & OPA_LINK_SPEED_12_5G) && (lse & OPA_LINK_SPEED_12_5G) &&
0233         cache[QSFP_NOM_BIT_RATE_100_OFFS] < 0x7D)
0234         ppd->offline_disabled_reason =
0235                HFI1_ODR_MASK(OPA_LINKDOWN_REASON_LINKSPEED_POLICY);
0236 
0237     if (ppd->offline_disabled_reason ==
0238             HFI1_ODR_MASK(OPA_LINKDOWN_REASON_LINKSPEED_POLICY)) {
0239         dd_dev_err(
0240             ppd->dd,
0241             "%s: Cable failed bitrate check, disabling port\n",
0242             __func__);
0243         return -EPERM;
0244     }
0245     return 0;
0246 }
0247 
0248 static int set_qsfp_high_power(struct hfi1_pportdata *ppd)
0249 {
0250     u8 cable_power_class = 0, power_ctrl_byte = 0;
0251     u8 *cache = ppd->qsfp_info.cache;
0252     int ret;
0253 
0254     cable_power_class = get_qsfp_power_class(cache[QSFP_MOD_PWR_OFFS]);
0255 
0256     if (cable_power_class > QSFP_POWER_CLASS_1) {
0257         power_ctrl_byte = cache[QSFP_PWR_CTRL_BYTE_OFFS];
0258 
0259         power_ctrl_byte |= 1;
0260         power_ctrl_byte &= ~(0x2);
0261 
0262         ret = qsfp_write(ppd, ppd->dd->hfi1_id,
0263                  QSFP_PWR_CTRL_BYTE_OFFS,
0264                  &power_ctrl_byte, 1);
0265         if (ret != 1)
0266             return -EIO;
0267 
0268         if (cable_power_class > QSFP_POWER_CLASS_4) {
0269             power_ctrl_byte |= (1 << 2);
0270             ret = qsfp_write(ppd, ppd->dd->hfi1_id,
0271                      QSFP_PWR_CTRL_BYTE_OFFS,
0272                      &power_ctrl_byte, 1);
0273             if (ret != 1)
0274                 return -EIO;
0275         }
0276 
0277         /* SFF 8679 rev 1.7 LPMode Deassert time */
0278         msleep(300);
0279     }
0280     return 0;
0281 }
0282 
0283 static void apply_rx_cdr(struct hfi1_pportdata *ppd,
0284              u32 rx_preset_index,
0285              u8 *cdr_ctrl_byte)
0286 {
0287     u32 rx_preset;
0288     u8 *cache = ppd->qsfp_info.cache;
0289     int cable_power_class;
0290 
0291     if (!((cache[QSFP_MOD_PWR_OFFS] & 0x4) &&
0292           (cache[QSFP_CDR_INFO_OFFS] & 0x40)))
0293         return;
0294 
0295     /* RX CDR present, bypass supported */
0296     cable_power_class = get_qsfp_power_class(cache[QSFP_MOD_PWR_OFFS]);
0297 
0298     if (cable_power_class <= QSFP_POWER_CLASS_3) {
0299         /* Power class <= 3, ignore config & turn RX CDR on */
0300         *cdr_ctrl_byte |= 0xF;
0301         return;
0302     }
0303 
0304     get_platform_config_field(
0305         ppd->dd, PLATFORM_CONFIG_RX_PRESET_TABLE,
0306         rx_preset_index, RX_PRESET_TABLE_QSFP_RX_CDR_APPLY,
0307         &rx_preset, 4);
0308 
0309     if (!rx_preset) {
0310         dd_dev_info(
0311             ppd->dd,
0312             "%s: RX_CDR_APPLY is set to disabled\n",
0313             __func__);
0314         return;
0315     }
0316     get_platform_config_field(
0317         ppd->dd, PLATFORM_CONFIG_RX_PRESET_TABLE,
0318         rx_preset_index, RX_PRESET_TABLE_QSFP_RX_CDR,
0319         &rx_preset, 4);
0320 
0321     /* Expand cdr setting to all 4 lanes */
0322     rx_preset = (rx_preset | (rx_preset << 1) |
0323             (rx_preset << 2) | (rx_preset << 3));
0324 
0325     if (rx_preset) {
0326         *cdr_ctrl_byte |= rx_preset;
0327     } else {
0328         *cdr_ctrl_byte &= rx_preset;
0329         /* Preserve current TX CDR status */
0330         *cdr_ctrl_byte |= (cache[QSFP_CDR_CTRL_BYTE_OFFS] & 0xF0);
0331     }
0332 }
0333 
0334 static void apply_tx_cdr(struct hfi1_pportdata *ppd,
0335              u32 tx_preset_index,
0336              u8 *cdr_ctrl_byte)
0337 {
0338     u32 tx_preset;
0339     u8 *cache = ppd->qsfp_info.cache;
0340     int cable_power_class;
0341 
0342     if (!((cache[QSFP_MOD_PWR_OFFS] & 0x8) &&
0343           (cache[QSFP_CDR_INFO_OFFS] & 0x80)))
0344         return;
0345 
0346     /* TX CDR present, bypass supported */
0347     cable_power_class = get_qsfp_power_class(cache[QSFP_MOD_PWR_OFFS]);
0348 
0349     if (cable_power_class <= QSFP_POWER_CLASS_3) {
0350         /* Power class <= 3, ignore config & turn TX CDR on */
0351         *cdr_ctrl_byte |= 0xF0;
0352         return;
0353     }
0354 
0355     get_platform_config_field(
0356         ppd->dd,
0357         PLATFORM_CONFIG_TX_PRESET_TABLE, tx_preset_index,
0358         TX_PRESET_TABLE_QSFP_TX_CDR_APPLY, &tx_preset, 4);
0359 
0360     if (!tx_preset) {
0361         dd_dev_info(
0362             ppd->dd,
0363             "%s: TX_CDR_APPLY is set to disabled\n",
0364             __func__);
0365         return;
0366     }
0367     get_platform_config_field(
0368         ppd->dd,
0369         PLATFORM_CONFIG_TX_PRESET_TABLE,
0370         tx_preset_index,
0371         TX_PRESET_TABLE_QSFP_TX_CDR, &tx_preset, 4);
0372 
0373     /* Expand cdr setting to all 4 lanes */
0374     tx_preset = (tx_preset | (tx_preset << 1) |
0375             (tx_preset << 2) | (tx_preset << 3));
0376 
0377     if (tx_preset)
0378         *cdr_ctrl_byte |= (tx_preset << 4);
0379     else
0380         /* Preserve current/determined RX CDR status */
0381         *cdr_ctrl_byte &= ((tx_preset << 4) | 0xF);
0382 }
0383 
0384 static void apply_cdr_settings(
0385         struct hfi1_pportdata *ppd, u32 rx_preset_index,
0386         u32 tx_preset_index)
0387 {
0388     u8 *cache = ppd->qsfp_info.cache;
0389     u8 cdr_ctrl_byte = cache[QSFP_CDR_CTRL_BYTE_OFFS];
0390 
0391     apply_rx_cdr(ppd, rx_preset_index, &cdr_ctrl_byte);
0392 
0393     apply_tx_cdr(ppd, tx_preset_index, &cdr_ctrl_byte);
0394 
0395     qsfp_write(ppd, ppd->dd->hfi1_id, QSFP_CDR_CTRL_BYTE_OFFS,
0396            &cdr_ctrl_byte, 1);
0397 }
0398 
0399 static void apply_tx_eq_auto(struct hfi1_pportdata *ppd)
0400 {
0401     u8 *cache = ppd->qsfp_info.cache;
0402     u8 tx_eq;
0403 
0404     if (!(cache[QSFP_EQ_INFO_OFFS] & 0x8))
0405         return;
0406     /* Disable adaptive TX EQ if present */
0407     tx_eq = cache[(128 * 3) + 241];
0408     tx_eq &= 0xF0;
0409     qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 241, &tx_eq, 1);
0410 }
0411 
0412 static void apply_tx_eq_prog(struct hfi1_pportdata *ppd, u32 tx_preset_index)
0413 {
0414     u8 *cache = ppd->qsfp_info.cache;
0415     u32 tx_preset;
0416     u8 tx_eq;
0417 
0418     if (!(cache[QSFP_EQ_INFO_OFFS] & 0x4))
0419         return;
0420 
0421     get_platform_config_field(
0422         ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE,
0423         tx_preset_index, TX_PRESET_TABLE_QSFP_TX_EQ_APPLY,
0424         &tx_preset, 4);
0425     if (!tx_preset) {
0426         dd_dev_info(
0427             ppd->dd,
0428             "%s: TX_EQ_APPLY is set to disabled\n",
0429             __func__);
0430         return;
0431     }
0432     get_platform_config_field(
0433             ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE,
0434             tx_preset_index, TX_PRESET_TABLE_QSFP_TX_EQ,
0435             &tx_preset, 4);
0436 
0437     if (((cache[(128 * 3) + 224] & 0xF0) >> 4) < tx_preset) {
0438         dd_dev_info(
0439             ppd->dd,
0440             "%s: TX EQ %x unsupported\n",
0441             __func__, tx_preset);
0442 
0443         dd_dev_info(
0444             ppd->dd,
0445             "%s: Applying EQ %x\n",
0446             __func__, cache[608] & 0xF0);
0447 
0448         tx_preset = (cache[608] & 0xF0) >> 4;
0449     }
0450 
0451     tx_eq = tx_preset | (tx_preset << 4);
0452     qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 234, &tx_eq, 1);
0453     qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 235, &tx_eq, 1);
0454 }
0455 
0456 static void apply_rx_eq_emp(struct hfi1_pportdata *ppd, u32 rx_preset_index)
0457 {
0458     u32 rx_preset;
0459     u8 rx_eq, *cache = ppd->qsfp_info.cache;
0460 
0461     if (!(cache[QSFP_EQ_INFO_OFFS] & 0x2))
0462         return;
0463     get_platform_config_field(
0464             ppd->dd, PLATFORM_CONFIG_RX_PRESET_TABLE,
0465             rx_preset_index, RX_PRESET_TABLE_QSFP_RX_EMP_APPLY,
0466             &rx_preset, 4);
0467 
0468     if (!rx_preset) {
0469         dd_dev_info(
0470             ppd->dd,
0471             "%s: RX_EMP_APPLY is set to disabled\n",
0472             __func__);
0473         return;
0474     }
0475     get_platform_config_field(
0476         ppd->dd, PLATFORM_CONFIG_RX_PRESET_TABLE,
0477         rx_preset_index, RX_PRESET_TABLE_QSFP_RX_EMP,
0478         &rx_preset, 4);
0479 
0480     if ((cache[(128 * 3) + 224] & 0xF) < rx_preset) {
0481         dd_dev_info(
0482             ppd->dd,
0483             "%s: Requested RX EMP %x\n",
0484             __func__, rx_preset);
0485 
0486         dd_dev_info(
0487             ppd->dd,
0488             "%s: Applying supported EMP %x\n",
0489             __func__, cache[608] & 0xF);
0490 
0491         rx_preset = cache[608] & 0xF;
0492     }
0493 
0494     rx_eq = rx_preset | (rx_preset << 4);
0495 
0496     qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 236, &rx_eq, 1);
0497     qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 237, &rx_eq, 1);
0498 }
0499 
0500 static void apply_eq_settings(struct hfi1_pportdata *ppd,
0501                   u32 rx_preset_index, u32 tx_preset_index)
0502 {
0503     u8 *cache = ppd->qsfp_info.cache;
0504 
0505     /* no point going on w/o a page 3 */
0506     if (cache[2] & 4) {
0507         dd_dev_info(ppd->dd,
0508                 "%s: Upper page 03 not present\n",
0509                 __func__);
0510         return;
0511     }
0512 
0513     apply_tx_eq_auto(ppd);
0514 
0515     apply_tx_eq_prog(ppd, tx_preset_index);
0516 
0517     apply_rx_eq_emp(ppd, rx_preset_index);
0518 }
0519 
0520 static void apply_rx_amplitude_settings(
0521         struct hfi1_pportdata *ppd, u32 rx_preset_index,
0522         u32 tx_preset_index)
0523 {
0524     u32 rx_preset;
0525     u8 rx_amp = 0, i = 0, preferred = 0, *cache = ppd->qsfp_info.cache;
0526 
0527     /* no point going on w/o a page 3 */
0528     if (cache[2] & 4) {
0529         dd_dev_info(ppd->dd,
0530                 "%s: Upper page 03 not present\n",
0531                 __func__);
0532         return;
0533     }
0534     if (!(cache[QSFP_EQ_INFO_OFFS] & 0x1)) {
0535         dd_dev_info(ppd->dd,
0536                 "%s: RX_AMP_APPLY is set to disabled\n",
0537                 __func__);
0538         return;
0539     }
0540 
0541     get_platform_config_field(ppd->dd,
0542                   PLATFORM_CONFIG_RX_PRESET_TABLE,
0543                   rx_preset_index,
0544                   RX_PRESET_TABLE_QSFP_RX_AMP_APPLY,
0545                   &rx_preset, 4);
0546 
0547     if (!rx_preset) {
0548         dd_dev_info(ppd->dd,
0549                 "%s: RX_AMP_APPLY is set to disabled\n",
0550                 __func__);
0551         return;
0552     }
0553     get_platform_config_field(ppd->dd,
0554                   PLATFORM_CONFIG_RX_PRESET_TABLE,
0555                   rx_preset_index,
0556                   RX_PRESET_TABLE_QSFP_RX_AMP,
0557                   &rx_preset, 4);
0558 
0559     dd_dev_info(ppd->dd,
0560             "%s: Requested RX AMP %x\n",
0561             __func__,
0562             rx_preset);
0563 
0564     for (i = 0; i < 4; i++) {
0565         if (cache[(128 * 3) + 225] & (1 << i)) {
0566             preferred = i;
0567             if (preferred == rx_preset)
0568                 break;
0569         }
0570     }
0571 
0572     /*
0573      * Verify that preferred RX amplitude is not just a
0574      * fall through of the default
0575      */
0576     if (!preferred && !(cache[(128 * 3) + 225] & 0x1)) {
0577         dd_dev_info(ppd->dd, "No supported RX AMP, not applying\n");
0578         return;
0579     }
0580 
0581     dd_dev_info(ppd->dd,
0582             "%s: Applying RX AMP %x\n", __func__, preferred);
0583 
0584     rx_amp = preferred | (preferred << 4);
0585     qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 238, &rx_amp, 1);
0586     qsfp_write(ppd, ppd->dd->hfi1_id, (256 * 3) + 239, &rx_amp, 1);
0587 }
0588 
0589 #define OPA_INVALID_INDEX 0xFFF
0590 
0591 static void apply_tx_lanes(struct hfi1_pportdata *ppd, u8 field_id,
0592                u32 config_data, const char *message)
0593 {
0594     u8 i;
0595     int ret;
0596 
0597     for (i = 0; i < 4; i++) {
0598         ret = load_8051_config(ppd->dd, field_id, i, config_data);
0599         if (ret != HCMD_SUCCESS) {
0600             dd_dev_err(
0601                 ppd->dd,
0602                 "%s: %s for lane %u failed\n",
0603                 message, __func__, i);
0604         }
0605     }
0606 }
0607 
0608 /*
0609  * Return a special SerDes setting for low power AOC cables.  The power class
0610  * threshold and setting being used were all found by empirical testing.
0611  *
0612  * Summary of the logic:
0613  *
0614  * if (QSFP and QSFP_TYPE == AOC and QSFP_POWER_CLASS < 4)
0615  *     return 0xe
0616  * return 0; // leave at default
0617  */
0618 static u8 aoc_low_power_setting(struct hfi1_pportdata *ppd)
0619 {
0620     u8 *cache = ppd->qsfp_info.cache;
0621     int power_class;
0622 
0623     /* QSFP only */
0624     if (ppd->port_type != PORT_TYPE_QSFP)
0625         return 0; /* leave at default */
0626 
0627     /* active optical cables only */
0628     switch ((cache[QSFP_MOD_TECH_OFFS] & 0xF0) >> 4) {
0629     case 0x0 ... 0x9: fallthrough;
0630     case 0xC: fallthrough;
0631     case 0xE:
0632         /* active AOC */
0633         power_class = get_qsfp_power_class(cache[QSFP_MOD_PWR_OFFS]);
0634         if (power_class < QSFP_POWER_CLASS_4)
0635             return 0xe;
0636     }
0637     return 0; /* leave at default */
0638 }
0639 
0640 static void apply_tunings(
0641         struct hfi1_pportdata *ppd, u32 tx_preset_index,
0642         u8 tuning_method, u32 total_atten, u8 limiting_active)
0643 {
0644     int ret = 0;
0645     u32 config_data = 0, tx_preset = 0;
0646     u8 precur = 0, attn = 0, postcur = 0, external_device_config = 0;
0647     u8 *cache = ppd->qsfp_info.cache;
0648 
0649     /* Pass tuning method to 8051 */
0650     read_8051_config(ppd->dd, LINK_TUNING_PARAMETERS, GENERAL_CONFIG,
0651              &config_data);
0652     config_data &= ~(0xff << TUNING_METHOD_SHIFT);
0653     config_data |= ((u32)tuning_method << TUNING_METHOD_SHIFT);
0654     ret = load_8051_config(ppd->dd, LINK_TUNING_PARAMETERS, GENERAL_CONFIG,
0655                    config_data);
0656     if (ret != HCMD_SUCCESS)
0657         dd_dev_err(ppd->dd, "%s: Failed to set tuning method\n",
0658                __func__);
0659 
0660     /* Set same channel loss for both TX and RX */
0661     config_data = 0 | (total_atten << 16) | (total_atten << 24);
0662     apply_tx_lanes(ppd, CHANNEL_LOSS_SETTINGS, config_data,
0663                "Setting channel loss");
0664 
0665     /* Inform 8051 of cable capabilities */
0666     if (ppd->qsfp_info.cache_valid) {
0667         external_device_config =
0668             ((cache[QSFP_MOD_PWR_OFFS] & 0x4) << 3) |
0669             ((cache[QSFP_MOD_PWR_OFFS] & 0x8) << 2) |
0670             ((cache[QSFP_EQ_INFO_OFFS] & 0x2) << 1) |
0671             (cache[QSFP_EQ_INFO_OFFS] & 0x4);
0672         ret = read_8051_config(ppd->dd, DC_HOST_COMM_SETTINGS,
0673                        GENERAL_CONFIG, &config_data);
0674         /* Clear, then set the external device config field */
0675         config_data &= ~(u32)0xFF;
0676         config_data |= external_device_config;
0677         ret = load_8051_config(ppd->dd, DC_HOST_COMM_SETTINGS,
0678                        GENERAL_CONFIG, config_data);
0679         if (ret != HCMD_SUCCESS)
0680             dd_dev_err(ppd->dd,
0681                    "%s: Failed set ext device config params\n",
0682                    __func__);
0683     }
0684 
0685     if (tx_preset_index == OPA_INVALID_INDEX) {
0686         if (ppd->port_type == PORT_TYPE_QSFP && limiting_active)
0687             dd_dev_err(ppd->dd, "%s: Invalid Tx preset index\n",
0688                    __func__);
0689         return;
0690     }
0691 
0692     /* Following for limiting active channels only */
0693     get_platform_config_field(
0694         ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE, tx_preset_index,
0695         TX_PRESET_TABLE_PRECUR, &tx_preset, 4);
0696     precur = tx_preset;
0697 
0698     get_platform_config_field(
0699         ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE,
0700         tx_preset_index, TX_PRESET_TABLE_ATTN, &tx_preset, 4);
0701     attn = tx_preset;
0702 
0703     get_platform_config_field(
0704         ppd->dd, PLATFORM_CONFIG_TX_PRESET_TABLE,
0705         tx_preset_index, TX_PRESET_TABLE_POSTCUR, &tx_preset, 4);
0706     postcur = tx_preset;
0707 
0708     /*
0709      * NOTES:
0710      * o The aoc_low_power_setting is applied to all lanes even
0711      *   though only lane 0's value is examined by the firmware.
0712      * o A lingering low power setting after a cable swap does
0713      *   not occur.  On cable unplug the 8051 is reset and
0714      *   restarted on cable insert.  This resets all settings to
0715      *   their default, erasing any previous low power setting.
0716      */
0717     config_data = precur | (attn << 8) | (postcur << 16) |
0718             (aoc_low_power_setting(ppd) << 24);
0719 
0720     apply_tx_lanes(ppd, TX_EQ_SETTINGS, config_data,
0721                "Applying TX settings");
0722 }
0723 
0724 /* Must be holding the QSFP i2c resource */
0725 static int tune_active_qsfp(struct hfi1_pportdata *ppd, u32 *ptr_tx_preset,
0726                 u32 *ptr_rx_preset, u32 *ptr_total_atten)
0727 {
0728     int ret;
0729     u16 lss = ppd->link_speed_supported, lse = ppd->link_speed_enabled;
0730     u8 *cache = ppd->qsfp_info.cache;
0731 
0732     ppd->qsfp_info.limiting_active = 1;
0733 
0734     ret = set_qsfp_tx(ppd, 0);
0735     if (ret)
0736         return ret;
0737 
0738     ret = qual_power(ppd);
0739     if (ret)
0740         return ret;
0741 
0742     ret = qual_bitrate(ppd);
0743     if (ret)
0744         return ret;
0745 
0746     /*
0747      * We'll change the QSFP memory contents from here on out, thus we set a
0748      * flag here to remind ourselves to reset the QSFP module. This prevents
0749      * reuse of stale settings established in our previous pass through.
0750      */
0751     if (ppd->qsfp_info.reset_needed) {
0752         ret = reset_qsfp(ppd);
0753         if (ret)
0754             return ret;
0755         refresh_qsfp_cache(ppd, &ppd->qsfp_info);
0756     } else {
0757         ppd->qsfp_info.reset_needed = 1;
0758     }
0759 
0760     ret = set_qsfp_high_power(ppd);
0761     if (ret)
0762         return ret;
0763 
0764     if (cache[QSFP_EQ_INFO_OFFS] & 0x4) {
0765         ret = get_platform_config_field(
0766             ppd->dd,
0767             PLATFORM_CONFIG_PORT_TABLE, 0,
0768             PORT_TABLE_TX_PRESET_IDX_ACTIVE_EQ,
0769             ptr_tx_preset, 4);
0770         if (ret) {
0771             *ptr_tx_preset = OPA_INVALID_INDEX;
0772             return ret;
0773         }
0774     } else {
0775         ret = get_platform_config_field(
0776             ppd->dd,
0777             PLATFORM_CONFIG_PORT_TABLE, 0,
0778             PORT_TABLE_TX_PRESET_IDX_ACTIVE_NO_EQ,
0779             ptr_tx_preset, 4);
0780         if (ret) {
0781             *ptr_tx_preset = OPA_INVALID_INDEX;
0782             return ret;
0783         }
0784     }
0785 
0786     ret = get_platform_config_field(
0787         ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
0788         PORT_TABLE_RX_PRESET_IDX, ptr_rx_preset, 4);
0789     if (ret) {
0790         *ptr_rx_preset = OPA_INVALID_INDEX;
0791         return ret;
0792     }
0793 
0794     if ((lss & OPA_LINK_SPEED_25G) && (lse & OPA_LINK_SPEED_25G))
0795         get_platform_config_field(
0796             ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
0797             PORT_TABLE_LOCAL_ATTEN_25G, ptr_total_atten, 4);
0798     else if ((lss & OPA_LINK_SPEED_12_5G) && (lse & OPA_LINK_SPEED_12_5G))
0799         get_platform_config_field(
0800             ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
0801             PORT_TABLE_LOCAL_ATTEN_12G, ptr_total_atten, 4);
0802 
0803     apply_cdr_settings(ppd, *ptr_rx_preset, *ptr_tx_preset);
0804 
0805     apply_eq_settings(ppd, *ptr_rx_preset, *ptr_tx_preset);
0806 
0807     apply_rx_amplitude_settings(ppd, *ptr_rx_preset, *ptr_tx_preset);
0808 
0809     ret = set_qsfp_tx(ppd, 1);
0810 
0811     return ret;
0812 }
0813 
0814 static int tune_qsfp(struct hfi1_pportdata *ppd,
0815              u32 *ptr_tx_preset, u32 *ptr_rx_preset,
0816              u8 *ptr_tuning_method, u32 *ptr_total_atten)
0817 {
0818     u32 cable_atten = 0, remote_atten = 0, platform_atten = 0;
0819     u16 lss = ppd->link_speed_supported, lse = ppd->link_speed_enabled;
0820     int ret = 0;
0821     u8 *cache = ppd->qsfp_info.cache;
0822 
0823     switch ((cache[QSFP_MOD_TECH_OFFS] & 0xF0) >> 4) {
0824     case 0xA ... 0xB:
0825         ret = get_platform_config_field(
0826             ppd->dd,
0827             PLATFORM_CONFIG_PORT_TABLE, 0,
0828             PORT_TABLE_LOCAL_ATTEN_25G,
0829             &platform_atten, 4);
0830         if (ret)
0831             return ret;
0832 
0833         if ((lss & OPA_LINK_SPEED_25G) && (lse & OPA_LINK_SPEED_25G))
0834             cable_atten = cache[QSFP_CU_ATTEN_12G_OFFS];
0835         else if ((lss & OPA_LINK_SPEED_12_5G) &&
0836              (lse & OPA_LINK_SPEED_12_5G))
0837             cable_atten = cache[QSFP_CU_ATTEN_7G_OFFS];
0838 
0839         /* Fallback to configured attenuation if cable memory is bad */
0840         if (cable_atten == 0 || cable_atten > 36) {
0841             ret = get_platform_config_field(
0842                 ppd->dd,
0843                 PLATFORM_CONFIG_SYSTEM_TABLE, 0,
0844                 SYSTEM_TABLE_QSFP_ATTENUATION_DEFAULT_25G,
0845                 &cable_atten, 4);
0846             if (ret)
0847                 return ret;
0848         }
0849 
0850         ret = get_platform_config_field(
0851             ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
0852             PORT_TABLE_REMOTE_ATTEN_25G, &remote_atten, 4);
0853         if (ret)
0854             return ret;
0855 
0856         *ptr_total_atten = platform_atten + cable_atten + remote_atten;
0857 
0858         *ptr_tuning_method = OPA_PASSIVE_TUNING;
0859         break;
0860     case 0x0 ... 0x9: fallthrough;
0861     case 0xC: fallthrough;
0862     case 0xE:
0863         ret = tune_active_qsfp(ppd, ptr_tx_preset, ptr_rx_preset,
0864                        ptr_total_atten);
0865         if (ret)
0866             return ret;
0867 
0868         *ptr_tuning_method = OPA_ACTIVE_TUNING;
0869         break;
0870     case 0xD: fallthrough;
0871     case 0xF:
0872     default:
0873         dd_dev_warn(ppd->dd, "%s: Unknown/unsupported cable\n",
0874                 __func__);
0875         break;
0876     }
0877     return ret;
0878 }
0879 
0880 /*
0881  * This function communicates its success or failure via ppd->driver_link_ready
0882  * Thus, it depends on its association with start_link(...) which checks
0883  * driver_link_ready before proceeding with the link negotiation and
0884  * initialization process.
0885  */
0886 void tune_serdes(struct hfi1_pportdata *ppd)
0887 {
0888     int ret = 0;
0889     u32 total_atten = 0;
0890     u32 remote_atten = 0, platform_atten = 0;
0891     u32 rx_preset_index, tx_preset_index;
0892     u8 tuning_method = 0, limiting_active = 0;
0893     struct hfi1_devdata *dd = ppd->dd;
0894 
0895     rx_preset_index = OPA_INVALID_INDEX;
0896     tx_preset_index = OPA_INVALID_INDEX;
0897 
0898     /* the link defaults to enabled */
0899     ppd->link_enabled = 1;
0900     /* the driver link ready state defaults to not ready */
0901     ppd->driver_link_ready = 0;
0902     ppd->offline_disabled_reason = HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE);
0903 
0904     /* Skip the tuning for testing (loopback != none) and simulations */
0905     if (loopback != LOOPBACK_NONE ||
0906         ppd->dd->icode == ICODE_FUNCTIONAL_SIMULATOR) {
0907         ppd->driver_link_ready = 1;
0908 
0909         if (qsfp_mod_present(ppd)) {
0910             ret = acquire_chip_resource(ppd->dd,
0911                             qsfp_resource(ppd->dd),
0912                             QSFP_WAIT);
0913             if (ret) {
0914                 dd_dev_err(ppd->dd, "%s: hfi%d: cannot lock i2c chain\n",
0915                        __func__, (int)ppd->dd->hfi1_id);
0916                 goto bail;
0917             }
0918 
0919             refresh_qsfp_cache(ppd, &ppd->qsfp_info);
0920             release_chip_resource(ppd->dd, qsfp_resource(ppd->dd));
0921         }
0922 
0923         return;
0924     }
0925 
0926     switch (ppd->port_type) {
0927     case PORT_TYPE_DISCONNECTED:
0928         ppd->offline_disabled_reason =
0929             HFI1_ODR_MASK(OPA_LINKDOWN_REASON_DISCONNECTED);
0930         dd_dev_warn(dd, "%s: Port disconnected, disabling port\n",
0931                 __func__);
0932         goto bail;
0933     case PORT_TYPE_FIXED:
0934         /* platform_atten, remote_atten pre-zeroed to catch error */
0935         get_platform_config_field(
0936             ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
0937             PORT_TABLE_LOCAL_ATTEN_25G, &platform_atten, 4);
0938 
0939         get_platform_config_field(
0940             ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
0941             PORT_TABLE_REMOTE_ATTEN_25G, &remote_atten, 4);
0942 
0943         total_atten = platform_atten + remote_atten;
0944 
0945         tuning_method = OPA_PASSIVE_TUNING;
0946         break;
0947     case PORT_TYPE_VARIABLE:
0948         if (qsfp_mod_present(ppd)) {
0949             /*
0950              * platform_atten, remote_atten pre-zeroed to
0951              * catch error
0952              */
0953             get_platform_config_field(
0954                 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
0955                 PORT_TABLE_LOCAL_ATTEN_25G,
0956                 &platform_atten, 4);
0957 
0958             get_platform_config_field(
0959                 ppd->dd, PLATFORM_CONFIG_PORT_TABLE, 0,
0960                 PORT_TABLE_REMOTE_ATTEN_25G,
0961                 &remote_atten, 4);
0962 
0963             total_atten = platform_atten + remote_atten;
0964 
0965             tuning_method = OPA_PASSIVE_TUNING;
0966         } else {
0967             ppd->offline_disabled_reason =
0968                  HFI1_ODR_MASK(OPA_LINKDOWN_REASON_CHASSIS_CONFIG);
0969             goto bail;
0970         }
0971         break;
0972     case PORT_TYPE_QSFP:
0973         if (qsfp_mod_present(ppd)) {
0974             ret = acquire_chip_resource(ppd->dd,
0975                             qsfp_resource(ppd->dd),
0976                             QSFP_WAIT);
0977             if (ret) {
0978                 dd_dev_err(ppd->dd, "%s: hfi%d: cannot lock i2c chain\n",
0979                        __func__, (int)ppd->dd->hfi1_id);
0980                 goto bail;
0981             }
0982             refresh_qsfp_cache(ppd, &ppd->qsfp_info);
0983 
0984             if (ppd->qsfp_info.cache_valid) {
0985                 ret = tune_qsfp(ppd,
0986                         &tx_preset_index,
0987                         &rx_preset_index,
0988                         &tuning_method,
0989                         &total_atten);
0990 
0991                 /*
0992                  * We may have modified the QSFP memory, so
0993                  * update the cache to reflect the changes
0994                  */
0995                 refresh_qsfp_cache(ppd, &ppd->qsfp_info);
0996                 limiting_active =
0997                         ppd->qsfp_info.limiting_active;
0998             } else {
0999                 dd_dev_err(dd,
1000                        "%s: Reading QSFP memory failed\n",
1001                        __func__);
1002                 ret = -EINVAL; /* a fail indication */
1003             }
1004             release_chip_resource(ppd->dd, qsfp_resource(ppd->dd));
1005             if (ret)
1006                 goto bail;
1007         } else {
1008             ppd->offline_disabled_reason =
1009                HFI1_ODR_MASK(
1010                 OPA_LINKDOWN_REASON_LOCAL_MEDIA_NOT_INSTALLED);
1011             goto bail;
1012         }
1013         break;
1014     default:
1015         dd_dev_warn(ppd->dd, "%s: Unknown port type\n", __func__);
1016         ppd->port_type = PORT_TYPE_UNKNOWN;
1017         tuning_method = OPA_UNKNOWN_TUNING;
1018         total_atten = 0;
1019         limiting_active = 0;
1020         tx_preset_index = OPA_INVALID_INDEX;
1021         break;
1022     }
1023 
1024     if (ppd->offline_disabled_reason ==
1025             HFI1_ODR_MASK(OPA_LINKDOWN_REASON_NONE))
1026         apply_tunings(ppd, tx_preset_index, tuning_method,
1027                   total_atten, limiting_active);
1028 
1029     if (!ret)
1030         ppd->driver_link_ready = 1;
1031 
1032     return;
1033 bail:
1034     ppd->driver_link_ready = 0;
1035 }