Skip to content

Commit

Permalink
net/mlx5e: Do not reload ethernet ports when changing eswitch mode
Browse files Browse the repository at this point in the history
When switching modes between legacy and switchdev and back, do not
reload ethernet interfaces. just change the profile from nic profile
to uplink rep profile in switchdev mode.

Signed-off-by: Roi Dayan <roid@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
  • Loading branch information
roidayan authored and Saeed Mahameed committed Mar 16, 2021
1 parent fec2b4b commit 7a9fb35
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 54 deletions.
3 changes: 0 additions & 3 deletions drivers/net/ethernet/mellanox/mlx5/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ static bool is_eth_supported(struct mlx5_core_dev *dev)
if (!IS_ENABLED(CONFIG_MLX5_CORE_EN))
return false;

if (is_eth_rep_supported(dev))
return false;

if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
return false;

Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en.h
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,7 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv);
void mlx5e_destroy_netdev(struct mlx5e_priv *priv);
int mlx5e_netdev_change_profile(struct mlx5e_priv *priv,
const struct mlx5e_profile *new_profile, void *new_ppriv);
void mlx5e_netdev_attach_nic_profile(struct mlx5e_priv *priv);
void mlx5e_set_netdev_mtu_boundaries(struct mlx5e_priv *priv);
void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 mtu);
void mlx5e_build_rq_params(struct mlx5_core_dev *mdev,
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -635,4 +635,5 @@ void mlx5e_reporter_rx_destroy(struct mlx5e_priv *priv)
return;

devlink_port_health_reporter_destroy(priv->rx_reporter);
priv->rx_reporter = NULL;
}
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,4 +593,5 @@ void mlx5e_reporter_tx_destroy(struct mlx5e_priv *priv)
return;

devlink_port_health_reporter_destroy(priv->tx_reporter);
priv->tx_reporter = NULL;
}
6 changes: 6 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5742,6 +5742,11 @@ int mlx5e_netdev_change_profile(struct mlx5e_priv *priv,
return err;
}

void mlx5e_netdev_attach_nic_profile(struct mlx5e_priv *priv)
{
mlx5e_netdev_change_profile(priv, &mlx5e_nic_profile, NULL);
}

void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
{
struct net_device *netdev = priv->netdev;
Expand Down Expand Up @@ -5852,6 +5857,7 @@ static int mlx5e_probe(struct auxiliary_device *adev,
mlx5e_devlink_port_type_eth_set(priv);

mlx5e_dcbnl_init_app(priv);
mlx5_uplink_netdev_set(mdev, netdev);
return 0;

err_resume:
Expand Down
148 changes: 97 additions & 51 deletions drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "en_tc.h"
#include "en/rep/tc.h"
#include "en/rep/neigh.h"
#include "en/devlink.h"
#include "fs_core.h"
#include "lib/mlx5.h"
#define CREATE_TRACE_POINTS
Expand Down Expand Up @@ -588,26 +589,15 @@ static void mlx5e_build_rep_params(struct net_device *netdev)
}

static void mlx5e_build_rep_netdev(struct net_device *netdev,
struct mlx5_core_dev *mdev,
struct mlx5_eswitch_rep *rep)
struct mlx5_core_dev *mdev)
{
SET_NETDEV_DEV(netdev, mdev->device);
if (rep->vport == MLX5_VPORT_UPLINK) {
netdev->netdev_ops = &mlx5e_netdev_ops;
/* we want a persistent mac for the uplink rep */
mlx5_query_mac_address(mdev, netdev->dev_addr);
netdev->ethtool_ops = &mlx5e_ethtool_ops;
mlx5e_dcbnl_build_rep_netdev(netdev);
} else {
netdev->netdev_ops = &mlx5e_netdev_ops_rep;
eth_hw_addr_random(netdev);
netdev->ethtool_ops = &mlx5e_rep_ethtool_ops;
}
netdev->netdev_ops = &mlx5e_netdev_ops_rep;
eth_hw_addr_random(netdev);
netdev->ethtool_ops = &mlx5e_rep_ethtool_ops;

netdev->watchdog_timeo = 15 * HZ;

netdev->features |= NETIF_F_NETNS_LOCAL;

#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
netdev->hw_features |= NETIF_F_HW_TC;
#endif
Expand All @@ -619,12 +609,9 @@ static void mlx5e_build_rep_netdev(struct net_device *netdev,
netdev->hw_features |= NETIF_F_TSO6;
netdev->hw_features |= NETIF_F_RXCSUM;

if (rep->vport == MLX5_VPORT_UPLINK)
netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX;
else
netdev->features |= NETIF_F_VLAN_CHALLENGED;

netdev->features |= netdev->hw_features;
netdev->features |= NETIF_F_VLAN_CHALLENGED;
netdev->features |= NETIF_F_NETNS_LOCAL;
}

static int mlx5e_init_rep(struct mlx5_core_dev *mdev,
Expand Down Expand Up @@ -990,13 +977,27 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
mlx5e_dcbnl_initialize(priv);
mlx5e_dcbnl_init_app(priv);
mlx5e_rep_neigh_init(rpriv);

netdev->wanted_features |= NETIF_F_HW_TC;

rtnl_lock();
if (netif_running(netdev))
mlx5e_open(netdev);
netif_device_attach(netdev);
rtnl_unlock();
}

static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
{
struct mlx5e_rep_priv *rpriv = priv->ppriv;
struct mlx5_core_dev *mdev = priv->mdev;

rtnl_lock();
if (netif_running(priv->netdev))
mlx5e_close(priv->netdev);
netif_device_detach(priv->netdev);
rtnl_unlock();

mlx5e_rep_neigh_cleanup(rpriv);
mlx5e_dcbnl_delete_app(priv);
mlx5_notifier_unregister(mdev, &priv->events_nb);
Expand Down Expand Up @@ -1081,26 +1082,56 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = {

/* e-Switch vport representors */
static int
mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
struct mlx5e_priv *priv = netdev_priv(mlx5_uplink_netdev_get(dev));
struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
struct devlink_port *dl_port;
int err;

rpriv->netdev = priv->netdev;

err = mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile,
rpriv);
if (err)
return err;

dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
if (dl_port)
devlink_port_type_eth_set(dl_port, rpriv->netdev);

return 0;
}

static void
mlx5e_vport_uplink_rep_unload(struct mlx5e_rep_priv *rpriv)
{
struct net_device *netdev = rpriv->netdev;
struct devlink_port *dl_port;
struct mlx5_core_dev *dev;
struct mlx5e_priv *priv;

priv = netdev_priv(netdev);
dev = priv->mdev;

dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
if (dl_port)
devlink_port_type_clear(dl_port);
mlx5e_netdev_attach_nic_profile(priv);
}

static int
mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
const struct mlx5e_profile *profile;
struct mlx5e_rep_priv *rpriv;
struct devlink_port *dl_port;
struct net_device *netdev;
struct mlx5e_priv *priv;
unsigned int txqs, rxqs;
int nch, err;

rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
if (!rpriv)
return -ENOMEM;

/* rpriv->rep to be looked up when profile->init() is called */
rpriv->rep = rep;

profile = (rep->vport == MLX5_VPORT_UPLINK) ?
&mlx5e_uplink_rep_profile : &mlx5e_rep_profile;

profile = &mlx5e_rep_profile;
nch = mlx5e_get_max_num_channels(dev);
txqs = nch * profile->max_tc;
rxqs = nch * profile->rq_groups;
Expand All @@ -1109,29 +1140,19 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
mlx5_core_warn(dev,
"Failed to create representor netdev for vport %d\n",
rep->vport);
kfree(rpriv);
return -EINVAL;
}

