12c81bfd5SHuy Nguyen /* 22c81bfd5SHuy Nguyen * Copyright (c) 2018, Mellanox Technologies. All rights reserved. 32c81bfd5SHuy Nguyen * 42c81bfd5SHuy Nguyen * This software is available to you under a choice of one of two 52c81bfd5SHuy Nguyen * licenses. You may choose to be licensed under the terms of the GNU 62c81bfd5SHuy Nguyen * General Public License (GPL) Version 2, available from the file 72c81bfd5SHuy Nguyen * COPYING in the main directory of this source tree, or the 82c81bfd5SHuy Nguyen * OpenIB.org BSD license below: 92c81bfd5SHuy Nguyen * 102c81bfd5SHuy Nguyen * Redistribution and use in source and binary forms, with or 112c81bfd5SHuy Nguyen * without modification, are permitted provided that the following 122c81bfd5SHuy Nguyen * conditions are met: 132c81bfd5SHuy Nguyen * 142c81bfd5SHuy Nguyen * - Redistributions of source code must retain the above 152c81bfd5SHuy Nguyen * copyright notice, this list of conditions and the following 162c81bfd5SHuy Nguyen * disclaimer. 172c81bfd5SHuy Nguyen * 182c81bfd5SHuy Nguyen * - Redistributions in binary form must reproduce the above 192c81bfd5SHuy Nguyen * copyright notice, this list of conditions and the following 202c81bfd5SHuy Nguyen * disclaimer in the documentation and/or other materials 212c81bfd5SHuy Nguyen * provided with the distribution. 222c81bfd5SHuy Nguyen * 232c81bfd5SHuy Nguyen * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 242c81bfd5SHuy Nguyen * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 252c81bfd5SHuy Nguyen * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 262c81bfd5SHuy Nguyen * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 272c81bfd5SHuy Nguyen * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 282c81bfd5SHuy Nguyen * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 292c81bfd5SHuy Nguyen * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 302c81bfd5SHuy Nguyen * SOFTWARE. 312c81bfd5SHuy Nguyen */ 322c81bfd5SHuy Nguyen 332c81bfd5SHuy Nguyen #include "port.h" 342c81bfd5SHuy Nguyen 352c81bfd5SHuy Nguyen /* speed in units of 1Mb */ 362c81bfd5SHuy Nguyen static const u32 mlx5e_link_speed[MLX5E_LINK_MODES_NUMBER] = { 372c81bfd5SHuy Nguyen [MLX5E_1000BASE_CX_SGMII] = 1000, 382c81bfd5SHuy Nguyen [MLX5E_1000BASE_KX] = 1000, 392c81bfd5SHuy Nguyen [MLX5E_10GBASE_CX4] = 10000, 402c81bfd5SHuy Nguyen [MLX5E_10GBASE_KX4] = 10000, 412c81bfd5SHuy Nguyen [MLX5E_10GBASE_KR] = 10000, 422c81bfd5SHuy Nguyen [MLX5E_20GBASE_KR2] = 20000, 432c81bfd5SHuy Nguyen [MLX5E_40GBASE_CR4] = 40000, 442c81bfd5SHuy Nguyen [MLX5E_40GBASE_KR4] = 40000, 452c81bfd5SHuy Nguyen [MLX5E_56GBASE_R4] = 56000, 462c81bfd5SHuy Nguyen [MLX5E_10GBASE_CR] = 10000, 472c81bfd5SHuy Nguyen [MLX5E_10GBASE_SR] = 10000, 482c81bfd5SHuy Nguyen [MLX5E_10GBASE_ER] = 10000, 492c81bfd5SHuy Nguyen [MLX5E_40GBASE_SR4] = 40000, 502c81bfd5SHuy Nguyen [MLX5E_40GBASE_LR4] = 40000, 512c81bfd5SHuy Nguyen [MLX5E_50GBASE_SR2] = 50000, 522c81bfd5SHuy Nguyen [MLX5E_100GBASE_CR4] = 100000, 532c81bfd5SHuy Nguyen [MLX5E_100GBASE_SR4] = 100000, 542c81bfd5SHuy Nguyen [MLX5E_100GBASE_KR4] = 100000, 552c81bfd5SHuy Nguyen [MLX5E_100GBASE_LR4] = 100000, 562c81bfd5SHuy Nguyen [MLX5E_100BASE_TX] = 100, 572c81bfd5SHuy Nguyen [MLX5E_1000BASE_T] = 1000, 582c81bfd5SHuy Nguyen [MLX5E_10GBASE_T] = 10000, 592c81bfd5SHuy Nguyen [MLX5E_25GBASE_CR] = 25000, 602c81bfd5SHuy Nguyen [MLX5E_25GBASE_KR] = 25000, 612c81bfd5SHuy Nguyen [MLX5E_25GBASE_SR] = 25000, 622c81bfd5SHuy Nguyen [MLX5E_50GBASE_CR2] = 50000, 632c81bfd5SHuy Nguyen [MLX5E_50GBASE_KR2] = 50000, 642c81bfd5SHuy Nguyen }; 652c81bfd5SHuy Nguyen 662c81bfd5SHuy Nguyen u32 mlx5e_port_ptys2speed(u32 eth_proto_oper) 672c81bfd5SHuy Nguyen { 682c81bfd5SHuy Nguyen unsigned long temp = eth_proto_oper; 692c81bfd5SHuy Nguyen u32 speed = 0; 702c81bfd5SHuy Nguyen int i; 712c81bfd5SHuy Nguyen 722c81bfd5SHuy Nguyen i = find_first_bit(&temp, MLX5E_LINK_MODES_NUMBER); 732c81bfd5SHuy Nguyen if (i < MLX5E_LINK_MODES_NUMBER) 742c81bfd5SHuy Nguyen speed = mlx5e_link_speed[i]; 752c81bfd5SHuy Nguyen 762c81bfd5SHuy Nguyen return speed; 772c81bfd5SHuy Nguyen } 782c81bfd5SHuy Nguyen 792c81bfd5SHuy Nguyen int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) 802c81bfd5SHuy Nguyen { 812c81bfd5SHuy Nguyen u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {}; 822c81bfd5SHuy Nguyen u32 eth_proto_oper; 832c81bfd5SHuy Nguyen int err; 842c81bfd5SHuy Nguyen 852c81bfd5SHuy Nguyen err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN, 1); 862c81bfd5SHuy Nguyen if (err) 872c81bfd5SHuy Nguyen return err; 882c81bfd5SHuy Nguyen 892c81bfd5SHuy Nguyen eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 902c81bfd5SHuy Nguyen *speed = mlx5e_port_ptys2speed(eth_proto_oper); 912c81bfd5SHuy Nguyen if (!(*speed)) { 922c81bfd5SHuy Nguyen mlx5_core_warn(mdev, "cannot get port speed\n"); 932c81bfd5SHuy Nguyen err = -EINVAL; 942c81bfd5SHuy Nguyen } 952c81bfd5SHuy Nguyen 962c81bfd5SHuy Nguyen return err; 972c81bfd5SHuy Nguyen } 982c81bfd5SHuy Nguyen 992c81bfd5SHuy Nguyen int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) 1002c81bfd5SHuy Nguyen { 1012c81bfd5SHuy Nguyen u32 max_speed = 0; 1022c81bfd5SHuy Nguyen u32 proto_cap; 1032c81bfd5SHuy Nguyen int err; 1042c81bfd5SHuy Nguyen int i; 1052c81bfd5SHuy Nguyen 1062c81bfd5SHuy Nguyen err = mlx5_query_port_proto_cap(mdev, &proto_cap, MLX5_PTYS_EN); 1072c81bfd5SHuy Nguyen if (err) 1082c81bfd5SHuy Nguyen return err; 1092c81bfd5SHuy Nguyen 1102c81bfd5SHuy Nguyen for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) 1112c81bfd5SHuy Nguyen if (proto_cap & MLX5E_PROT_MASK(i)) 1122c81bfd5SHuy Nguyen max_speed = max(max_speed, mlx5e_link_speed[i]); 1132c81bfd5SHuy Nguyen 1142c81bfd5SHuy Nguyen *speed = max_speed; 1152c81bfd5SHuy Nguyen return 0; 1162c81bfd5SHuy Nguyen } 1172c81bfd5SHuy Nguyen 1182c81bfd5SHuy Nguyen u32 mlx5e_port_speed2linkmodes(u32 speed) 1192c81bfd5SHuy Nguyen { 1202c81bfd5SHuy Nguyen u32 link_modes = 0; 1212c81bfd5SHuy Nguyen int i; 1222c81bfd5SHuy Nguyen 1232c81bfd5SHuy Nguyen for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { 1242c81bfd5SHuy Nguyen if (mlx5e_link_speed[i] == speed) 1252c81bfd5SHuy Nguyen link_modes |= MLX5E_PROT_MASK(i); 1262c81bfd5SHuy Nguyen } 1272c81bfd5SHuy Nguyen 1282c81bfd5SHuy Nguyen return link_modes; 1292c81bfd5SHuy Nguyen } 13050b4a3c2SHuy Nguyen 13150b4a3c2SHuy Nguyen int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out) 13250b4a3c2SHuy Nguyen { 13350b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pbmc_reg); 13450b4a3c2SHuy Nguyen void *in; 13550b4a3c2SHuy Nguyen int err; 13650b4a3c2SHuy Nguyen 13750b4a3c2SHuy Nguyen in = kzalloc(sz, GFP_KERNEL); 13850b4a3c2SHuy Nguyen if (!in) 13950b4a3c2SHuy Nguyen return -ENOMEM; 14050b4a3c2SHuy Nguyen 14150b4a3c2SHuy Nguyen MLX5_SET(pbmc_reg, in, local_port, 1); 14250b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0); 14350b4a3c2SHuy Nguyen 14450b4a3c2SHuy Nguyen kfree(in); 14550b4a3c2SHuy Nguyen return err; 14650b4a3c2SHuy Nguyen } 14750b4a3c2SHuy Nguyen 14850b4a3c2SHuy Nguyen int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in) 14950b4a3c2SHuy Nguyen { 15050b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pbmc_reg); 15150b4a3c2SHuy Nguyen void *out; 15250b4a3c2SHuy Nguyen int err; 15350b4a3c2SHuy Nguyen 15450b4a3c2SHuy Nguyen out = kzalloc(sz, GFP_KERNEL); 15550b4a3c2SHuy Nguyen if (!out) 15650b4a3c2SHuy Nguyen return -ENOMEM; 15750b4a3c2SHuy Nguyen 15850b4a3c2SHuy Nguyen MLX5_SET(pbmc_reg, in, local_port, 1); 15950b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1); 16050b4a3c2SHuy Nguyen 16150b4a3c2SHuy Nguyen kfree(out); 16250b4a3c2SHuy Nguyen return err; 16350b4a3c2SHuy Nguyen } 16450b4a3c2SHuy Nguyen 16550b4a3c2SHuy Nguyen /* buffer[i]: buffer that priority i mapped to */ 16650b4a3c2SHuy Nguyen int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer) 16750b4a3c2SHuy Nguyen { 16850b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pptb_reg); 16950b4a3c2SHuy Nguyen u32 prio_x_buff; 17050b4a3c2SHuy Nguyen void *out; 17150b4a3c2SHuy Nguyen void *in; 17250b4a3c2SHuy Nguyen int prio; 17350b4a3c2SHuy Nguyen int err; 17450b4a3c2SHuy Nguyen 17550b4a3c2SHuy Nguyen in = kzalloc(sz, GFP_KERNEL); 17650b4a3c2SHuy Nguyen out = kzalloc(sz, GFP_KERNEL); 17750b4a3c2SHuy Nguyen if (!in || !out) { 17850b4a3c2SHuy Nguyen err = -ENOMEM; 17950b4a3c2SHuy Nguyen goto out; 18050b4a3c2SHuy Nguyen } 18150b4a3c2SHuy Nguyen 18250b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, local_port, 1); 18350b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0); 18450b4a3c2SHuy Nguyen if (err) 18550b4a3c2SHuy Nguyen goto out; 18650b4a3c2SHuy Nguyen 18750b4a3c2SHuy Nguyen prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff); 18850b4a3c2SHuy Nguyen for (prio = 0; prio < 8; prio++) { 18950b4a3c2SHuy Nguyen buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF; 19050b4a3c2SHuy Nguyen mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]); 19150b4a3c2SHuy Nguyen } 19250b4a3c2SHuy Nguyen out: 19350b4a3c2SHuy Nguyen kfree(in); 19450b4a3c2SHuy Nguyen kfree(out); 19550b4a3c2SHuy Nguyen return err; 19650b4a3c2SHuy Nguyen } 19750b4a3c2SHuy Nguyen 19850b4a3c2SHuy Nguyen int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer) 19950b4a3c2SHuy Nguyen { 20050b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pptb_reg); 20150b4a3c2SHuy Nguyen u32 prio_x_buff; 20250b4a3c2SHuy Nguyen void *out; 20350b4a3c2SHuy Nguyen void *in; 20450b4a3c2SHuy Nguyen int prio; 20550b4a3c2SHuy Nguyen int err; 20650b4a3c2SHuy Nguyen 20750b4a3c2SHuy Nguyen in = kzalloc(sz, GFP_KERNEL); 20850b4a3c2SHuy Nguyen out = kzalloc(sz, GFP_KERNEL); 20950b4a3c2SHuy Nguyen if (!in || !out) { 21050b4a3c2SHuy Nguyen err = -ENOMEM; 21150b4a3c2SHuy Nguyen goto out; 21250b4a3c2SHuy Nguyen } 21350b4a3c2SHuy Nguyen 21450b4a3c2SHuy Nguyen /* First query the pptb register */ 21550b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, local_port, 1); 21650b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0); 21750b4a3c2SHuy Nguyen if (err) 21850b4a3c2SHuy Nguyen goto out; 21950b4a3c2SHuy Nguyen 22050b4a3c2SHuy Nguyen memcpy(in, out, sz); 22150b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, local_port, 1); 22250b4a3c2SHuy Nguyen 22350b4a3c2SHuy Nguyen /* Update the pm and prio_x_buff */ 22450b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, pm, 0xFF); 22550b4a3c2SHuy Nguyen 22650b4a3c2SHuy Nguyen prio_x_buff = 0; 22750b4a3c2SHuy Nguyen for (prio = 0; prio < 8; prio++) 22850b4a3c2SHuy Nguyen prio_x_buff |= (buffer[prio] << (4 * prio)); 22950b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff); 23050b4a3c2SHuy Nguyen 23150b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1); 23250b4a3c2SHuy Nguyen 23350b4a3c2SHuy Nguyen out: 23450b4a3c2SHuy Nguyen kfree(in); 23550b4a3c2SHuy Nguyen kfree(out); 23650b4a3c2SHuy Nguyen return err; 23750b4a3c2SHuy Nguyen } 2382095b264SShay Agroskin 2392095b264SShay Agroskin static u32 fec_supported_speeds[] = { 2402095b264SShay Agroskin 10000, 2412095b264SShay Agroskin 40000, 2422095b264SShay Agroskin 25000, 2432095b264SShay Agroskin 50000, 2442095b264SShay Agroskin 56000, 2452095b264SShay Agroskin 100000 2462095b264SShay Agroskin }; 2472095b264SShay Agroskin 2482095b264SShay Agroskin #define MLX5E_FEC_SUPPORTED_SPEEDS ARRAY_SIZE(fec_supported_speeds) 2492095b264SShay Agroskin 2502095b264SShay Agroskin /* get/set FEC admin field for a given speed */ 2512095b264SShay Agroskin static int mlx5e_fec_admin_field(u32 *pplm, 2522095b264SShay Agroskin u8 *fec_policy, 2532095b264SShay Agroskin bool write, 2542095b264SShay Agroskin u32 speed) 2552095b264SShay Agroskin { 2562095b264SShay Agroskin switch (speed) { 2572095b264SShay Agroskin case 10000: 2582095b264SShay Agroskin case 40000: 2592095b264SShay Agroskin if (!write) 2602095b264SShay Agroskin *fec_policy = MLX5_GET(pplm_reg, pplm, 261febd72f2SShay Agroskin fec_override_admin_10g_40g); 2622095b264SShay Agroskin else 2632095b264SShay Agroskin MLX5_SET(pplm_reg, pplm, 2642095b264SShay Agroskin fec_override_admin_10g_40g, *fec_policy); 2652095b264SShay Agroskin break; 2662095b264SShay Agroskin case 25000: 2672095b264SShay Agroskin if (!write) 2682095b264SShay Agroskin *fec_policy = MLX5_GET(pplm_reg, pplm, 2692095b264SShay Agroskin fec_override_admin_25g); 2702095b264SShay Agroskin else 2712095b264SShay Agroskin MLX5_SET(pplm_reg, pplm, 2722095b264SShay Agroskin fec_override_admin_25g, *fec_policy); 2732095b264SShay Agroskin break; 2742095b264SShay Agroskin case 50000: 2752095b264SShay Agroskin if (!write) 2762095b264SShay Agroskin *fec_policy = MLX5_GET(pplm_reg, pplm, 2772095b264SShay Agroskin fec_override_admin_50g); 2782095b264SShay Agroskin else 2792095b264SShay Agroskin MLX5_SET(pplm_reg, pplm, 2802095b264SShay Agroskin fec_override_admin_50g, *fec_policy); 2812095b264SShay Agroskin break; 2822095b264SShay Agroskin case 56000: 2832095b264SShay Agroskin if (!write) 2842095b264SShay Agroskin *fec_policy = MLX5_GET(pplm_reg, pplm, 2852095b264SShay Agroskin fec_override_admin_56g); 2862095b264SShay Agroskin else 2872095b264SShay Agroskin MLX5_SET(pplm_reg, pplm, 2882095b264SShay Agroskin fec_override_admin_56g, *fec_policy); 2892095b264SShay Agroskin break; 2902095b264SShay Agroskin case 100000: 2912095b264SShay Agroskin if (!write) 2922095b264SShay Agroskin *fec_policy = MLX5_GET(pplm_reg, pplm, 2932095b264SShay Agroskin fec_override_admin_100g); 2942095b264SShay Agroskin else 2952095b264SShay Agroskin MLX5_SET(pplm_reg, pplm, 2962095b264SShay Agroskin fec_override_admin_100g, *fec_policy); 2972095b264SShay Agroskin break; 2982095b264SShay Agroskin default: 2992095b264SShay Agroskin return -EINVAL; 3002095b264SShay Agroskin } 3012095b264SShay Agroskin return 0; 3022095b264SShay Agroskin } 3032095b264SShay Agroskin 3042095b264SShay Agroskin /* returns FEC capabilities for a given speed */ 3052095b264SShay Agroskin static int mlx5e_get_fec_cap_field(u32 *pplm, 3062095b264SShay Agroskin u8 *fec_cap, 3072095b264SShay Agroskin u32 speed) 3082095b264SShay Agroskin { 3092095b264SShay Agroskin switch (speed) { 3102095b264SShay Agroskin case 10000: 3112095b264SShay Agroskin case 40000: 3122095b264SShay Agroskin *fec_cap = MLX5_GET(pplm_reg, pplm, 313febd72f2SShay Agroskin fec_override_cap_10g_40g); 3142095b264SShay Agroskin break; 3152095b264SShay Agroskin case 25000: 3162095b264SShay Agroskin *fec_cap = MLX5_GET(pplm_reg, pplm, 3172095b264SShay Agroskin fec_override_cap_25g); 3182095b264SShay Agroskin break; 3192095b264SShay Agroskin case 50000: 3202095b264SShay Agroskin *fec_cap = MLX5_GET(pplm_reg, pplm, 3212095b264SShay Agroskin fec_override_cap_50g); 3222095b264SShay Agroskin break; 3232095b264SShay Agroskin case 56000: 3242095b264SShay Agroskin *fec_cap = MLX5_GET(pplm_reg, pplm, 3252095b264SShay Agroskin fec_override_cap_56g); 3262095b264SShay Agroskin break; 3272095b264SShay Agroskin case 100000: 3282095b264SShay Agroskin *fec_cap = MLX5_GET(pplm_reg, pplm, 3292095b264SShay Agroskin fec_override_cap_100g); 3302095b264SShay Agroskin break; 3312095b264SShay Agroskin default: 3322095b264SShay Agroskin return -EINVAL; 3332095b264SShay Agroskin } 3342095b264SShay Agroskin return 0; 3352095b264SShay Agroskin } 3362095b264SShay Agroskin 3372095b264SShay Agroskin int mlx5e_get_fec_caps(struct mlx5_core_dev *dev, u8 *fec_caps) 3382095b264SShay Agroskin { 3392095b264SShay Agroskin u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 3402095b264SShay Agroskin u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 3412095b264SShay Agroskin int sz = MLX5_ST_SZ_BYTES(pplm_reg); 3422095b264SShay Agroskin u32 current_fec_speed; 3432095b264SShay Agroskin int err; 3442095b264SShay Agroskin 3452095b264SShay Agroskin if (!MLX5_CAP_GEN(dev, pcam_reg)) 3462095b264SShay Agroskin return -EOPNOTSUPP; 3472095b264SShay Agroskin 3482095b264SShay Agroskin if (!MLX5_CAP_PCAM_REG(dev, pplm)) 3492095b264SShay Agroskin return -EOPNOTSUPP; 3502095b264SShay Agroskin 3512095b264SShay Agroskin MLX5_SET(pplm_reg, in, local_port, 1); 3522095b264SShay Agroskin err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0); 3532095b264SShay Agroskin if (err) 3542095b264SShay Agroskin return err; 3552095b264SShay Agroskin 3562095b264SShay Agroskin err = mlx5e_port_linkspeed(dev, ¤t_fec_speed); 3572095b264SShay Agroskin if (err) 3582095b264SShay Agroskin return err; 3592095b264SShay Agroskin 3602095b264SShay Agroskin return mlx5e_get_fec_cap_field(out, fec_caps, current_fec_speed); 3612095b264SShay Agroskin } 3622095b264SShay Agroskin 3632095b264SShay Agroskin int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active, 3642095b264SShay Agroskin u8 *fec_configured_mode) 3652095b264SShay Agroskin { 3662095b264SShay Agroskin u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 3672095b264SShay Agroskin u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 3682095b264SShay Agroskin int sz = MLX5_ST_SZ_BYTES(pplm_reg); 3692095b264SShay Agroskin u32 link_speed; 3702095b264SShay Agroskin int err; 3712095b264SShay Agroskin 3722095b264SShay Agroskin if (!MLX5_CAP_GEN(dev, pcam_reg)) 3732095b264SShay Agroskin return -EOPNOTSUPP; 3742095b264SShay Agroskin 3752095b264SShay Agroskin if (!MLX5_CAP_PCAM_REG(dev, pplm)) 3762095b264SShay Agroskin return -EOPNOTSUPP; 3772095b264SShay Agroskin 3782095b264SShay Agroskin MLX5_SET(pplm_reg, in, local_port, 1); 3792095b264SShay Agroskin err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0); 3802095b264SShay Agroskin if (err) 3812095b264SShay Agroskin return err; 3822095b264SShay Agroskin 3832095b264SShay Agroskin *fec_mode_active = MLX5_GET(pplm_reg, out, fec_mode_active); 3842095b264SShay Agroskin 3852095b264SShay Agroskin if (!fec_configured_mode) 3862095b264SShay Agroskin return 0; 3872095b264SShay Agroskin 3882095b264SShay Agroskin err = mlx5e_port_linkspeed(dev, &link_speed); 3892095b264SShay Agroskin if (err) 3902095b264SShay Agroskin return err; 3912095b264SShay Agroskin 3922095b264SShay Agroskin return mlx5e_fec_admin_field(out, fec_configured_mode, 0, link_speed); 3932095b264SShay Agroskin } 3942095b264SShay Agroskin 3952095b264SShay Agroskin int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy) 3962095b264SShay Agroskin { 3979cdeaab3SShay Agroskin u8 fec_policy_nofec = BIT(MLX5E_FEC_NOFEC); 3982095b264SShay Agroskin bool fec_mode_not_supp_in_speed = false; 3992095b264SShay Agroskin u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 4002095b264SShay Agroskin u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 4012095b264SShay Agroskin int sz = MLX5_ST_SZ_BYTES(pplm_reg); 4029cdeaab3SShay Agroskin u8 fec_policy_auto = 0; 4032095b264SShay Agroskin u8 fec_caps = 0; 4042095b264SShay Agroskin int err; 4052095b264SShay Agroskin int i; 4062095b264SShay Agroskin 4072095b264SShay Agroskin if (!MLX5_CAP_GEN(dev, pcam_reg)) 4082095b264SShay Agroskin return -EOPNOTSUPP; 4092095b264SShay Agroskin 4102095b264SShay Agroskin if (!MLX5_CAP_PCAM_REG(dev, pplm)) 4112095b264SShay Agroskin return -EOPNOTSUPP; 4122095b264SShay Agroskin 4132095b264SShay Agroskin MLX5_SET(pplm_reg, in, local_port, 1); 4142095b264SShay Agroskin err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0); 4152095b264SShay Agroskin if (err) 4162095b264SShay Agroskin return err; 4172095b264SShay Agroskin 4189cdeaab3SShay Agroskin MLX5_SET(pplm_reg, out, local_port, 1); 4192095b264SShay Agroskin 4209cdeaab3SShay Agroskin for (i = 0; i < MLX5E_FEC_SUPPORTED_SPEEDS; i++) { 4212095b264SShay Agroskin mlx5e_get_fec_cap_field(out, &fec_caps, fec_supported_speeds[i]); 4229cdeaab3SShay Agroskin /* policy supported for link speed, or policy is auto */ 4239cdeaab3SShay Agroskin if (fec_caps & fec_policy || fec_policy == fec_policy_auto) { 4249cdeaab3SShay Agroskin mlx5e_fec_admin_field(out, &fec_policy, 1, 4252095b264SShay Agroskin fec_supported_speeds[i]); 4262095b264SShay Agroskin } else { 4279cdeaab3SShay Agroskin /* turn off FEC if supported. Else, leave it the same */ 4289cdeaab3SShay Agroskin if (fec_caps & fec_policy_nofec) 4299cdeaab3SShay Agroskin mlx5e_fec_admin_field(out, &fec_policy_nofec, 1, 4302095b264SShay Agroskin fec_supported_speeds[i]); 4312095b264SShay Agroskin fec_mode_not_supp_in_speed = true; 4322095b264SShay Agroskin } 4332095b264SShay Agroskin } 4342095b264SShay Agroskin 4352095b264SShay Agroskin if (fec_mode_not_supp_in_speed) 4362095b264SShay Agroskin mlx5_core_dbg(dev, 4372095b264SShay Agroskin "FEC policy 0x%x is not supported for some speeds", 4382095b264SShay Agroskin fec_policy); 4392095b264SShay Agroskin 4409cdeaab3SShay Agroskin return mlx5_core_access_reg(dev, out, sz, out, sz, MLX5_REG_PPLM, 0, 1); 4412095b264SShay Agroskin } 442