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 66a08b4ed1SAya Levin static const u32 mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = { 67a08b4ed1SAya Levin [MLX5E_SGMII_100M] = 100, 68a08b4ed1SAya Levin [MLX5E_1000BASE_X_SGMII] = 1000, 69a08b4ed1SAya Levin [MLX5E_5GBASE_R] = 5000, 70a08b4ed1SAya Levin [MLX5E_10GBASE_XFI_XAUI_1] = 10000, 71a08b4ed1SAya Levin [MLX5E_40GBASE_XLAUI_4_XLPPI_4] = 40000, 72a08b4ed1SAya Levin [MLX5E_25GAUI_1_25GBASE_CR_KR] = 25000, 73a08b4ed1SAya Levin [MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2] = 50000, 74a08b4ed1SAya Levin [MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR] = 50000, 75a08b4ed1SAya Levin [MLX5E_CAUI_4_100GBASE_CR4_KR4] = 100000, 766d485e5eSAya Levin [MLX5E_100GAUI_2_100GBASE_CR2_KR2] = 100000, 77a08b4ed1SAya Levin [MLX5E_200GAUI_4_200GBASE_CR4_KR4] = 200000, 78a08b4ed1SAya Levin [MLX5E_400GAUI_8] = 400000, 7912fdafb8SMeir Lichtinger [MLX5E_100GAUI_1_100GBASE_CR_KR] = 100000, 8012fdafb8SMeir Lichtinger [MLX5E_200GAUI_2_200GBASE_CR2_KR2] = 200000, 8112fdafb8SMeir Lichtinger [MLX5E_400GAUI_4_400GBASE_CR4_KR4] = 400000, 82a08b4ed1SAya Levin }; 83a08b4ed1SAya Levin 846a1cf4e4SAya Levin bool mlx5e_ptys_ext_supported(struct mlx5_core_dev *mdev) 856a1cf4e4SAya Levin { 866a1cf4e4SAya Levin struct mlx5e_port_eth_proto eproto; 876a1cf4e4SAya Levin int err; 886a1cf4e4SAya Levin 896a1cf4e4SAya Levin if (MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet)) 906a1cf4e4SAya Levin return true; 916a1cf4e4SAya Levin 926a1cf4e4SAya Levin err = mlx5_port_query_eth_proto(mdev, 1, true, &eproto); 936a1cf4e4SAya Levin if (err) 946a1cf4e4SAya Levin return false; 956a1cf4e4SAya Levin 966a1cf4e4SAya Levin return !!eproto.cap; 976a1cf4e4SAya Levin } 986a1cf4e4SAya Levin 99a08b4ed1SAya Levin static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev, 1004b95840aSAya Levin const u32 **arr, u32 *size, 1014b95840aSAya Levin bool force_legacy) 102a08b4ed1SAya Levin { 1036a1cf4e4SAya Levin bool ext = force_legacy ? false : mlx5e_ptys_ext_supported(mdev); 104a08b4ed1SAya Levin 105a08b4ed1SAya Levin *size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) : 106a08b4ed1SAya Levin ARRAY_SIZE(mlx5e_link_speed); 107a08b4ed1SAya Levin *arr = ext ? mlx5e_ext_link_speed : mlx5e_link_speed; 108a08b4ed1SAya Levin } 109a08b4ed1SAya Levin 110a08b4ed1SAya Levin int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext, 111bc4e12ffSAya Levin struct mlx5e_port_eth_proto *eproto) 112bc4e12ffSAya Levin { 113bc4e12ffSAya Levin u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 114bc4e12ffSAya Levin int err; 115bc4e12ffSAya Levin 116bc4e12ffSAya Levin if (!eproto) 117bc4e12ffSAya Levin return -EINVAL; 118bc4e12ffSAya Levin 119bc4e12ffSAya Levin err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port); 120bc4e12ffSAya Levin if (err) 121bc4e12ffSAya Levin return err; 122bc4e12ffSAya Levin 123a08b4ed1SAya Levin eproto->cap = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, 124a08b4ed1SAya Levin eth_proto_capability); 125a08b4ed1SAya Levin eproto->admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_admin); 126a08b4ed1SAya Levin eproto->oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper); 127bc4e12ffSAya Levin return 0; 128bc4e12ffSAya Levin } 129bc4e12ffSAya Levin 130bc4e12ffSAya Levin void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status, 131bc4e12ffSAya Levin u8 *an_disable_cap, u8 *an_disable_admin) 132bc4e12ffSAya Levin { 133bc4e12ffSAya Levin u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 134bc4e12ffSAya Levin 135bc4e12ffSAya Levin *an_status = 0; 136bc4e12ffSAya Levin *an_disable_cap = 0; 137bc4e12ffSAya Levin *an_disable_admin = 0; 138bc4e12ffSAya Levin 139bc4e12ffSAya Levin if (mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, 1)) 140bc4e12ffSAya Levin return; 141bc4e12ffSAya Levin 142bc4e12ffSAya Levin *an_status = MLX5_GET(ptys_reg, out, an_status); 143bc4e12ffSAya Levin *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap); 144bc4e12ffSAya Levin *an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin); 145bc4e12ffSAya Levin } 146bc4e12ffSAya Levin 147bc4e12ffSAya Levin int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable, 148a08b4ed1SAya Levin u32 proto_admin, bool ext) 149bc4e12ffSAya Levin { 150bc4e12ffSAya Levin u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 151bc4e12ffSAya Levin u32 in[MLX5_ST_SZ_DW(ptys_reg)]; 152bc4e12ffSAya Levin u8 an_disable_admin; 153bc4e12ffSAya Levin u8 an_disable_cap; 154bc4e12ffSAya Levin u8 an_status; 155bc4e12ffSAya Levin 156bc4e12ffSAya Levin mlx5_port_query_eth_autoneg(dev, &an_status, &an_disable_cap, 157bc4e12ffSAya Levin &an_disable_admin); 158bc4e12ffSAya Levin if (!an_disable_cap && an_disable) 159bc4e12ffSAya Levin return -EPERM; 160bc4e12ffSAya Levin 161bc4e12ffSAya Levin memset(in, 0, sizeof(in)); 162bc4e12ffSAya Levin 163bc4e12ffSAya Levin MLX5_SET(ptys_reg, in, local_port, 1); 164bc4e12ffSAya Levin MLX5_SET(ptys_reg, in, an_disable_admin, an_disable); 165bc4e12ffSAya Levin MLX5_SET(ptys_reg, in, proto_mask, MLX5_PTYS_EN); 166a08b4ed1SAya Levin if (ext) 167a08b4ed1SAya Levin MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin); 168a08b4ed1SAya Levin else 169bc4e12ffSAya Levin MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin); 170bc4e12ffSAya Levin 171bc4e12ffSAya Levin return mlx5_core_access_reg(dev, in, sizeof(in), out, 172bc4e12ffSAya Levin sizeof(out), MLX5_REG_PTYS, 0, 1); 173bc4e12ffSAya Levin } 174bc4e12ffSAya Levin 1754b95840aSAya Levin u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper, 1764b95840aSAya Levin bool force_legacy) 1772c81bfd5SHuy Nguyen { 1782c81bfd5SHuy Nguyen unsigned long temp = eth_proto_oper; 179a08b4ed1SAya Levin const u32 *table; 1802c81bfd5SHuy Nguyen u32 speed = 0; 181a08b4ed1SAya Levin u32 max_size; 1822c81bfd5SHuy Nguyen int i; 1832c81bfd5SHuy Nguyen 1844b95840aSAya Levin mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy); 185a08b4ed1SAya Levin i = find_first_bit(&temp, max_size); 186a08b4ed1SAya Levin if (i < max_size) 187a08b4ed1SAya Levin speed = table[i]; 1882c81bfd5SHuy Nguyen return speed; 1892c81bfd5SHuy Nguyen } 1902c81bfd5SHuy Nguyen 1912c81bfd5SHuy Nguyen int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) 1922c81bfd5SHuy Nguyen { 193bc4e12ffSAya Levin struct mlx5e_port_eth_proto eproto; 1944b95840aSAya Levin bool force_legacy = false; 195a08b4ed1SAya Levin bool ext; 1962c81bfd5SHuy Nguyen int err; 1972c81bfd5SHuy Nguyen 1986a1cf4e4SAya Levin ext = mlx5e_ptys_ext_supported(mdev); 199a08b4ed1SAya Levin err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto); 2002c81bfd5SHuy Nguyen if (err) 201a08b4ed1SAya Levin goto out; 2024b95840aSAya Levin if (ext && !eproto.admin) { 2034b95840aSAya Levin force_legacy = true; 2044b95840aSAya Levin err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto); 2054b95840aSAya Levin if (err) 2064b95840aSAya Levin goto out; 2074b95840aSAya Levin } 2084b95840aSAya Levin *speed = mlx5e_port_ptys2speed(mdev, eproto.oper, force_legacy); 20964e28334SShay Agroskin if (!(*speed)) 2102c81bfd5SHuy Nguyen err = -EINVAL; 2112c81bfd5SHuy Nguyen 212a08b4ed1SAya Levin out: 2132c81bfd5SHuy Nguyen return err; 2142c81bfd5SHuy Nguyen } 2152c81bfd5SHuy Nguyen 2162c81bfd5SHuy Nguyen int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) 2172c81bfd5SHuy Nguyen { 218bc4e12ffSAya Levin struct mlx5e_port_eth_proto eproto; 2192c81bfd5SHuy Nguyen u32 max_speed = 0; 220a08b4ed1SAya Levin const u32 *table; 221a08b4ed1SAya Levin u32 max_size; 222a08b4ed1SAya Levin bool ext; 2232c81bfd5SHuy Nguyen int err; 2242c81bfd5SHuy Nguyen int i; 2252c81bfd5SHuy Nguyen 2266a1cf4e4SAya Levin ext = mlx5e_ptys_ext_supported(mdev); 227a08b4ed1SAya Levin err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto); 2282c81bfd5SHuy Nguyen if (err) 2292c81bfd5SHuy Nguyen return err; 2302c81bfd5SHuy Nguyen 2314b95840aSAya Levin mlx5e_port_get_speed_arr(mdev, &table, &max_size, false); 232a08b4ed1SAya Levin for (i = 0; i < max_size; ++i) 233bc4e12ffSAya Levin if (eproto.cap & MLX5E_PROT_MASK(i)) 234a08b4ed1SAya Levin max_speed = max(max_speed, table[i]); 2352c81bfd5SHuy Nguyen 2362c81bfd5SHuy Nguyen *speed = max_speed; 2372c81bfd5SHuy Nguyen return 0; 2382c81bfd5SHuy Nguyen } 2392c81bfd5SHuy Nguyen 2404b95840aSAya Levin u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed, 2414b95840aSAya Levin bool force_legacy) 2422c81bfd5SHuy Nguyen { 2432c81bfd5SHuy Nguyen u32 link_modes = 0; 244a08b4ed1SAya Levin const u32 *table; 245a08b4ed1SAya Levin u32 max_size; 2462c81bfd5SHuy Nguyen int i; 2472c81bfd5SHuy Nguyen 2484b95840aSAya Levin mlx5e_port_get_speed_arr(mdev, &table, &max_size, force_legacy); 249a08b4ed1SAya Levin for (i = 0; i < max_size; ++i) { 250a08b4ed1SAya Levin if (table[i] == speed) 2512c81bfd5SHuy Nguyen link_modes |= MLX5E_PROT_MASK(i); 2522c81bfd5SHuy Nguyen } 2532c81bfd5SHuy Nguyen return link_modes; 2542c81bfd5SHuy Nguyen } 25550b4a3c2SHuy Nguyen 25650b4a3c2SHuy Nguyen int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out) 25750b4a3c2SHuy Nguyen { 25850b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pbmc_reg); 25950b4a3c2SHuy Nguyen void *in; 26050b4a3c2SHuy Nguyen int err; 26150b4a3c2SHuy Nguyen 26250b4a3c2SHuy Nguyen in = kzalloc(sz, GFP_KERNEL); 26350b4a3c2SHuy Nguyen if (!in) 26450b4a3c2SHuy Nguyen return -ENOMEM; 26550b4a3c2SHuy Nguyen 26650b4a3c2SHuy Nguyen MLX5_SET(pbmc_reg, in, local_port, 1); 26750b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0); 26850b4a3c2SHuy Nguyen 26950b4a3c2SHuy Nguyen kfree(in); 27050b4a3c2SHuy Nguyen return err; 27150b4a3c2SHuy Nguyen } 27250b4a3c2SHuy Nguyen 27350b4a3c2SHuy Nguyen int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in) 27450b4a3c2SHuy Nguyen { 27550b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pbmc_reg); 27650b4a3c2SHuy Nguyen void *out; 27750b4a3c2SHuy Nguyen int err; 27850b4a3c2SHuy Nguyen 27950b4a3c2SHuy Nguyen out = kzalloc(sz, GFP_KERNEL); 28050b4a3c2SHuy Nguyen if (!out) 28150b4a3c2SHuy Nguyen return -ENOMEM; 28250b4a3c2SHuy Nguyen 28350b4a3c2SHuy Nguyen MLX5_SET(pbmc_reg, in, local_port, 1); 28450b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1); 28550b4a3c2SHuy Nguyen 28650b4a3c2SHuy Nguyen kfree(out); 28750b4a3c2SHuy Nguyen return err; 28850b4a3c2SHuy Nguyen } 28950b4a3c2SHuy Nguyen 290*11f0996dSMaher Sanalla int mlx5e_port_query_sbpr(struct mlx5_core_dev *mdev, u32 desc, u8 dir, 291*11f0996dSMaher Sanalla u8 pool_idx, void *out, int size_out) 292*11f0996dSMaher Sanalla { 293*11f0996dSMaher Sanalla u32 in[MLX5_ST_SZ_DW(sbpr_reg)] = {}; 294*11f0996dSMaher Sanalla 295*11f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, desc, desc); 296*11f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, dir, dir); 297*11f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, pool, pool_idx); 298*11f0996dSMaher Sanalla 299*11f0996dSMaher Sanalla return mlx5_core_access_reg(mdev, in, sizeof(in), out, size_out, MLX5_REG_SBPR, 0, 0); 300*11f0996dSMaher Sanalla } 301*11f0996dSMaher Sanalla 302*11f0996dSMaher Sanalla int mlx5e_port_set_sbpr(struct mlx5_core_dev *mdev, u32 desc, u8 dir, 303*11f0996dSMaher Sanalla u8 pool_idx, u32 infi_size, u32 size) 304*11f0996dSMaher Sanalla { 305*11f0996dSMaher Sanalla u32 out[MLX5_ST_SZ_DW(sbpr_reg)] = {}; 306*11f0996dSMaher Sanalla u32 in[MLX5_ST_SZ_DW(sbpr_reg)] = {}; 307*11f0996dSMaher Sanalla 308*11f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, desc, desc); 309*11f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, dir, dir); 310*11f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, pool, pool_idx); 311*11f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, infi_size, infi_size); 312*11f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, size, size); 313*11f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, mode, 1); 314*11f0996dSMaher Sanalla 315*11f0996dSMaher Sanalla return mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), MLX5_REG_SBPR, 0, 1); 316*11f0996dSMaher Sanalla } 317*11f0996dSMaher Sanalla 318*11f0996dSMaher Sanalla static int mlx5e_port_query_sbcm(struct mlx5_core_dev *mdev, u32 desc, 319*11f0996dSMaher Sanalla u8 pg_buff_idx, u8 dir, void *out, 320*11f0996dSMaher Sanalla int size_out) 321*11f0996dSMaher Sanalla { 322*11f0996dSMaher Sanalla u32 in[MLX5_ST_SZ_DW(sbcm_reg)] = {}; 323*11f0996dSMaher Sanalla 324*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, desc, desc); 325*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, local_port, 1); 326*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, pg_buff, pg_buff_idx); 327*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, dir, dir); 328*11f0996dSMaher Sanalla 329*11f0996dSMaher Sanalla return mlx5_core_access_reg(mdev, in, sizeof(in), out, size_out, MLX5_REG_SBCM, 0, 0); 330*11f0996dSMaher Sanalla } 331*11f0996dSMaher Sanalla 332*11f0996dSMaher Sanalla int mlx5e_port_set_sbcm(struct mlx5_core_dev *mdev, u32 desc, u8 pg_buff_idx, 333*11f0996dSMaher Sanalla u8 dir, u8 infi_size, u32 max_buff, u8 pool_idx) 334*11f0996dSMaher Sanalla { 335*11f0996dSMaher Sanalla u32 out[MLX5_ST_SZ_DW(sbcm_reg)] = {}; 336*11f0996dSMaher Sanalla u32 in[MLX5_ST_SZ_DW(sbcm_reg)] = {}; 337*11f0996dSMaher Sanalla u32 min_buff; 338*11f0996dSMaher Sanalla int err; 339*11f0996dSMaher Sanalla u8 exc; 340*11f0996dSMaher Sanalla 341*11f0996dSMaher Sanalla err = mlx5e_port_query_sbcm(mdev, desc, pg_buff_idx, dir, out, 342*11f0996dSMaher Sanalla sizeof(out)); 343*11f0996dSMaher Sanalla if (err) 344*11f0996dSMaher Sanalla return err; 345*11f0996dSMaher Sanalla 346*11f0996dSMaher Sanalla exc = MLX5_GET(sbcm_reg, out, exc); 347*11f0996dSMaher Sanalla min_buff = MLX5_GET(sbcm_reg, out, min_buff); 348*11f0996dSMaher Sanalla 349*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, desc, desc); 350*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, local_port, 1); 351*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, pg_buff, pg_buff_idx); 352*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, dir, dir); 353*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, exc, exc); 354*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, min_buff, min_buff); 355*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, infi_max, infi_size); 356*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, max_buff, max_buff); 357*11f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, pool, pool_idx); 358*11f0996dSMaher Sanalla 359*11f0996dSMaher Sanalla return mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), MLX5_REG_SBCM, 0, 1); 360*11f0996dSMaher Sanalla } 361*11f0996dSMaher Sanalla 36250b4a3c2SHuy Nguyen /* buffer[i]: buffer that priority i mapped to */ 36350b4a3c2SHuy Nguyen int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer) 36450b4a3c2SHuy Nguyen { 36550b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pptb_reg); 36650b4a3c2SHuy Nguyen u32 prio_x_buff; 36750b4a3c2SHuy Nguyen void *out; 36850b4a3c2SHuy Nguyen void *in; 36950b4a3c2SHuy Nguyen int prio; 37050b4a3c2SHuy Nguyen int err; 37150b4a3c2SHuy Nguyen 37250b4a3c2SHuy Nguyen in = kzalloc(sz, GFP_KERNEL); 37350b4a3c2SHuy Nguyen out = kzalloc(sz, GFP_KERNEL); 37450b4a3c2SHuy Nguyen if (!in || !out) { 37550b4a3c2SHuy Nguyen err = -ENOMEM; 37650b4a3c2SHuy Nguyen goto out; 37750b4a3c2SHuy Nguyen } 37850b4a3c2SHuy Nguyen 37950b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, local_port, 1); 38050b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0); 38150b4a3c2SHuy Nguyen if (err) 38250b4a3c2SHuy Nguyen goto out; 38350b4a3c2SHuy Nguyen 38450b4a3c2SHuy Nguyen prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff); 38550b4a3c2SHuy Nguyen for (prio = 0; prio < 8; prio++) { 38650b4a3c2SHuy Nguyen buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF; 38750b4a3c2SHuy Nguyen mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]); 38850b4a3c2SHuy Nguyen } 38950b4a3c2SHuy Nguyen out: 39050b4a3c2SHuy Nguyen kfree(in); 39150b4a3c2SHuy Nguyen kfree(out); 39250b4a3c2SHuy Nguyen return err; 39350b4a3c2SHuy Nguyen } 39450b4a3c2SHuy Nguyen 39550b4a3c2SHuy Nguyen int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer) 39650b4a3c2SHuy Nguyen { 39750b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pptb_reg); 39850b4a3c2SHuy Nguyen u32 prio_x_buff; 39950b4a3c2SHuy Nguyen void *out; 40050b4a3c2SHuy Nguyen void *in; 40150b4a3c2SHuy Nguyen int prio; 40250b4a3c2SHuy Nguyen int err; 40350b4a3c2SHuy Nguyen 40450b4a3c2SHuy Nguyen in = kzalloc(sz, GFP_KERNEL); 40550b4a3c2SHuy Nguyen out = kzalloc(sz, GFP_KERNEL); 40650b4a3c2SHuy Nguyen if (!in || !out) { 40750b4a3c2SHuy Nguyen err = -ENOMEM; 40850b4a3c2SHuy Nguyen goto out; 40950b4a3c2SHuy Nguyen } 41050b4a3c2SHuy Nguyen 41150b4a3c2SHuy Nguyen /* First query the pptb register */ 41250b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, local_port, 1); 41350b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0); 41450b4a3c2SHuy Nguyen if (err) 41550b4a3c2SHuy Nguyen goto out; 41650b4a3c2SHuy Nguyen 41750b4a3c2SHuy Nguyen memcpy(in, out, sz); 41850b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, local_port, 1); 41950b4a3c2SHuy Nguyen 42050b4a3c2SHuy Nguyen /* Update the pm and prio_x_buff */ 42150b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, pm, 0xFF); 42250b4a3c2SHuy Nguyen 42350b4a3c2SHuy Nguyen prio_x_buff = 0; 42450b4a3c2SHuy Nguyen for (prio = 0; prio < 8; prio++) 42550b4a3c2SHuy Nguyen prio_x_buff |= (buffer[prio] << (4 * prio)); 42650b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff); 42750b4a3c2SHuy Nguyen 42850b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1); 42950b4a3c2SHuy Nguyen 43050b4a3c2SHuy Nguyen out: 43150b4a3c2SHuy Nguyen kfree(in); 43250b4a3c2SHuy Nguyen kfree(out); 43350b4a3c2SHuy Nguyen return err; 43450b4a3c2SHuy Nguyen } 4352095b264SShay Agroskin 4363c19208eSAya Levin enum mlx5e_fec_supported_link_mode { 4373c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_10G_40G, 4383c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_25G, 4393c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_50G, 4403c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_56G, 4413c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_100G, 442b5ede32dSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X, 443b5ede32dSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X, 444b5ede32dSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X, 445b5ede32dSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X, 4463c19208eSAya Levin MLX5E_MAX_FEC_SUPPORTED_LINK_MODE, 4472095b264SShay Agroskin }; 4482095b264SShay Agroskin 449b5ede32dSAya Levin #define MLX5E_FEC_FIRST_50G_PER_LANE_MODE MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X 450b5ede32dSAya Levin 4513c19208eSAya Levin #define MLX5E_FEC_OVERRIDE_ADMIN_POLICY(buf, policy, write, link) \ 4523c19208eSAya Levin do { \ 453b5ede32dSAya Levin u16 *_policy = &(policy); \ 4543c19208eSAya Levin u32 *_buf = buf; \ 4553c19208eSAya Levin \ 4563c19208eSAya Levin if (write) \ 4573c19208eSAya Levin MLX5_SET(pplm_reg, _buf, fec_override_admin_##link, *_policy); \ 4583c19208eSAya Levin else \ 4593c19208eSAya Levin *_policy = MLX5_GET(pplm_reg, _buf, fec_override_admin_##link); \ 4603c19208eSAya Levin } while (0) 4612095b264SShay Agroskin 4622095b264SShay Agroskin /* get/set FEC admin field for a given speed */ 463b5ede32dSAya Levin static int mlx5e_fec_admin_field(u32 *pplm, u16 *fec_policy, bool write, 4643c19208eSAya Levin enum mlx5e_fec_supported_link_mode link_mode) 4652095b264SShay Agroskin { 4663c19208eSAya Levin switch (link_mode) { 4673c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_10G_40G: 4683c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 10g_40g); 4692095b264SShay Agroskin break; 4703c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_25G: 4713c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 25g); 4722095b264SShay Agroskin break; 4733c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_50G: 4743c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 50g); 4752095b264SShay Agroskin break; 4763c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_56G: 4773c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 56g); 4782095b264SShay Agroskin break; 4793c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_100G: 4803c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 100g); 4812095b264SShay Agroskin break; 482b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X: 4837a320c9dSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 50g_1x); 484b5ede32dSAya Levin break; 485b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X: 4867a320c9dSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 100g_2x); 487b5ede32dSAya Levin break; 488b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X: 4897a320c9dSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 200g_4x); 490b5ede32dSAya Levin break; 491b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X: 4927a320c9dSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 400g_8x); 493b5ede32dSAya Levin break; 4942095b264SShay Agroskin default: 4952095b264SShay Agroskin return -EINVAL; 4962095b264SShay Agroskin } 4972095b264SShay Agroskin return 0; 4982095b264SShay Agroskin } 4992095b264SShay Agroskin 5003c19208eSAya Levin #define MLX5E_GET_FEC_OVERRIDE_CAP(buf, link) \ 5013c19208eSAya Levin MLX5_GET(pplm_reg, buf, fec_override_cap_##link) 5023c19208eSAya Levin 5032095b264SShay Agroskin /* returns FEC capabilities for a given speed */ 504b5ede32dSAya Levin static int mlx5e_get_fec_cap_field(u32 *pplm, u16 *fec_cap, 5053c19208eSAya Levin enum mlx5e_fec_supported_link_mode link_mode) 5062095b264SShay Agroskin { 5073c19208eSAya Levin switch (link_mode) { 5083c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_10G_40G: 5093c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 10g_40g); 5102095b264SShay Agroskin break; 5113c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_25G: 5123c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 25g); 5132095b264SShay Agroskin break; 5143c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_50G: 5153c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 50g); 5162095b264SShay Agroskin break; 5173c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_56G: 5183c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 56g); 5192095b264SShay Agroskin break; 5203c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_100G: 5213c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 100g); 5222095b264SShay Agroskin break; 523b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X: 524b5ede32dSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 50g_1x); 525b5ede32dSAya Levin break; 526b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X: 527b5ede32dSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 100g_2x); 528b5ede32dSAya Levin break; 529b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X: 530b5ede32dSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 200g_4x); 531b5ede32dSAya Levin break; 532b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X: 533b5ede32dSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 400g_8x); 534b5ede32dSAya Levin break; 5352095b264SShay Agroskin default: 5362095b264SShay Agroskin return -EINVAL; 5372095b264SShay Agroskin } 5382095b264SShay Agroskin return 0; 5392095b264SShay Agroskin } 5402095b264SShay Agroskin 5412132b71fSAya Levin bool mlx5e_fec_in_caps(struct mlx5_core_dev *dev, int fec_policy) 5422095b264SShay Agroskin { 543b5ede32dSAya Levin bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm); 5442095b264SShay Agroskin u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 5452095b264SShay Agroskin u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 5462095b264SShay Agroskin int sz = MLX5_ST_SZ_BYTES(pplm_reg); 5472095b264SShay Agroskin int err; 5482132b71fSAya Levin int i; 5492095b264SShay Agroskin 550cb39ccc5SSaeed Mahameed if (!MLX5_CAP_GEN(dev, pcam_reg) || !MLX5_CAP_PCAM_REG(dev, pplm)) 551cb39ccc5SSaeed Mahameed return false; 5522095b264SShay Agroskin 5532095b264SShay Agroskin MLX5_SET(pplm_reg, in, local_port, 1); 5542095b264SShay Agroskin err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0); 5552095b264SShay Agroskin if (err) 5562132b71fSAya Levin return false; 5572095b264SShay Agroskin 5583c19208eSAya Levin for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) { 559b5ede32dSAya Levin u16 fec_caps; 560b5ede32dSAya Levin 561b5ede32dSAya Levin if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane) 562b5ede32dSAya Levin break; 5632095b264SShay Agroskin 5643c19208eSAya Levin mlx5e_get_fec_cap_field(out, &fec_caps, i); 5652132b71fSAya Levin if (fec_caps & fec_policy) 5662132b71fSAya Levin return true; 5672132b71fSAya Levin } 5682132b71fSAya Levin return false; 5692095b264SShay Agroskin } 5702095b264SShay Agroskin 5712095b264SShay Agroskin int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active, 572b5ede32dSAya Levin u16 *fec_configured_mode) 5732095b264SShay Agroskin { 574b5ede32dSAya Levin bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm); 5752095b264SShay Agroskin u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 5762095b264SShay Agroskin u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 5772095b264SShay Agroskin int sz = MLX5_ST_SZ_BYTES(pplm_reg); 5782095b264SShay Agroskin int err; 5793c19208eSAya Levin int i; 5802095b264SShay Agroskin 5812095b264SShay Agroskin if (!MLX5_CAP_GEN(dev, pcam_reg)) 5822095b264SShay Agroskin return -EOPNOTSUPP; 5832095b264SShay Agroskin 5842095b264SShay Agroskin if (!MLX5_CAP_PCAM_REG(dev, pplm)) 5852095b264SShay Agroskin return -EOPNOTSUPP; 5862095b264SShay Agroskin 5872095b264SShay Agroskin MLX5_SET(pplm_reg, in, local_port, 1); 5882095b264SShay Agroskin err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0); 5892095b264SShay Agroskin if (err) 5902095b264SShay Agroskin return err; 5912095b264SShay Agroskin 5922095b264SShay Agroskin *fec_mode_active = MLX5_GET(pplm_reg, out, fec_mode_active); 5932095b264SShay Agroskin 5942095b264SShay Agroskin if (!fec_configured_mode) 5953c19208eSAya Levin goto out; 5963c19208eSAya Levin 5973c19208eSAya Levin *fec_configured_mode = 0; 5983c19208eSAya Levin for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) { 599b5ede32dSAya Levin if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane) 600b5ede32dSAya Levin break; 601b5ede32dSAya Levin 6023c19208eSAya Levin mlx5e_fec_admin_field(out, fec_configured_mode, 0, i); 6033c19208eSAya Levin if (*fec_configured_mode != 0) 6043c19208eSAya Levin goto out; 6053c19208eSAya Levin } 6063c19208eSAya Levin out: 6072095b264SShay Agroskin return 0; 6082095b264SShay Agroskin } 6092095b264SShay Agroskin 610b5ede32dSAya Levin int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy) 6112095b264SShay Agroskin { 612b5ede32dSAya Levin bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm); 6132095b264SShay Agroskin u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {}; 6142095b264SShay Agroskin u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {}; 6152095b264SShay Agroskin int sz = MLX5_ST_SZ_BYTES(pplm_reg); 616b5ede32dSAya Levin u16 fec_policy_auto = 0; 6172095b264SShay Agroskin int err; 6182095b264SShay Agroskin int i; 6192095b264SShay Agroskin 6202095b264SShay Agroskin if (!MLX5_CAP_GEN(dev, pcam_reg)) 6212095b264SShay Agroskin return -EOPNOTSUPP; 6222095b264SShay Agroskin 6232095b264SShay Agroskin if (!MLX5_CAP_PCAM_REG(dev, pplm)) 6242095b264SShay Agroskin return -EOPNOTSUPP; 6252095b264SShay Agroskin 626b5ede32dSAya Levin if (fec_policy >= (1 << MLX5E_FEC_LLRS_272_257_1) && !fec_50g_per_lane) 627b5ede32dSAya Levin return -EOPNOTSUPP; 628b5ede32dSAya Levin 6292608a2f8SAya Levin if (fec_policy && !mlx5e_fec_in_caps(dev, fec_policy)) 6302608a2f8SAya Levin return -EOPNOTSUPP; 6312608a2f8SAya Levin 6322095b264SShay Agroskin MLX5_SET(pplm_reg, in, local_port, 1); 6332095b264SShay Agroskin err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0); 6342095b264SShay Agroskin if (err) 6352095b264SShay Agroskin return err; 6362095b264SShay Agroskin 6379cdeaab3SShay Agroskin MLX5_SET(pplm_reg, out, local_port, 1); 6382095b264SShay Agroskin 6393c19208eSAya Levin for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) { 640b5ede32dSAya Levin u16 conf_fec = fec_policy; 641b5ede32dSAya Levin u16 fec_caps = 0; 642b5ede32dSAya Levin 643b5ede32dSAya Levin if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane) 644b5ede32dSAya Levin break; 645b5ede32dSAya Levin 646b5ede32dSAya Levin /* RS fec in ethtool is mapped to MLX5E_FEC_RS_528_514 647b5ede32dSAya Levin * to link modes up to 25G per lane and to 648b5ede32dSAya Levin * MLX5E_FEC_RS_544_514 in the new link modes based on 649b5ede32dSAya Levin * 50 G per lane 650b5ede32dSAya Levin */ 651b5ede32dSAya Levin if (conf_fec == (1 << MLX5E_FEC_RS_528_514) && 652b5ede32dSAya Levin i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE) 653b5ede32dSAya Levin conf_fec = (1 << MLX5E_FEC_RS_544_514); 654b5ede32dSAya Levin 6553c19208eSAya Levin mlx5e_get_fec_cap_field(out, &fec_caps, i); 656b5ede32dSAya Levin 657511aa2aaSAya Levin /* policy supported for link speed */ 658b5ede32dSAya Levin if (fec_caps & conf_fec) 659b5ede32dSAya Levin mlx5e_fec_admin_field(out, &conf_fec, 1, i); 660511aa2aaSAya Levin else 661511aa2aaSAya Levin /* set FEC to auto*/ 6623c19208eSAya Levin mlx5e_fec_admin_field(out, &fec_policy_auto, 1, i); 6632095b264SShay Agroskin } 6642095b264SShay Agroskin 6659cdeaab3SShay Agroskin return mlx5_core_access_reg(dev, out, sz, out, sz, MLX5_REG_PPLM, 0, 1); 6662095b264SShay Agroskin } 667