From: Huy Nguyen <h...@mellanox.com>

The QPTS register allows changing the priority trust state between pcp and
dscp. Add support to get/set trust state from device. When the port is
in pcp/dscp trust state, packet is routed by hardware to matching priority
based on its pcp/dscp value respectively.

The QPDPM register allow channing the dscp to priority mapping. Add support
to get/set dscp to priority mapping from device.
Note that to change a dscp mapping, the "e" bit of this dscp structure
must be set in the QPDPM firmware command.

Signed-off-by: Huy Nguyen <h...@mellanox.com>
Reviewed-by: Parav Pandit <pa...@mellanox.com>
Signed-off-by: Saeed Mahameed <sae...@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/port.c | 99 ++++++++++++++++++++++++++
 include/linux/mlx5/driver.h                    |  7 ++
 include/linux/mlx5/mlx5_ifc.h                  | 20 ++++++
 include/linux/mlx5/port.h                      |  5 ++
 4 files changed, 131 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c 
b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index b6553be841f9..c37d00cd472a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -971,3 +971,102 @@ int mlx5_set_mtppse(struct mlx5_core_dev *mdev, u8 pin, 
u8 arm, u8 mode)
        return mlx5_core_access_reg(mdev, in, sizeof(in), out,
                                    sizeof(out), MLX5_REG_MTPPSE, 0, 1);
 }
+
+int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state)
+{
+       u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
+       u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
+       int err;
+
+       MLX5_SET(qpts_reg, in, local_port, 1);
+       MLX5_SET(qpts_reg, in, trust_state, trust_state);
+
+       err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
+                                  sizeof(out), MLX5_REG_QPTS, 0, 1);
+       return err;
+}
+
+int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state)
+{
+       u32 out[MLX5_ST_SZ_DW(qpts_reg)] = {};
+       u32 in[MLX5_ST_SZ_DW(qpts_reg)] = {};
+       int err;
+
+       MLX5_SET(qpts_reg, in, local_port, 1);
+
+       err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
+                                  sizeof(out), MLX5_REG_QPTS, 0, 0);
+       if (!err)
+               *trust_state = MLX5_GET(qpts_reg, out, trust_state);
+
+       return err;
+}
+
+int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio)
+{
+       int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
+       void *qpdpm_dscp;
+       void *out;
+       void *in;
+       int err;
+
+       in = kzalloc(sz, GFP_KERNEL);
+       out = kzalloc(sz, GFP_KERNEL);
+       if (!in || !out) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       MLX5_SET(qpdpm_reg, in, local_port, 1);
+       err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
+       if (err)
+               goto out;
+
+       memcpy(in, out, sz);
+       MLX5_SET(qpdpm_reg, in, local_port, 1);
+
+       /* Update the corresponding dscp entry */
+       qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, in, dscp[dscp]);
+       MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, prio, prio);
+       MLX5_SET16(qpdpm_dscp_reg, qpdpm_dscp, e, 1);
+       err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 1);
+
+out:
+       kfree(in);
+       kfree(out);
+       return err;
+}
+
+/* dscp2prio[i]: priority that dscp i mapped to */
+#define MLX5E_SUPPORTED_DSCP 64
+int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio)
+{
+       int sz = MLX5_ST_SZ_BYTES(qpdpm_reg);
+       void *qpdpm_dscp;
+       void *out;
+       void *in;
+       int err;
+       int i;
+
+       in = kzalloc(sz, GFP_KERNEL);
+       out = kzalloc(sz, GFP_KERNEL);
+       if (!in || !out) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       MLX5_SET(qpdpm_reg, in, local_port, 1);
+       err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_QPDPM, 0, 0);
+       if (err)
+               goto out;
+
+       for (i = 0; i < (MLX5E_SUPPORTED_DSCP); i++) {
+               qpdpm_dscp = MLX5_ADDR_OF(qpdpm_reg, out, dscp[i]);
+               dscp2prio[i] = MLX5_GET16(qpdpm_dscp_reg, qpdpm_dscp, prio);
+       }
+
+out:
+       kfree(in);
+       kfree(out);
+       return err;
+}
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index ed5be52282ea..a886b51511ab 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -107,8 +107,10 @@ enum {
 };
 
 enum {
+       MLX5_REG_QPTS            = 0x4002,
        MLX5_REG_QETCR           = 0x4005,
        MLX5_REG_QTCT            = 0x400a,
+       MLX5_REG_QPDPM           = 0x4013,
        MLX5_REG_QCAM            = 0x4019,
        MLX5_REG_DCBX_PARAM      = 0x4020,
        MLX5_REG_DCBX_APP        = 0x4021,
@@ -142,6 +144,11 @@ enum {
        MLX5_REG_MCAM            = 0x907f,
 };
 
+enum mlx5_qpts_trust_state {
+       MLX5_QPTS_TRUST_PCP  = 1,
+       MLX5_QPTS_TRUST_DSCP = 2,
+};
+
 enum mlx5_dcbx_oper_mode {
        MLX5E_DCBX_PARAM_VER_OPER_HOST  = 0x0,
        MLX5E_DCBX_PARAM_VER_OPER_AUTO  = 0x3,
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index f127c5b310c5..3e5363f760dd 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -8578,6 +8578,26 @@ struct mlx5_ifc_qetc_reg_bits {
        struct mlx5_ifc_ets_global_config_reg_bits global_configuration;
 };
 
+struct mlx5_ifc_qpdpm_dscp_reg_bits {
+       u8         e[0x1];
+       u8         reserved_at_01[0x0b];
+       u8         prio[0x04];
+};
+
+struct mlx5_ifc_qpdpm_reg_bits {
+       u8                                     reserved_at_0[0x8];
+       u8                                     local_port[0x8];
+       u8                                     reserved_at_10[0x10];
+       struct mlx5_ifc_qpdpm_dscp_reg_bits    dscp[64];
+};
+
+struct mlx5_ifc_qpts_reg_bits {
+       u8         reserved_at_0[0x8];
+       u8         local_port[0x8];
+       u8         reserved_at_10[0x2d];
+       u8         trust_state[0x3];
+};
+
 struct mlx5_ifc_qtct_reg_bits {
        u8         reserved_at_0[0x8];
        u8         port_number[0x8];
diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h
index c59af8ab753a..035f0d4dc9fe 100644
--- a/include/linux/mlx5/port.h
+++ b/include/linux/mlx5/port.h
@@ -179,4 +179,9 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
 
 int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out);
 int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in);
+
+int mlx5_set_trust_state(struct mlx5_core_dev *mdev, u8 trust_state);
+int mlx5_query_trust_state(struct mlx5_core_dev *mdev, u8 *trust_state);
+int mlx5_set_dscp2prio(struct mlx5_core_dev *mdev, u8 dscp, u8 prio);
+int mlx5_query_dscp2prio(struct mlx5_core_dev *mdev, u8 *dscp2prio);
 #endif /* __MLX5_PORT_H__ */
-- 
2.14.2

Reply via email to