net/mlx5e: Fix port buffers cell size value
authorEran Ben Elisha <eranbe@mellanox.com>
Mon, 22 Jun 2020 06:03:31 +0000 (09:03 +0300)
committerSaeed Mahameed <saeedm@mellanox.com>
Fri, 10 Jul 2020 02:27:07 +0000 (19:27 -0700)
Device unit for port buffers size, xoff_threshold and xon_threshold is
cells. Fix a bug in driver where cell unit size was hard-coded to
128 bytes. This hard-coded value is buggy, as it is wrong for some hardware
versions.

Driver to read cell size from SBCAM register and translate bytes to cell
units accordingly.

In order to fix the bug, this patch exposes SBCAM (Shared buffer
capabilities mask) layout and defines.

If SBCAM.cap_cell_size is valid, use it for all bytes to cells
calculations. If not valid, fallback to 128.

Cell size do not change on the fly per device. Instead of issuing SBCAM
access reg command every time such translation is needed, cache it in
mlx5e_dcbx as part of mlx5e_dcbnl_initialize(). Pass dcbx.port_buff_cell_sz
as a param to every function that needs bytes to cells translation.

While fixing the bug, move MLX5E_BUFFER_CELL_SHIFT macro to
en_dcbnl.c, as it is only used by that file.

Fixes: 0696d60853d5 ("net/mlx5e: Receive buffer configuration")
Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Reviewed-by: Huy Nguyen <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/en/dcbnl.h
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc.h

index 7be6b2d..9976de8 100644 (file)
@@ -29,6 +29,7 @@ struct mlx5e_dcbx {
        bool                       manual_buffer;
        u32                        cable_len;
        u32                        xoff;
+       u16                        port_buff_cell_sz;
 };
 
 #define MLX5E_MAX_DSCP (64)
index ae99fac..673f1c8 100644 (file)
@@ -34,6 +34,7 @@
 int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
                            struct mlx5e_port_buffer *port_buffer)
 {
+       u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz;
        struct mlx5_core_dev *mdev = priv->mdev;
        int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
        u32 total_used = 0;
@@ -57,11 +58,11 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
                port_buffer->buffer[i].epsb =
                        MLX5_GET(bufferx_reg, buffer, epsb);
                port_buffer->buffer[i].size =
-                       MLX5_GET(bufferx_reg, buffer, size) << MLX5E_BUFFER_CELL_SHIFT;
+                       MLX5_GET(bufferx_reg, buffer, size) * port_buff_cell_sz;
                port_buffer->buffer[i].xon =
-                       MLX5_GET(bufferx_reg, buffer, xon_threshold) << MLX5E_BUFFER_CELL_SHIFT;
+                       MLX5_GET(bufferx_reg, buffer, xon_threshold) * port_buff_cell_sz;
                port_buffer->buffer[i].xoff =
-                       MLX5_GET(bufferx_reg, buffer, xoff_threshold) << MLX5E_BUFFER_CELL_SHIFT;
+                       MLX5_GET(bufferx_reg, buffer, xoff_threshold) * port_buff_cell_sz;
                total_used += port_buffer->buffer[i].size;
 
                mlx5e_dbg(HW, priv, "buffer %d: size=%d, xon=%d, xoff=%d, epsb=%d, lossy=%d\n", i,
@@ -73,7 +74,7 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv,
        }
 
        port_buffer->port_buffer_size =
-               MLX5_GET(pbmc_reg, out, port_buffer_size) << MLX5E_BUFFER_CELL_SHIFT;
+               MLX5_GET(pbmc_reg, out, port_buffer_size) * port_buff_cell_sz;
        port_buffer->spare_buffer_size =
                port_buffer->port_buffer_size - total_used;
 
@@ -88,9 +89,9 @@ out:
 static int port_set_buffer(struct mlx5e_priv *priv,
                           struct mlx5e_port_buffer *port_buffer)
 {
+       u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz;
        struct mlx5_core_dev *mdev = priv->mdev;
        int sz = MLX5_ST_SZ_BYTES(pbmc_reg);
-       void *buffer;
        void *in;
        int err;
        int i;
@@ -104,16 +105,18 @@ static int port_set_buffer(struct mlx5e_priv *priv,
                goto out;
 
        for (i = 0; i < MLX5E_MAX_BUFFER; i++) {
-               buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]);
-
-               MLX5_SET(bufferx_reg, buffer, size,
-                        port_buffer->buffer[i].size >> MLX5E_BUFFER_CELL_SHIFT);
-               MLX5_SET(bufferx_reg, buffer, lossy,
-                        port_buffer->buffer[i].lossy);
-               MLX5_SET(bufferx_reg, buffer, xoff_threshold,
-                        port_buffer->buffer[i].xoff >> MLX5E_BUFFER_CELL_SHIFT);
-               MLX5_SET(bufferx_reg, buffer, xon_threshold,
-                        port_buffer->buffer[i].xon >> MLX5E_BUFFER_CELL_SHIFT);
+               void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]);
+               u64 size = port_buffer->buffer[i].size;
+               u64 xoff = port_buffer->buffer[i].xoff;
+               u64 xon = port_buffer->buffer[i].xon;
+
+               do_div(size, port_buff_cell_sz);
+               do_div(xoff, port_buff_cell_sz);
+               do_div(xon, port_buff_cell_sz);
+               MLX5_SET(bufferx_reg, buffer, size, size);
+               MLX5_SET(bufferx_reg, buffer, lossy, port_buffer->buffer[i].lossy);
+               MLX5_SET(bufferx_reg, buffer, xoff_threshold, xoff);
+               MLX5_SET(bufferx_reg, buffer, xon_threshold, xon);
        }
 
        err = mlx5e_port_set_pbmc(mdev, in);
