From: Ron Diskin <ro...@mellanox.com>

[ Upstream commit 7d0314b11cdd92bca8b89684c06953bf114605fc ]

When setting the PF interface up/down, notify the firmware to update
uplink state via MODIFY_VPORT_STATE, when E-Switch is enabled.

This behavior will prevent sending traffic out on uplink port when PF is
down, such as sending traffic from a VF interface which is still up.
Currently when calling mlx5e_open/close(), the driver only sends PAOS
command to notify the firmware to set the physical port state to
up/down, however, it is not sufficient. When VF is in "auto" state, it
follows the uplink state, which was not updated on mlx5e_open/close()
before this patch.

When switchdev mode is enabled and uplink representor is first enabled,
set the uplink port state value back to its FW default "AUTO".

Fixes: 63bfd399de55 ("net/mlx5e: Send PAOS command on interface up/down")
Signed-off-by: Ron Diskin <ro...@mellanox.com>
Reviewed-by: Roi Dayan <r...@mellanox.com>
Reviewed-by: Moshe Shemesh <mo...@mellanox.com>
Signed-off-by: Saeed Mahameed <sae...@mellanox.com>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 .../net/ethernet/mellanox/mlx5/core/en_main.c | 25 ++++++++++++++++---
 .../net/ethernet/mellanox/mlx5/core/en_rep.c  |  2 ++
 .../net/ethernet/mellanox/mlx5/core/eswitch.c | 16 +++++++-----
 .../net/ethernet/mellanox/mlx5/core/eswitch.h |  2 ++
 include/linux/mlx5/mlx5_ifc.h                 |  1 +
 5 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 15db4a8746dd7..cb3dcfced89fa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3038,6 +3038,25 @@ void mlx5e_timestamp_init(struct mlx5e_priv *priv)
        priv->tstamp.rx_filter = HWTSTAMP_FILTER_NONE;
 }
 
+static void mlx5e_modify_admin_state(struct mlx5_core_dev *mdev,
+                                    enum mlx5_port_status state)
+{
+       struct mlx5_eswitch *esw = mdev->priv.eswitch;
+       int vport_admin_state;
+
+       mlx5_set_port_admin_status(mdev, state);
+
+       if (!MLX5_ESWITCH_MANAGER(mdev) ||  mlx5_eswitch_mode(esw) == 
MLX5_ESWITCH_OFFLOADS)
+               return;
+
+       if (state == MLX5_PORT_UP)
+               vport_admin_state = MLX5_VPORT_ADMIN_STATE_AUTO;
+       else
+               vport_admin_state = MLX5_VPORT_ADMIN_STATE_DOWN;
+
+       mlx5_eswitch_set_vport_state(esw, MLX5_VPORT_UPLINK, vport_admin_state);
+}
+
 int mlx5e_open_locked(struct net_device *netdev)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -3070,7 +3089,7 @@ int mlx5e_open(struct net_device *netdev)
        mutex_lock(&priv->state_lock);
        err = mlx5e_open_locked(netdev);
        if (!err)
-               mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_UP);
+               mlx5e_modify_admin_state(priv->mdev, MLX5_PORT_UP);
        mutex_unlock(&priv->state_lock);
 
        if (mlx5_vxlan_allowed(priv->mdev->vxlan))
@@ -3107,7 +3126,7 @@ int mlx5e_close(struct net_device *netdev)
                return -ENODEV;
 
        mutex_lock(&priv->state_lock);
-       mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_DOWN);
+       mlx5e_modify_admin_state(priv->mdev, MLX5_PORT_DOWN);
        err = mlx5e_close_locked(netdev);
        mutex_unlock(&priv->state_lock);
 
@@ -5172,7 +5191,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv)
 
        /* Marking the link as currently not needed by the Driver */
        if (!netif_running(netdev))
-               mlx5_set_port_admin_status(mdev, MLX5_PORT_DOWN);
+               mlx5e_modify_admin_state(mdev, MLX5_PORT_DOWN);
 
        mlx5e_set_netdev_mtu_boundaries(priv);
        mlx5e_set_dev_port_mtu(priv);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 9b232ef36d53b..88b51f64a64ea 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -1736,6 +1736,8 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv 
*priv)
        INIT_WORK(&rpriv->uplink_priv.reoffload_flows_work,
                  mlx5e_tc_reoffload_flows_work);
 
+       mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK,
+                                     0, 0, MLX5_VPORT_ADMIN_STATE_AUTO);
        mlx5_lag_add(mdev, netdev);
        priv->events_nb.notifier_call = uplink_rep_async_event;
        mlx5_notifier_register(mdev, &priv->events_nb);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c 
b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index 422a57404407d..6b711affb7da4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -2094,6 +2094,8 @@ int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
                                 u16 vport, int link_state)
 {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
+       int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
+       int other_vport = 1;
        int err = 0;
 
        if (!ESW_ALLOWED(esw))
@@ -2101,15 +2103,17 @@ int mlx5_eswitch_set_vport_state(struct mlx5_eswitch 
*esw,
        if (IS_ERR(evport))
                return PTR_ERR(evport);
 
+       if (vport == MLX5_VPORT_UPLINK) {
+               opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK;
+               other_vport = 0;
+               vport = 0;
+       }
        mutex_lock(&esw->state_lock);
 
-       err = mlx5_modify_vport_admin_state(esw->dev,
-                                           MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
-                                           vport, 1, link_state);
+       err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, 
other_vport, link_state);
        if (err) {
-               mlx5_core_warn(esw->dev,
-                              "Failed to set vport %d link state, err = %d",
-                              vport, err);
+               mlx5_core_warn(esw->dev, "Failed to set vport %d link state, 
opmod = %d, err = %d",
+                              vport, opmod, err);
                goto unlock;
        }
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h 
b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index 6bd6f58952442..0ddbae1e64fad 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -606,6 +606,8 @@ static inline int  mlx5_eswitch_enable(struct mlx5_eswitch 
*esw, int mode) { ret
 static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw) {}
 static inline bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct 
mlx5_core_dev *dev1) { return true; }
 static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { 
return false; }
+static inline
+int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int 
link_state) { return 0; }
 static inline const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
 {
        return ERR_PTR(-EOPNOTSUPP);
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index acd859ea09d42..aba56077cfda2 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -4177,6 +4177,7 @@ struct mlx5_ifc_query_vport_state_out_bits {
 enum {
        MLX5_VPORT_STATE_OP_MOD_VNIC_VPORT  = 0x0,
        MLX5_VPORT_STATE_OP_MOD_ESW_VPORT   = 0x1,
+       MLX5_VPORT_STATE_OP_MOD_UPLINK      = 0x2,
 };
 
 struct mlx5_ifc_arm_monitor_counter_in_bits {
-- 
2.25.1



Reply via email to