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

Add firmware command interface to read and write PPTB and PBMC
registers.

PPTB register enables mappings priority to a specific receive buffer.

PBMC registers enables changing the receive buffer's configuration such
as buffer size, xon/xoff thresholds, buffer's lossy property and
buffer's shared property.

Signed-off-by: Huy Nguyen <h...@mellanox.com>
Signed-off-by: Saeed Mahameed <sae...@mellanox.com>
---
 .../net/ethernet/mellanox/mlx5/core/en/port.c | 108 ++++++++++++++++++
 .../net/ethernet/mellanox/mlx5/core/en/port.h |   5 +
 include/linux/mlx5/driver.h                   |   2 +
 include/linux/mlx5/mlx5_ifc.h                 |  35 ++++++
 4 files changed, 150 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
index 9f04542f3661..24e3b564964f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
@@ -127,3 +127,111 @@ u32 mlx5e_port_speed2linkmodes(u32 speed)
 
        return link_modes;
 }
+
+int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out)
+{
+       int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
+       void *in;
+       int err;
+
+       in = kzalloc(sz, GFP_KERNEL);
+       if (!in)
+               return -ENOMEM;
+
+       MLX5_SET(pbmc_reg, in, local_port, 1);
+       err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 0);
+
+       kfree(in);
+       return err;
+}
+
+int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in)
+{
+       int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
+       void *out;
+       int err;
+
+       out = kzalloc(sz, GFP_KERNEL);
+       if (!out)
+               return -ENOMEM;
+
+       MLX5_SET(pbmc_reg, in, local_port, 1);
+       err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PBMC, 0, 1);
+
+       kfree(out);
+       return err;
+}
+
+/* buffer[i]: buffer that priority i mapped to */
+int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
+{
+       int sz = MLX5_ST_SZ_BYTES(pptb_reg);
+       u32 prio_x_buff;
+       void *out;
+       void *in;
+       int prio;
+       int err;
+
+       in = kzalloc(sz, GFP_KERNEL);
+       out = kzalloc(sz, GFP_KERNEL);
+       if (!in || !out) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       MLX5_SET(pptb_reg, in, local_port, 1);
+       err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
+       if (err)
+               goto out;
+
+       prio_x_buff = MLX5_GET(pptb_reg, out, prio_x_buff);
+       for (prio = 0; prio < 8; prio++) {
+               buffer[prio] = (u8)(prio_x_buff >> (4 * prio)) & 0xF;
+               mlx5_core_dbg(mdev, "prio %d, buffer %d\n", prio, buffer[prio]);
+       }
+out:
+       kfree(in);
+       kfree(out);
+       return err;
+}
+
+int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer)
+{
+       int sz = MLX5_ST_SZ_BYTES(pptb_reg);
+       u32 prio_x_buff;
+       void *out;
+       void *in;
+       int prio;
+       int err;
+
+       in = kzalloc(sz, GFP_KERNEL);
+       out = kzalloc(sz, GFP_KERNEL);
+       if (!in || !out) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* First query the pptb register */
+       MLX5_SET(pptb_reg, in, local_port, 1);
+       err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 0);
+       if (err)
+               goto out;
+
+       memcpy(in, out, sz);
+       MLX5_SET(pptb_reg, in, local_port, 1);
+
+       /* Update the pm and prio_x_buff */
+       MLX5_SET(pptb_reg, in, pm, 0xFF);
+
+       prio_x_buff = 0;
+       for (prio = 0; prio < 8; prio++)
+               prio_x_buff |= (buffer[prio] << (4 * prio));
+       MLX5_SET(pptb_reg, in, prio_x_buff, prio_x_buff);
+
+       err = mlx5_core_access_reg(mdev, in, sz, out, sz, MLX5_REG_PPTB, 0, 1);
+
+out:
+       kfree(in);
+       kfree(out);
+       return err;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h 
b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
index 7aae38e98a65..f8cbd8194179 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
@@ -40,4 +40,9 @@ u32 mlx5e_port_ptys2speed(u32 eth_proto_oper);
 int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
 int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
 u32 mlx5e_port_speed2linkmodes(u32 speed);
+
+int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
+int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
+int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);
+int mlx5e_port_set_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);
 #endif
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index 2a156c5dfadd..395fc1a9e378 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -124,6 +124,8 @@ enum {
        MLX5_REG_PAOS            = 0x5006,
        MLX5_REG_PFCC            = 0x5007,
        MLX5_REG_PPCNT           = 0x5008,
+       MLX5_REG_PPTB            = 0x500b,
+       MLX5_REG_PBMC            = 0x500c,
        MLX5_REG_PMAOS           = 0x5012,
        MLX5_REG_PUDE            = 0x5009,
        MLX5_REG_PMPE            = 0x5010,
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index f687989d336b..edbddeaacc88 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -8788,6 +8788,41 @@ struct mlx5_ifc_qpts_reg_bits {
        u8         trust_state[0x3];
 };
 
+struct mlx5_ifc_pptb_reg_bits {
+       u8         reserved_at_0[0x2];
+       u8         mm[0x2];
+       u8         reserved_at_4[0x4];
+       u8         local_port[0x8];
+       u8         reserved_at_10[0x6];
+       u8         cm[0x1];
+       u8         um[0x1];
+       u8         pm[0x8];
+
+       u8         prio_x_buff[0x20];
+
+       u8         pm_msb[0x8];
+       u8         reserved_at_48[0x10];
+       u8         ctrl_buff[0x4];
+       u8         untagged_buff[0x4];
+};
+
+struct mlx5_ifc_pbmc_reg_bits {
+       u8         reserved_at_0[0x8];
+       u8         local_port[0x8];
+       u8         reserved_at_10[0x10];
+
+       u8         xoff_timer_value[0x10];
+       u8         xoff_refresh[0x10];
+
+       u8         reserved_at_40[0x9];
+       u8         fullness_threshold[0x7];
+       u8         port_buffer_size[0x10];
+
+       struct mlx5_ifc_bufferx_reg_bits buffer[10];
+
+       u8         reserved_at_2e0[0x40];
+};
+
 struct mlx5_ifc_qtct_reg_bits {
        u8         reserved_at_0[0x8];
        u8         port_number[0x8];
-- 
2.17.0

Reply via email to