| From f327f5790880c735410f49ba43f15a87e32a3e4d Mon Sep 17 00:00:00 2001 |
| From: Ron Diskin <rondi@mellanox.com> |
| Date: Sun, 5 Apr 2020 13:58:40 +0300 |
| Subject: [PATCH] net/mlx5e: Modify uplink state on interface up/down |
| |
| commit 7d0314b11cdd92bca8b89684c06953bf114605fc upstream. |
| |
| 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 <rondi@mellanox.com> |
| Reviewed-by: Roi Dayan <roid@mellanox.com> |
| Reviewed-by: Moshe Shemesh <moshe@mellanox.com> |
| Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> |
| [PG: SRIOV_OFFLOADS <---> MLX5_ESWITCH_OFFLOADS as per v5.3-rc1~79^2~20^2~20] |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c |
| index 180b74b34f9a..f146dfadf5f7 100644 |
| --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c |
| +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c |
| @@ -2889,6 +2889,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) == SRIOV_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); |
| @@ -2921,7 +2940,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)) |
| @@ -2958,7 +2977,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); |
| |
| @@ -4898,7 +4917,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 23f843dd92dc..e6515fcb548b 100644 |
| --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c |
| +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c |
| @@ -1692,6 +1692,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 76ffde866979..3fcc53a6b2dc 100644 |
| --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c |
| +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c |
| @@ -1957,6 +1957,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)) |
| @@ -1964,15 +1966,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 d043d6f9797d..5df1759b2b9e 100644 |
| --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h |
| +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h |
| @@ -498,6 +498,8 @@ static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {} |
| static inline int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) { return 0; } |
| static inline void mlx5_eswitch_disable_sriov(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 |
| +int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int link_state) { return 0; } |
| |
| #define FDB_MAX_CHAIN 1 |
| #define FDB_SLOW_PATH_CHAIN (FDB_MAX_CHAIN + 1) |
| diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h |
| index 3d1e4a53b9e4..9310a7e1057b 100644 |
| --- a/include/linux/mlx5/mlx5_ifc.h |
| +++ b/include/linux/mlx5/mlx5_ifc.h |
| @@ -3929,6 +3929,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.27.0 |
| |