@@ -143,7 +146,7 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)
 }
 
 static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
-                                u32 xoff, unsigned int max_mtu)
+                                u32 xoff, unsigned int max_mtu, u16 port_buff_cell_sz)
 {
        int i;
 
@@ -155,7 +158,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
                }
 
                if (port_buffer->buffer[i].size <
-                   (xoff + max_mtu + (1 << MLX5E_BUFFER_CELL_SHIFT))) {
+                   (xoff + max_mtu + port_buff_cell_sz)) {
                        pr_err("buffer_size[%d]=%d is not enough for lossless buffer\n",
                               i, port_buffer->buffer[i].size);
                        return -ENOMEM;
@@ -175,6 +178,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
  *     @pfc_en: <input> current pfc configuration
  *     @buffer: <input> current prio to buffer mapping
  *     @xoff:   <input> xoff value
+ *     @port_buff_cell_sz: <input> port buffer cell_size
  *     @port_buffer: <output> port receive buffer configuration
  *     @change: <output>
  *
@@ -189,7 +193,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer,
  *     sets change to true if buffer configuration was modified.
  */
 static int update_buffer_lossy(unsigned int max_mtu,
-                              u8 pfc_en, u8 *buffer, u32 xoff,
+                              u8 pfc_en, u8 *buffer, u32 xoff, u16 port_buff_cell_sz,
                               struct mlx5e_port_buffer *port_buffer,
                               bool *change)
 {
@@ -225,7 +229,7 @@ static int update_buffer_lossy(unsigned int max_mtu,
        }
 
        if (changed) {
-               err = update_xoff_threshold(port_buffer, xoff, max_mtu);
+               err = update_xoff_threshold(port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
 
@@ -262,6 +266,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
                                    u32 *buffer_size,
                                    u8 *prio2buffer)
 {
+       u16 port_buff_cell_sz = priv->dcbx.port_buff_cell_sz;
        struct mlx5e_port_buffer port_buffer;
        u32 xoff = calculate_xoff(priv, mtu);
        bool update_prio2buffer = false;
@@ -282,7 +287,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
 
        if (change & MLX5E_PORT_BUFFER_CABLE_LEN) {
                update_buffer = true;
-               err = update_xoff_threshold(&port_buffer, xoff, max_mtu);
+               err = update_xoff_threshold(&port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
        }
@@ -292,7 +297,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
                if (err)
                        return err;
 
-               err = update_buffer_lossy(max_mtu, pfc->pfc_en, buffer, xoff,
+               err = update_buffer_lossy(max_mtu, pfc->pfc_en, buffer, xoff, port_buff_cell_sz,
                                          &port_buffer, &update_buffer);
                if (err)
                        return err;
@@ -304,7 +309,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
                if (err)
                        return err;
 
-               err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer,
+               err = update_buffer_lossy(max_mtu, curr_pfc_en, prio2buffer, port_buff_cell_sz,
                                          xoff, &port_buffer, &update_buffer);
                if (err)
                        return err;
@@ -329,7 +334,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
                        return -EINVAL;
 
                update_buffer = true;
-               err = update_xoff_threshold(&port_buffer, xoff, max_mtu);
+               err = update_xoff_threshold(&port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
        }
@@ -337,7 +342,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
        /* Need to update buffer configuration if xoff value is changed */
        if (!update_buffer && xoff != priv->dcbx.xoff) {
                update_buffer = true;
-               err = update_xoff_threshold(&port_buffer, xoff, max_mtu);
+               err = update_xoff_threshold(&port_buffer, xoff, max_mtu, port_buff_cell_sz);
                if (err)
                        return err;
        }
index 34f55b8..80af7a5 100644 (file)
@@ -36,7 +36,6 @@
 #include "port.h"
 
 #define MLX5E_MAX_BUFFER 8
-#define MLX5E_BUFFER_CELL_SHIFT 7
 #define MLX5E_DEFAULT_CABLE_LEN 7 /* 7 meters */
 
 #define MLX5_BUFFER_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, pcam_reg) && \
index bc102d0..d20243d 100644 (file)
@@ -1217,6 +1217,24 @@ static int mlx5e_trust_initialize(struct mlx5e_priv *priv)
        return 0;
 }
 
+#define MLX5E_BUFFER_CELL_SHIFT 7
+
+static u16 mlx5e_query_port_buffers_cell_size(struct mlx5e_priv *priv)
+{
+       struct mlx5_core_dev *mdev = priv->mdev;
+       u32 out[MLX5_ST_SZ_DW(sbcam_reg)] = {};
+       u32 in[MLX5_ST_SZ_DW(sbcam_reg)] = {};
+
+       if (!MLX5_CAP_GEN(mdev, sbcam_reg))
+               return (1 << MLX5E_BUFFER_CELL_SHIFT);
+
+       if (mlx5_core_access_reg(mdev, in, sizeof(in), out, sizeof(out),
+                                MLX5_REG_SBCAM, 0, 0))
+               return (1 << MLX5E_BUFFER_CELL_SHIFT);
+
+       return MLX5_GET(sbcam_reg, out, cap_cell_size);
+}
+
 void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
 {
        struct mlx5e_dcbx *dcbx = &priv->dcbx;
@@ -1234,6 +1252,7 @@ void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
        if (priv->dcbx.mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
                priv->dcbx.cap |= DCB_CAP_DCBX_HOST;
 
+       priv->dcbx.port_buff_cell_sz = mlx5e_query_port_buffers_cell_size(priv);
        priv->dcbx.manual_buffer = false;
        priv->dcbx.cable_len = MLX5E_DEFAULT_CABLE_LEN;
 
index 13c0e45..1e6ca71 100644 (file)
@@ -147,6 +147,7 @@ enum {
        MLX5_REG_MCDA            = 0x9063,
        MLX5_REG_MCAM            = 0x907f,
        MLX5_REG_MIRC            = 0x9162,
+       MLX5_REG_SBCAM           = 0xB01F,
        MLX5_REG_RESOURCE_DUMP   = 0xC000,
 };
 
index ca1887d..073b79e 100644 (file)
@@ -9960,6 +9960,34 @@ struct mlx5_ifc_pptb_reg_bits {
        u8         untagged_buff[0x4];
 };
 
+struct mlx5_ifc_sbcam_reg_bits {
+       u8         reserved_at_0[0x8];
+       u8         feature_group[0x8];
+       u8         reserved_at_10[0x8];
+       u8         access_reg_group[0x8];
+
+       u8         reserved_at_20[0x20];
+
+       u8         sb_access_reg_cap_mask[4][0x20];
+
+       u8         reserved_at_c0[0x80];
+
+       u8         sb_feature_cap_mask[4][0x20];
+
+       u8         reserved_at_1c0[0x40];
+
+       u8         cap_total_buffer_size[0x20];
+
+       u8         cap_cell_size[0x10];
+       u8         cap_max_pg_buffers[0x8];
+       u8         cap_num_pool_supported[0x8];
+
+       u8         reserved_at_240[0x8];
+       u8         cap_sbsr_stat_size[0x8];
+       u8         cap_max_tclass_data[0x8];
+       u8         cap_max_cpu_ingress_tclass_sb[0x8];
+};
+
 struct mlx5_ifc_pbmc_reg_bits {
        u8         reserved_at_0[0x8];
        u8         local_port[0x8];