]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
mlxsw: spectrum: Move here the three-step headroom configuration from DCB
authorPetr Machata <petrm@nvidia.com>
Wed, 16 Sep 2020 06:35:23 +0000 (09:35 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 16 Sep 2020 22:19:30 +0000 (15:19 -0700)
The ETS handler performs the headroom configuration in three steps: first
it resizes the buffers and adds any new ones. Then it redirects priorities
to the new buffers. And finally it sets the size of the now-unused buffers
to zero. This way no packet drops are introduced.

This sort of careful approach will also be useful for configuring port
buffer sizes and priority map by hand, through dcbnl_setbuffer. Therefore
move the code from the DCB handler to the generic headroom function.

Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c

index 48e48c398142bd8384c100c1bb9046771ff0b3f2..1f0e930d8a5005efaa7a8a78c39739c553cc7125 100644 (file)
@@ -718,6 +718,30 @@ static int mlxsw_sp_hdroom_configure_buffers(struct mlxsw_sp_port *mlxsw_sp_port
        return 0;
 }
 
+static int mlxsw_sp_hdroom_configure_priomap(struct mlxsw_sp_port *mlxsw_sp_port,
+                                            const struct mlxsw_sp_hdroom *hdroom, bool force)
+{
+       char pptb_pl[MLXSW_REG_PPTB_LEN];
+       bool dirty;
+       int prio;
+       int err;
+
+       dirty = memcmp(&mlxsw_sp_port->hdroom->prios, &hdroom->prios, sizeof(hdroom->prios));
+       if (!dirty && !force)
+               return 0;
+
+       mlxsw_reg_pptb_pack(pptb_pl, mlxsw_sp_port->local_port);
+       for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
+               mlxsw_reg_pptb_prio_to_buff_pack(pptb_pl, prio, hdroom->prios.prio[prio].buf_idx);
+
+       err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pptb), pptb_pl);
+       if (err)
+               return err;
+
+       mlxsw_sp_port->hdroom->prios = hdroom->prios;
+       return 0;
+}
+
 static bool mlxsw_sp_hdroom_bufs_fit(struct mlxsw_sp *mlxsw_sp,
                                     const struct mlxsw_sp_hdroom *hdroom)
 {
@@ -735,17 +759,50 @@ static bool mlxsw_sp_hdroom_bufs_fit(struct mlxsw_sp *mlxsw_sp,
 static int __mlxsw_sp_hdroom_configure(struct mlxsw_sp_port *mlxsw_sp_port,
                                       const struct mlxsw_sp_hdroom *hdroom, bool force)
 {
+       struct mlxsw_sp_hdroom orig_hdroom;
+       struct mlxsw_sp_hdroom tmp_hdroom;
        int err;
+       int i;
+
+       /* Port buffers need to be configured in three steps. First, all buffers
+        * with non-zero size are configured. Then, prio-to-buffer map is
+        * updated, allowing traffic to flow to the now non-zero buffers.
+        * Finally, zero-sized buffers are configured, because now no traffic
+        * should be directed to them anymore. This way, in a non-congested
+        * system, no packet drops are introduced by the reconfiguration.
+        */
 
-       if (!mlxsw_sp_hdroom_bufs_fit(mlxsw_sp_port->mlxsw_sp, hdroom))
+       orig_hdroom = *mlxsw_sp_port->hdroom;
+       tmp_hdroom = orig_hdroom;
+       for (i = 0; i < MLXSW_SP_PB_COUNT; i++) {
+               if (hdroom->bufs.buf[i].size_cells)
+                       tmp_hdroom.bufs.buf[i] = hdroom->bufs.buf[i];
+       }
+
+       if (!mlxsw_sp_hdroom_bufs_fit(mlxsw_sp_port->mlxsw_sp, &tmp_hdroom) ||
+           !mlxsw_sp_hdroom_bufs_fit(mlxsw_sp_port->mlxsw_sp, hdroom))
                return -ENOBUFS;
 
-       err = mlxsw_sp_hdroom_configure_buffers(mlxsw_sp_port, hdroom, false);
+       err = mlxsw_sp_hdroom_configure_buffers(mlxsw_sp_port, &tmp_hdroom, force);
        if (err)
                return err;
 
+       err = mlxsw_sp_hdroom_configure_priomap(mlxsw_sp_port, hdroom, force);
+       if (err)
+               goto err_configure_priomap;
+
+       err = mlxsw_sp_hdroom_configure_buffers(mlxsw_sp_port, hdroom, false);
+       if (err)
+               goto err_configure_buffers;
+
        *mlxsw_sp_port->hdroom = *hdroom;
        return 0;
+
+err_configure_buffers:
+       mlxsw_sp_hdroom_configure_priomap(mlxsw_sp_port, &tmp_hdroom, false);
+err_configure_priomap:
+       mlxsw_sp_hdroom_configure_buffers(mlxsw_sp_port, &orig_hdroom, false);
+       return err;
 }
 
 int mlxsw_sp_hdroom_configure(struct mlxsw_sp_port *mlxsw_sp_port,
index 098432c881c2808fb9b8f214198b0e7dda3f20be..d9a556dbe85ef4cf057a088219d1b97bb97971b3 100644 (file)
@@ -64,85 +64,28 @@ static int mlxsw_sp_port_ets_validate(struct mlxsw_sp_port *mlxsw_sp_port,
        return 0;
 }
 
-static int mlxsw_sp_hdroom_configure_priomap(struct mlxsw_sp_port *mlxsw_sp_port,
-                                            const struct mlxsw_sp_hdroom *hdroom, bool force)
-{
-       char pptb_pl[MLXSW_REG_PPTB_LEN];
-       bool dirty;
-       int prio;
-       int err;
-
-       dirty = memcmp(&mlxsw_sp_port->hdroom->prios, &hdroom->prios, sizeof(hdroom->prios));
-       if (!dirty && !force)
-               return 0;
-
-       mlxsw_reg_pptb_pack(pptb_pl, mlxsw_sp_port->local_port);
-       for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
-               mlxsw_reg_pptb_prio_to_buff_pack(pptb_pl, prio, hdroom->prios.prio[prio].buf_idx);
-
-       err = mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pptb), pptb_pl);
-       if (err)
-               return err;
-
-       mlxsw_sp_port->hdroom->prios = hdroom->prios;
-       return 0;
-}
-
 static int mlxsw_sp_port_headroom_ets_set(struct mlxsw_sp_port *mlxsw_sp_port,
                                          struct ieee_ets *ets)
 {
        struct net_device *dev = mlxsw_sp_port->dev;
-       struct mlxsw_sp_hdroom orig_hdroom;
-       struct mlxsw_sp_hdroom tmp_hdroom;
        struct mlxsw_sp_hdroom hdroom;
        int prio;
        int err;
-       int i;
 
-       orig_hdroom = *mlxsw_sp_port->hdroom;
-
-       hdroom = orig_hdroom;
+       hdroom = *mlxsw_sp_port->hdroom;
        for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
                hdroom.prios.prio[prio].ets_buf_idx = ets->prio_tc[prio];
        mlxsw_sp_hdroom_prios_reset_buf_idx(&hdroom);
        mlxsw_sp_hdroom_bufs_reset_lossiness(&hdroom);
        mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port, &hdroom);
 
-       /* Create the required PGs, but don't destroy existing ones, as
-        * traffic is still directed to them.
-        */
-       tmp_hdroom = hdroom;
-       for (i = 0; i < DCBX_MAX_BUFFERS; i++) {
-               if (!tmp_hdroom.bufs.buf[i].size_cells)
-                       tmp_hdroom.bufs.buf[i].size_cells =
-                               mlxsw_sp_port->hdroom->bufs.buf[i].size_cells;
-       }
-
-       err = mlxsw_sp_hdroom_configure(mlxsw_sp_port, &tmp_hdroom);
+       err = mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom);
        if (err) {
                netdev_err(dev, "Failed to configure port's headroom\n");
                return err;
        }
 
-       err = mlxsw_sp_hdroom_configure_priomap(mlxsw_sp_port, &hdroom, false);
-       if (err) {
-               netdev_err(dev, "Failed to set PG-priority mapping\n");
-               goto err_port_prio_pg_map;
-       }
-
-       err = mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom);
-       if (err) {
-               netdev_warn(dev, "Failed to remove unused PGs\n");
-               goto err_configure_buffers;
-       }
-
        return 0;
-
-err_configure_buffers:
-       mlxsw_sp_hdroom_configure_priomap(mlxsw_sp_port, &tmp_hdroom, false);
-err_port_prio_pg_map:
-       mlxsw_sp_hdroom_configure(mlxsw_sp_port, &orig_hdroom);
-       return err;
 }
 
 static int __mlxsw_sp_dcbnl_ieee_setets(struct mlxsw_sp_port *mlxsw_sp_port,