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
mlx5_port_query_eth_autoneg(struct mlx5_core_dev * dev,u8 * an_status,u8 * an_disable_cap,u8 * an_disable_admin)35bc4e12ffSAya Levin void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
36bc4e12ffSAya Levin u8 *an_disable_cap, u8 *an_disable_admin)
37bc4e12ffSAya Levin {
38bc4e12ffSAya Levin u32 out[MLX5_ST_SZ_DW(ptys_reg)];
39bc4e12ffSAya Levin
40bc4e12ffSAya Levin *an_status = 0;
41bc4e12ffSAya Levin *an_disable_cap = 0;
42bc4e12ffSAya Levin *an_disable_admin = 0;
43bc4e12ffSAya Levin
44bc4e12ffSAya Levin if (mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, 1))
45bc4e12ffSAya Levin return;
46bc4e12ffSAya Levin
47bc4e12ffSAya Levin *an_status = MLX5_GET(ptys_reg, out, an_status);
48bc4e12ffSAya Levin *an_disable_cap = MLX5_GET(ptys_reg, out, an_disable_cap);
49bc4e12ffSAya Levin *an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
50bc4e12ffSAya Levin }
51bc4e12ffSAya Levin
mlx5_port_set_eth_ptys(struct mlx5_core_dev * dev,bool an_disable,u32 proto_admin,bool ext)52bc4e12ffSAya Levin int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
53a08b4ed1SAya Levin u32 proto_admin, bool ext)
54bc4e12ffSAya Levin {
55bc4e12ffSAya Levin u32 out[MLX5_ST_SZ_DW(ptys_reg)];
56bc4e12ffSAya Levin u32 in[MLX5_ST_SZ_DW(ptys_reg)];
57bc4e12ffSAya Levin u8 an_disable_admin;
58bc4e12ffSAya Levin u8 an_disable_cap;
59bc4e12ffSAya Levin u8 an_status;
60bc4e12ffSAya Levin
61bc4e12ffSAya Levin mlx5_port_query_eth_autoneg(dev, &an_status, &an_disable_cap,
62bc4e12ffSAya Levin &an_disable_admin);
63bc4e12ffSAya Levin if (!an_disable_cap && an_disable)
64bc4e12ffSAya Levin return -EPERM;
65bc4e12ffSAya Levin
66bc4e12ffSAya Levin memset(in, 0, sizeof(in));
67bc4e12ffSAya Levin
68bc4e12ffSAya Levin MLX5_SET(ptys_reg, in, local_port, 1);
69bc4e12ffSAya Levin MLX5_SET(ptys_reg, in, an_disable_admin, an_disable);
70bc4e12ffSAya Levin MLX5_SET(ptys_reg, in, proto_mask, MLX5_PTYS_EN);
71a08b4ed1SAya Levin if (ext)
72a08b4ed1SAya Levin MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin);
73a08b4ed1SAya Levin else
74bc4e12ffSAya Levin MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
75bc4e12ffSAya Levin
76bc4e12ffSAya Levin return mlx5_core_access_reg(dev, in, sizeof(in), out,
77bc4e12ffSAya Levin sizeof(out), MLX5_REG_PTYS, 0, 1);
78bc4e12ffSAya Levin }
79bc4e12ffSAya Levin
mlx5e_port_linkspeed(struct mlx5_core_dev * mdev,u32 * speed)802c81bfd5SHuy Nguyen int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
812c81bfd5SHuy Nguyen {
82*028522e2SGal Pressman struct mlx5_port_eth_proto eproto;
834b95840aSAya Levin bool force_legacy = false;
84a08b4ed1SAya Levin bool ext;
852c81bfd5SHuy Nguyen int err;
862c81bfd5SHuy Nguyen
87*028522e2SGal Pressman ext = mlx5_ptys_ext_supported(mdev);
88a08b4ed1SAya Levin err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
892c81bfd5SHuy Nguyen if (err)
90a08b4ed1SAya Levin goto out;
914b95840aSAya Levin if (ext && !eproto.admin) {
924b95840aSAya Levin force_legacy = true;
934b95840aSAya Levin err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto);
944b95840aSAya Levin if (err)
954b95840aSAya Levin goto out;
964b95840aSAya Levin }
97*028522e2SGal Pressman *speed = mlx5_port_ptys2speed(mdev, eproto.oper, force_legacy);
9864e28334SShay Agroskin if (!(*speed))
992c81bfd5SHuy Nguyen err = -EINVAL;
1002c81bfd5SHuy Nguyen
101a08b4ed1SAya Levin out:
1022c81bfd5SHuy Nguyen return err;
1032c81bfd5SHuy Nguyen }
1042c81bfd5SHuy Nguyen
mlx5e_port_query_pbmc(struct mlx5_core_dev * mdev,void * out)10550b4a3c2SHuy Nguyen int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out)
10650b4a3c2SHuy Nguyen {
10750b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
10850b4a3c2SHuy Nguyen void *in;
10950b4a3c2SHuy Nguyen int err;
11050b4a3c2SHuy Nguyen
11150b4a3c2SHuy Nguyen in = kzalloc(sz, GFP_KERNEL);
11250b4a3c2SHuy Nguyen if (!in)
11350b4a3c2SHuy Nguyen return -ENOMEM;
11450b4a3c2SHuy Nguyen
11550b4a3c2SHuy Nguyen MLX5_SET(pbmc_reg, in, local_port, 1);
11650b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0);
11750b4a3c2SHuy Nguyen
11850b4a3c2SHuy Nguyen kfree(in);
11950b4a3c2SHuy Nguyen return err;
12050b4a3c2SHuy Nguyen }
12150b4a3c2SHuy Nguyen
mlx5e_port_set_pbmc(struct mlx5_core_dev * mdev,void * in)12250b4a3c2SHuy Nguyen int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in)
12350b4a3c2SHuy Nguyen {
12450b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
12550b4a3c2SHuy Nguyen void *out;
12650b4a3c2SHuy Nguyen int err;
12750b4a3c2SHuy Nguyen
12850b4a3c2SHuy Nguyen out = kzalloc(sz, GFP_KERNEL);
12950b4a3c2SHuy Nguyen if (!out)
13050b4a3c2SHuy Nguyen return -ENOMEM;
13150b4a3c2SHuy Nguyen
13250b4a3c2SHuy Nguyen MLX5_SET(pbmc_reg, in, local_port, 1);
13350b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1);
13450b4a3c2SHuy Nguyen
13550b4a3c2SHuy Nguyen kfree(out);
13650b4a3c2SHuy Nguyen return err;
13750b4a3c2SHuy Nguyen }
13850b4a3c2SHuy Nguyen
mlx5e_port_query_sbpr(struct mlx5_core_dev * mdev,u32 desc,u8 dir,u8 pool_idx,void * out,int size_out)13911f0996dSMaher Sanalla int mlx5e_port_query_sbpr(struct mlx5_core_dev *mdev, u32 desc, u8 dir,
14011f0996dSMaher Sanalla u8 pool_idx, void *out, int size_out)
14111f0996dSMaher Sanalla {
14211f0996dSMaher Sanalla u32 in[MLX5_ST_SZ_DW(sbpr_reg)] = {};
14311f0996dSMaher Sanalla
14411f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, desc, desc);
14511f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, dir, dir);
14611f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, pool, pool_idx);
14711f0996dSMaher Sanalla
14811f0996dSMaher Sanalla return mlx5_core_access_reg(mdev, in, sizeof(in), out, size_out, MLX5_REG_SBPR, 0, 0);
14911f0996dSMaher Sanalla }
15011f0996dSMaher Sanalla
mlx5e_port_set_sbpr(struct mlx5_core_dev * mdev,u32 desc,u8 dir,u8 pool_idx,u32 infi_size,u32 size)15111f0996dSMaher Sanalla int mlx5e_port_set_sbpr(struct mlx5_core_dev *mdev, u32 desc, u8 dir,
15211f0996dSMaher Sanalla u8 pool_idx, u32 infi_size, u32 size)
15311f0996dSMaher Sanalla {
15411f0996dSMaher Sanalla u32 out[MLX5_ST_SZ_DW(sbpr_reg)] = {};
15511f0996dSMaher Sanalla u32 in[MLX5_ST_SZ_DW(sbpr_reg)] = {};
15611f0996dSMaher Sanalla
15711f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, desc, desc);
15811f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, dir, dir);
15911f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, pool, pool_idx);
16011f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, infi_size, infi_size);
16111f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, size, size);
16211f0996dSMaher Sanalla MLX5_SET(sbpr_reg, in, mode, 1);
16311f0996dSMaher Sanalla
16411f0996dSMaher Sanalla return mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), MLX5_REG_SBPR, 0, 1);
16511f0996dSMaher Sanalla }
16611f0996dSMaher Sanalla
mlx5e_port_query_sbcm(struct mlx5_core_dev * mdev,u32 desc,u8 pg_buff_idx,u8 dir,void * out,int size_out)16711f0996dSMaher Sanalla static int mlx5e_port_query_sbcm(struct mlx5_core_dev *mdev, u32 desc,
16811f0996dSMaher Sanalla u8 pg_buff_idx, u8 dir, void *out,
16911f0996dSMaher Sanalla int size_out)
17011f0996dSMaher Sanalla {
17111f0996dSMaher Sanalla u32 in[MLX5_ST_SZ_DW(sbcm_reg)] = {};
17211f0996dSMaher Sanalla
17311f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, desc, desc);
17411f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, local_port, 1);
17511f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, pg_buff, pg_buff_idx);
17611f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, dir, dir);
17711f0996dSMaher Sanalla
17811f0996dSMaher Sanalla return mlx5_core_access_reg(mdev, in, sizeof(in), out, size_out, MLX5_REG_SBCM, 0, 0);
17911f0996dSMaher Sanalla }
18011f0996dSMaher Sanalla
mlx5e_port_set_sbcm(struct mlx5_core_dev * mdev,u32 desc,u8 pg_buff_idx,u8 dir,u8 infi_size,u32 max_buff,u8 pool_idx)18111f0996dSMaher Sanalla int mlx5e_port_set_sbcm(struct mlx5_core_dev *mdev, u32 desc, u8 pg_buff_idx,
18211f0996dSMaher Sanalla u8 dir, u8 infi_size, u32 max_buff, u8 pool_idx)
18311f0996dSMaher Sanalla {
18411f0996dSMaher Sanalla u32 out[MLX5_ST_SZ_DW(sbcm_reg)] = {};
18511f0996dSMaher Sanalla u32 in[MLX5_ST_SZ_DW(sbcm_reg)] = {};
18611f0996dSMaher Sanalla u32 min_buff;
18711f0996dSMaher Sanalla int err;
18811f0996dSMaher Sanalla u8 exc;
18911f0996dSMaher Sanalla
19011f0996dSMaher Sanalla err = mlx5e_port_query_sbcm(mdev, desc, pg_buff_idx, dir, out,
19111f0996dSMaher Sanalla sizeof(out));
19211f0996dSMaher Sanalla if (err)
19311f0996dSMaher Sanalla return err;
19411f0996dSMaher Sanalla
19511f0996dSMaher Sanalla exc = MLX5_GET(sbcm_reg, out, exc);
19611f0996dSMaher Sanalla min_buff = MLX5_GET(sbcm_reg, out, min_buff);
19711f0996dSMaher Sanalla
19811f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, desc, desc);
19911f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, local_port, 1);
20011f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, pg_buff, pg_buff_idx);
20111f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, dir, dir);
20211f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, exc, exc);
20311f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, min_buff, min_buff);
20411f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, infi_max, infi_size);
20511f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, max_buff, max_buff);
20611f0996dSMaher Sanalla MLX5_SET(sbcm_reg, in, pool, pool_idx);
20711f0996dSMaher Sanalla
20811f0996dSMaher Sanalla return mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out), MLX5_REG_SBCM, 0, 1);
20911f0996dSMaher Sanalla }
21011f0996dSMaher Sanalla
21150b4a3c2SHuy Nguyen /* buffer[i]: buffer that priority i mapped to */
mlx5e_port_query_priority2buffer(struct mlx5_core_dev * mdev,u8 * buffer)21250b4a3c2SHuy Nguyen int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
21350b4a3c2SHuy Nguyen {
21450b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pptb_reg);
21550b4a3c2SHuy Nguyen u32 prio_x_buff;
21650b4a3c2SHuy Nguyen void *out;
21750b4a3c2SHuy Nguyen void *in;
21850b4a3c2SHuy Nguyen int prio;
21950b4a3c2SHuy Nguyen int err;
22050b4a3c2SHuy Nguyen
22150b4a3c2SHuy Nguyen in = kzalloc(sz, GFP_KERNEL);
22250b4a3c2SHuy Nguyen out = kzalloc(sz, GFP_KERNEL);
22350b4a3c2SHuy Nguyen if (!in || !out) {
22450b4a3c2SHuy Nguyen err = -ENOMEM;
22550b4a3c2SHuy Nguyen goto out;
22650b4a3c2SHuy Nguyen }
22750b4a3c2SHuy Nguyen
22850b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, local_port, 1);
22950b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
23050b4a3c2SHuy Nguyen if (err)
23150b4a3c2SHuy Nguyen goto out;
23250b4a3c2SHuy Nguyen
23350b4a3c2SHuy Nguyen prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff);
23450b4a3c2SHuy Nguyen for (prio = 0; prio < 8; prio++) {
23550b4a3c2SHuy Nguyen buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF;
23650b4a3c2SHuy Nguyen mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]);
23750b4a3c2SHuy Nguyen }
23850b4a3c2SHuy Nguyen out:
23950b4a3c2SHuy Nguyen kfree(in);
24050b4a3c2SHuy Nguyen kfree(out);
24150b4a3c2SHuy Nguyen return err;
24250b4a3c2SHuy Nguyen }
24350b4a3c2SHuy Nguyen
mlx5e_port_set_priority2buffer(struct mlx5_core_dev * mdev,u8 * buffer)24450b4a3c2SHuy Nguyen int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
24550b4a3c2SHuy Nguyen {
24650b4a3c2SHuy Nguyen int sz = MLX5_ST_SZ_BYTES(pptb_reg);
24750b4a3c2SHuy Nguyen u32 prio_x_buff;
24850b4a3c2SHuy Nguyen void *out;
24950b4a3c2SHuy Nguyen void *in;
25050b4a3c2SHuy Nguyen int prio;
25150b4a3c2SHuy Nguyen int err;
25250b4a3c2SHuy Nguyen
25350b4a3c2SHuy Nguyen in = kzalloc(sz, GFP_KERNEL);
25450b4a3c2SHuy Nguyen out = kzalloc(sz, GFP_KERNEL);
25550b4a3c2SHuy Nguyen if (!in || !out) {
25650b4a3c2SHuy Nguyen err = -ENOMEM;
25750b4a3c2SHuy Nguyen goto out;
25850b4a3c2SHuy Nguyen }
25950b4a3c2SHuy Nguyen
26050b4a3c2SHuy Nguyen /* First query the pptb register */
26150b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, local_port, 1);
26250b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
26350b4a3c2SHuy Nguyen if (err)
26450b4a3c2SHuy Nguyen goto out;
26550b4a3c2SHuy Nguyen
26650b4a3c2SHuy Nguyen memcpy(in, out, sz);
26750b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, local_port, 1);
26850b4a3c2SHuy Nguyen
26950b4a3c2SHuy Nguyen /* Update the pm and prio_x_buff */
27050b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, pm, 0xFF);
27150b4a3c2SHuy Nguyen
27250b4a3c2SHuy Nguyen prio_x_buff = 0;
27350b4a3c2SHuy Nguyen for (prio = 0; prio < 8; prio++)
27450b4a3c2SHuy Nguyen prio_x_buff |= (buffer[prio] << (4 * prio));
27550b4a3c2SHuy Nguyen MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff);
27650b4a3c2SHuy Nguyen
27750b4a3c2SHuy Nguyen err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1);
27850b4a3c2SHuy Nguyen
27950b4a3c2SHuy Nguyen out:
28050b4a3c2SHuy Nguyen kfree(in);
28150b4a3c2SHuy Nguyen kfree(out);
28250b4a3c2SHuy Nguyen return err;
28350b4a3c2SHuy Nguyen }
2842095b264SShay Agroskin
2853c19208eSAya Levin enum mlx5e_fec_supported_link_mode {
2863c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_10G_40G,
2873c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_25G,
2883c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_50G,
2893c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_56G,
2903c19208eSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODES_100G,
291b5ede32dSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X,
292b5ede32dSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X,
293b5ede32dSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X,
294b5ede32dSAya Levin MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X,
2953c19208eSAya Levin MLX5E_MAX_FEC_SUPPORTED_LINK_MODE,
2962095b264SShay Agroskin };
2972095b264SShay Agroskin
298b5ede32dSAya Levin #define MLX5E_FEC_FIRST_50G_PER_LANE_MODE MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X
299b5ede32dSAya Levin
3003c19208eSAya Levin #define MLX5E_FEC_OVERRIDE_ADMIN_POLICY(buf, policy, write, link) \
3013c19208eSAya Levin do { \
302b5ede32dSAya Levin u16 *_policy = &(policy); \
3033c19208eSAya Levin u32 *_buf = buf; \
3043c19208eSAya Levin \
3053c19208eSAya Levin if (write) \
3063c19208eSAya Levin MLX5_SET(pplm_reg, _buf, fec_override_admin_##link, *_policy); \
3073c19208eSAya Levin else \
3083c19208eSAya Levin *_policy = MLX5_GET(pplm_reg, _buf, fec_override_admin_##link); \
3093c19208eSAya Levin } while (0)
3102095b264SShay Agroskin
3112095b264SShay Agroskin /* get/set FEC admin field for a given speed */
mlx5e_fec_admin_field(u32 * pplm,u16 * fec_policy,bool write,enum mlx5e_fec_supported_link_mode link_mode)312b5ede32dSAya Levin static int mlx5e_fec_admin_field(u32 *pplm, u16 *fec_policy, bool write,
3133c19208eSAya Levin enum mlx5e_fec_supported_link_mode link_mode)
3142095b264SShay Agroskin {
3153c19208eSAya Levin switch (link_mode) {
3163c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_10G_40G:
3173c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 10g_40g);
3182095b264SShay Agroskin break;
3193c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_25G:
3203c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 25g);
3212095b264SShay Agroskin break;
3223c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_50G:
3233c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 50g);
3242095b264SShay Agroskin break;
3253c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_56G:
3263c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 56g);
3272095b264SShay Agroskin break;
3283c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_100G:
3293c19208eSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 100g);
3302095b264SShay Agroskin break;
331b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X:
3327a320c9dSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 50g_1x);
333b5ede32dSAya Levin break;
334b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X:
3357a320c9dSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 100g_2x);
336b5ede32dSAya Levin break;
337b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X:
3387a320c9dSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 200g_4x);
339b5ede32dSAya Levin break;
340b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X:
3417a320c9dSAya Levin MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 400g_8x);
342b5ede32dSAya Levin break;
3432095b264SShay Agroskin default:
3442095b264SShay Agroskin return -EINVAL;
3452095b264SShay Agroskin }
3462095b264SShay Agroskin return 0;
3472095b264SShay Agroskin }
3482095b264SShay Agroskin
3493c19208eSAya Levin #define MLX5E_GET_FEC_OVERRIDE_CAP(buf, link) \
3503c19208eSAya Levin MLX5_GET(pplm_reg, buf, fec_override_cap_##link)
3513c19208eSAya Levin
3522095b264SShay Agroskin /* returns FEC capabilities for a given speed */
mlx5e_get_fec_cap_field(u32 * pplm,u16 * fec_cap,enum mlx5e_fec_supported_link_mode link_mode)353b5ede32dSAya Levin static int mlx5e_get_fec_cap_field(u32 *pplm, u16 *fec_cap,
3543c19208eSAya Levin enum mlx5e_fec_supported_link_mode link_mode)
3552095b264SShay Agroskin {
3563c19208eSAya Levin switch (link_mode) {
3573c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_10G_40G:
3583c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 10g_40g);
3592095b264SShay Agroskin break;
3603c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_25G:
3613c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 25g);
3622095b264SShay Agroskin break;
3633c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_50G:
3643c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 50g);
3652095b264SShay Agroskin break;
3663c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_56G:
3673c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 56g);
3682095b264SShay Agroskin break;
3693c19208eSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODES_100G:
3703c19208eSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 100g);
3712095b264SShay Agroskin break;
372b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X:
373b5ede32dSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 50g_1x);
374b5ede32dSAya Levin break;
375b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X:
376b5ede32dSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 100g_2x);
377b5ede32dSAya Levin break;
378b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X:
379b5ede32dSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 200g_4x);
380b5ede32dSAya Levin break;
381b5ede32dSAya Levin case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X:
382b5ede32dSAya Levin *fec_cap = MLX5E_GET_FEC_OVERRIDE_CAP(pplm, 400g_8x);
383b5ede32dSAya Levin break;
3842095b264SShay Agroskin default:
3852095b264SShay Agroskin return -EINVAL;
3862095b264SShay Agroskin }
3872095b264SShay Agroskin return 0;
3882095b264SShay Agroskin }
3892095b264SShay Agroskin
mlx5e_fec_in_caps(struct mlx5_core_dev * dev,int fec_policy)3902132b71fSAya Levin bool mlx5e_fec_in_caps(struct mlx5_core_dev *dev, int fec_policy)
3912095b264SShay Agroskin {
392b5ede32dSAya Levin bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm);
3932095b264SShay Agroskin u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
3942095b264SShay Agroskin u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
3952095b264SShay Agroskin int sz = MLX5_ST_SZ_BYTES(pplm_reg);
3962095b264SShay Agroskin int err;
3972132b71fSAya Levin int i;
3982095b264SShay Agroskin
399cb39ccc5SSaeed Mahameed if (!MLX5_CAP_GEN(dev, pcam_reg) || !MLX5_CAP_PCAM_REG(dev, pplm))
400cb39ccc5SSaeed Mahameed return false;
4012095b264SShay Agroskin
4022095b264SShay Agroskin MLX5_SET(pplm_reg, in, local_port, 1);
4032095b264SShay Agroskin err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
4042095b264SShay Agroskin if (err)
4052132b71fSAya Levin return false;
4062095b264SShay Agroskin
4073c19208eSAya Levin for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) {
408b5ede32dSAya Levin u16 fec_caps;
409b5ede32dSAya Levin
410b5ede32dSAya Levin if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane)
411b5ede32dSAya Levin break;
4122095b264SShay Agroskin
4133c19208eSAya Levin mlx5e_get_fec_cap_field(out, &fec_caps, i);
4142132b71fSAya Levin if (fec_caps & fec_policy)
4152132b71fSAya Levin return true;
4162132b71fSAya Levin }
4172132b71fSAya Levin return false;
4182095b264SShay Agroskin }
4192095b264SShay Agroskin
mlx5e_get_fec_mode(struct mlx5_core_dev * dev,u32 * fec_mode_active,u16 * fec_configured_mode)4202095b264SShay Agroskin int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,
421b5ede32dSAya Levin u16 *fec_configured_mode)
4222095b264SShay Agroskin {
423b5ede32dSAya Levin bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm);
4242095b264SShay Agroskin u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
4252095b264SShay Agroskin u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
4262095b264SShay Agroskin int sz = MLX5_ST_SZ_BYTES(pplm_reg);
4272095b264SShay Agroskin int err;
4283c19208eSAya Levin int i;
4292095b264SShay Agroskin
4302095b264SShay Agroskin if (!MLX5_CAP_GEN(dev, pcam_reg))
4312095b264SShay Agroskin return -EOPNOTSUPP;
4322095b264SShay Agroskin
4332095b264SShay Agroskin if (!MLX5_CAP_PCAM_REG(dev, pplm))
4342095b264SShay Agroskin return -EOPNOTSUPP;
4352095b264SShay Agroskin
4362095b264SShay Agroskin MLX5_SET(pplm_reg, in, local_port, 1);
4372095b264SShay Agroskin err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
4382095b264SShay Agroskin if (err)
4392095b264SShay Agroskin return err;
4402095b264SShay Agroskin
4412095b264SShay Agroskin *fec_mode_active = MLX5_GET(pplm_reg, out, fec_mode_active);
4422095b264SShay Agroskin
4432095b264SShay Agroskin if (!fec_configured_mode)
4443c19208eSAya Levin goto out;
4453c19208eSAya Levin
4463c19208eSAya Levin *fec_configured_mode = 0;
4473c19208eSAya Levin for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) {
448b5ede32dSAya Levin if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane)
449b5ede32dSAya Levin break;
450b5ede32dSAya Levin
4513c19208eSAya Levin mlx5e_fec_admin_field(out, fec_configured_mode, 0, i);
4523c19208eSAya Levin if (*fec_configured_mode != 0)
4533c19208eSAya Levin goto out;
4543c19208eSAya Levin }
4553c19208eSAya Levin out:
4562095b264SShay Agroskin return 0;
4572095b264SShay Agroskin }
4582095b264SShay Agroskin
mlx5e_set_fec_mode(struct mlx5_core_dev * dev,u16 fec_policy)459b5ede32dSAya Levin int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u16 fec_policy)
4602095b264SShay Agroskin {
461b5ede32dSAya Levin bool fec_50g_per_lane = MLX5_CAP_PCAM_FEATURE(dev, fec_50G_per_lane_in_pplm);
4622095b264SShay Agroskin u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
4632095b264SShay Agroskin u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
4642095b264SShay Agroskin int sz = MLX5_ST_SZ_BYTES(pplm_reg);
465b5ede32dSAya Levin u16 fec_policy_auto = 0;
4662095b264SShay Agroskin int err;
4672095b264SShay Agroskin int i;
4682095b264SShay Agroskin
4692095b264SShay Agroskin if (!MLX5_CAP_GEN(dev, pcam_reg))
4702095b264SShay Agroskin return -EOPNOTSUPP;
4712095b264SShay Agroskin
4722095b264SShay Agroskin if (!MLX5_CAP_PCAM_REG(dev, pplm))
4732095b264SShay Agroskin return -EOPNOTSUPP;
4742095b264SShay Agroskin
475b5ede32dSAya Levin if (fec_policy >= (1 << MLX5E_FEC_LLRS_272_257_1) && !fec_50g_per_lane)
476b5ede32dSAya Levin return -EOPNOTSUPP;
477b5ede32dSAya Levin
4782608a2f8SAya Levin if (fec_policy && !mlx5e_fec_in_caps(dev, fec_policy))
4792608a2f8SAya Levin return -EOPNOTSUPP;
4802608a2f8SAya Levin
4812095b264SShay Agroskin MLX5_SET(pplm_reg, in, local_port, 1);
4822095b264SShay Agroskin err = mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 0);
4832095b264SShay Agroskin if (err)
4842095b264SShay Agroskin return err;
4852095b264SShay Agroskin
4869cdeaab3SShay Agroskin MLX5_SET(pplm_reg, out, local_port, 1);
4872095b264SShay Agroskin
4883c19208eSAya Levin for (i = 0; i < MLX5E_MAX_FEC_SUPPORTED_LINK_MODE; i++) {
489b5ede32dSAya Levin u16 conf_fec = fec_policy;
490b5ede32dSAya Levin u16 fec_caps = 0;
491b5ede32dSAya Levin
492b5ede32dSAya Levin if (i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE && !fec_50g_per_lane)
493b5ede32dSAya Levin break;
494b5ede32dSAya Levin
495b5ede32dSAya Levin /* RS fec in ethtool is mapped to MLX5E_FEC_RS_528_514
496b5ede32dSAya Levin * to link modes up to 25G per lane and to
497b5ede32dSAya Levin * MLX5E_FEC_RS_544_514 in the new link modes based on
498b5ede32dSAya Levin * 50 G per lane
499b5ede32dSAya Levin */
500b5ede32dSAya Levin if (conf_fec == (1 << MLX5E_FEC_RS_528_514) &&
501b5ede32dSAya Levin i >= MLX5E_FEC_FIRST_50G_PER_LANE_MODE)
502b5ede32dSAya Levin conf_fec = (1 << MLX5E_FEC_RS_544_514);
503b5ede32dSAya Levin
5043c19208eSAya Levin mlx5e_get_fec_cap_field(out, &fec_caps, i);
505b5ede32dSAya Levin
506511aa2aaSAya Levin /* policy supported for link speed */
507b5ede32dSAya Levin if (fec_caps & conf_fec)
508b5ede32dSAya Levin mlx5e_fec_admin_field(out, &conf_fec, 1, i);
509511aa2aaSAya Levin else
510511aa2aaSAya Levin /* set FEC to auto*/
5113c19208eSAya Levin mlx5e_fec_admin_field(out, &fec_policy_auto, 1, i);
5122095b264SShay Agroskin }
5132095b264SShay Agroskin
5149cdeaab3SShay Agroskin return mlx5_core_access_reg(dev, out, sz, out, sz, MLX5_REG_PPLM, 0, 1);
5152095b264SShay Agroskin }
516