mlx5e_build_rep_netdev(netdev, dev, rep);

mlx5e_build_rep_netdev(netdev, dev);
rpriv->netdev = netdev;
rep->rep_data[REP_ETH].priv = rpriv;
INIT_LIST_HEAD(&rpriv->vport_sqs_list);

if (rep->vport == MLX5_VPORT_UPLINK) {
err = mlx5e_create_mdev_resources(dev);
if (err)
goto err_destroy_netdev;
}

priv = netdev_priv(netdev);
priv->profile = profile;
priv->ppriv = rpriv;
err = profile->init(dev, netdev);
if (err) {
netdev_warn(netdev, "rep profile init failed, %d\n", err);
goto err_destroy_mdev_resources;
goto err_destroy_netdev;
}

err = mlx5e_attach_netdev(netdev_priv(netdev));
Expand Down Expand Up @@ -1161,13 +1182,34 @@ mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
err_cleanup_profile:
priv->profile->cleanup(priv);

err_destroy_mdev_resources:
if (rep->vport == MLX5_VPORT_UPLINK)
mlx5e_destroy_mdev_resources(dev);

err_destroy_netdev:
mlx5e_destroy_netdev(netdev_priv(netdev));
kfree(rpriv);
return err;
}

static int
mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
{
struct mlx5e_rep_priv *rpriv;
int err;

rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
if (!rpriv)
return -ENOMEM;

/* rpriv->rep to be looked up when profile->init() is called */
rpriv->rep = rep;
rep->rep_data[REP_ETH].priv = rpriv;
INIT_LIST_HEAD(&rpriv->vport_sqs_list);

if (rep->vport == MLX5_VPORT_UPLINK)
err = mlx5e_vport_uplink_rep_load(dev, rep);
else
err = mlx5e_vport_vf_rep_load(dev, rep);

if (err)
kfree(rpriv);

return err;
}

Expand All @@ -1181,15 +1223,19 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
struct devlink_port *dl_port;
void *ppriv = priv->ppriv;

if (rep->vport == MLX5_VPORT_UPLINK) {
mlx5e_vport_uplink_rep_unload(rpriv);
goto free_ppriv;
}

dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
if (dl_port)
devlink_port_type_clear(dl_port);
unregister_netdev(netdev);
mlx5e_detach_netdev(priv);
priv->profile->cleanup(priv);
if (rep->vport == MLX5_VPORT_UPLINK)
mlx5e_destroy_mdev_resources(priv->mdev);
mlx5e_destroy_netdev(priv);
free_ppriv:
kfree(ppriv); /* mlx5e_rep_priv */
}

Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/lib/mlx5.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,13 @@ static inline struct net *mlx5_core_net(struct mlx5_core_dev *dev)
return devlink_net(priv_to_devlink(dev));
}

static inline void mlx5_uplink_netdev_set(struct mlx5_core_dev *mdev, struct net_device *netdev)
{
mdev->mlx5e_res.uplink_netdev = netdev;
}

static inline struct net_device *mlx5_uplink_netdev_get(struct mlx5_core_dev *mdev)
{
return mdev->mlx5e_res.uplink_netdev;
}
#endif
1 change: 1 addition & 0 deletions include/linux/mlx5/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,7 @@ struct mlx5e_resources {
struct mlx5_sq_bfreg bfreg;
} hw_objs;
struct devlink_port dl_port;
struct net_device *uplink_netdev;
};

enum mlx5_sw_icm_type {
Expand Down

0 comments on commit 7a9fb35

Please sign in to comment.