mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 16:44:58 +02:00
Merge branch 'mlx5e-profile-change-fix'
Saeed Mahameed says: ==================== mlx5e profile change fix This series fixes a crash in mlx5e due to profile change error flow. ==================== Link: https://patch.msgid.link/20260108212657.25090-1-saeed@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
16ce6e6fa9
|
|
@ -962,7 +962,7 @@ struct mlx5e_priv {
|
|||
};
|
||||
|
||||
struct mlx5e_dev {
|
||||
struct mlx5e_priv *priv;
|
||||
struct net_device *netdev;
|
||||
struct devlink_port dl_port;
|
||||
};
|
||||
|
||||
|
|
@ -1242,10 +1242,13 @@ struct net_device *
|
|||
mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *profile);
|
||||
int mlx5e_attach_netdev(struct mlx5e_priv *priv);
|
||||
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_destroy_netdev(struct net_device *netdev);
|
||||
int mlx5e_netdev_change_profile(struct net_device *netdev,
|
||||
struct mlx5_core_dev *mdev,
|
||||
const struct mlx5e_profile *new_profile,
|
||||
void *new_ppriv);
|
||||
void mlx5e_netdev_attach_nic_profile(struct net_device *netdev,
|
||||
struct mlx5_core_dev *mdev);
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -6325,6 +6325,7 @@ int mlx5e_priv_init(struct mlx5e_priv *priv,
|
|||
|
||||
void mlx5e_priv_cleanup(struct mlx5e_priv *priv)
|
||||
{
|
||||
bool destroying = test_bit(MLX5E_STATE_DESTROYING, &priv->state);
|
||||
int i;
|
||||
|
||||
/* bail if change profile failed and also rollback failed */
|
||||
|
|
@ -6352,6 +6353,8 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv)
|
|||
}
|
||||
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
if (destroying) /* restore destroying bit, to allow unload */
|
||||
set_bit(MLX5E_STATE_DESTROYING, &priv->state);
|
||||
}
|
||||
|
||||
static unsigned int mlx5e_get_max_num_txqs(struct mlx5_core_dev *mdev,
|
||||
|
|
@ -6584,19 +6587,28 @@ mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mde
|
|||
return err;
|
||||
}
|
||||
|
||||
int mlx5e_netdev_change_profile(struct mlx5e_priv *priv,
|
||||
const struct mlx5e_profile *new_profile, void *new_ppriv)
|
||||
int mlx5e_netdev_change_profile(struct net_device *netdev,
|
||||
struct mlx5_core_dev *mdev,
|
||||
const struct mlx5e_profile *new_profile,
|
||||
void *new_ppriv)
|
||||
{
|
||||
const struct mlx5e_profile *orig_profile = priv->profile;
|
||||
struct net_device *netdev = priv->netdev;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
void *orig_ppriv = priv->ppriv;
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
const struct mlx5e_profile *orig_profile;
|
||||
int err, rollback_err;
|
||||
void *orig_ppriv;
|
||||
|
||||
/* cleanup old profile */
|
||||
mlx5e_detach_netdev(priv);
|
||||
priv->profile->cleanup(priv);
|
||||
mlx5e_priv_cleanup(priv);
|
||||
orig_profile = priv->profile;
|
||||
orig_ppriv = priv->ppriv;
|
||||
|
||||
/* NULL could happen if previous change_profile failed to rollback */
|
||||
if (priv->profile) {
|
||||
WARN_ON_ONCE(priv->mdev != mdev);
|
||||
/* cleanup old profile */
|
||||
mlx5e_detach_netdev(priv);
|
||||
priv->profile->cleanup(priv);
|
||||
mlx5e_priv_cleanup(priv);
|
||||
}
|
||||
/* priv members are not valid from this point ... */
|
||||
|
||||
if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
|
||||
mlx5e_netdev_init_profile(netdev, mdev, new_profile, new_ppriv);
|
||||
|
|
@ -6613,23 +6625,33 @@ int mlx5e_netdev_change_profile(struct mlx5e_priv *priv,
|
|||
return 0;
|
||||
|
||||
rollback:
|
||||
if (!orig_profile) {
|
||||
netdev_warn(netdev, "no original profile to rollback to\n");
|
||||
priv->profile = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
rollback_err = mlx5e_netdev_attach_profile(netdev, mdev, orig_profile, orig_ppriv);
|
||||
if (rollback_err)
|
||||
netdev_err(netdev, "%s: failed to rollback to orig profile, %d\n",
|
||||
__func__, rollback_err);
|
||||
if (rollback_err) {
|
||||
netdev_err(netdev, "failed to rollback to orig profile, %d\n",
|
||||
rollback_err);
|
||||
priv->profile = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5e_netdev_attach_nic_profile(struct mlx5e_priv *priv)
|
||||
void mlx5e_netdev_attach_nic_profile(struct net_device *netdev,
|
||||
struct mlx5_core_dev *mdev)
|
||||
{
|
||||
mlx5e_netdev_change_profile(priv, &mlx5e_nic_profile, NULL);
|
||||
mlx5e_netdev_change_profile(netdev, mdev, &mlx5e_nic_profile, NULL);
|
||||
}
|
||||
|
||||
void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
|
||||
void mlx5e_destroy_netdev(struct net_device *netdev)
|
||||
{
|
||||
struct net_device *netdev = priv->netdev;
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
||||
mlx5e_priv_cleanup(priv);
|
||||
if (priv->profile)
|
||||
mlx5e_priv_cleanup(priv);
|
||||
free_netdev(netdev);
|
||||
}
|
||||
|
||||
|
|
@ -6637,8 +6659,8 @@ static int _mlx5e_resume(struct auxiliary_device *adev)
|
|||
{
|
||||
struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
|
||||
struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev);
|
||||
struct mlx5e_priv *priv = mlx5e_dev->priv;
|
||||
struct net_device *netdev = priv->netdev;
|
||||
struct mlx5e_priv *priv = netdev_priv(mlx5e_dev->netdev);
|
||||
struct net_device *netdev = mlx5e_dev->netdev;
|
||||
struct mlx5_core_dev *mdev = edev->mdev;
|
||||
struct mlx5_core_dev *pos, *to;
|
||||
int err, i;
|
||||
|
|
@ -6684,10 +6706,11 @@ static int mlx5e_resume(struct auxiliary_device *adev)
|
|||
|
||||
static int _mlx5e_suspend(struct auxiliary_device *adev, bool pre_netdev_reg)
|
||||
{
|
||||
struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
|
||||
struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev);
|
||||
struct mlx5e_priv *priv = mlx5e_dev->priv;
|
||||
struct net_device *netdev = priv->netdev;
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
struct mlx5e_priv *priv = netdev_priv(mlx5e_dev->netdev);
|
||||
struct net_device *netdev = mlx5e_dev->netdev;
|
||||
struct mlx5_core_dev *mdev = edev->mdev;
|
||||
struct mlx5_core_dev *pos;
|
||||
int i;
|
||||
|
||||
|
|
@ -6748,11 +6771,11 @@ static int _mlx5e_probe(struct auxiliary_device *adev)
|
|||
goto err_devlink_port_unregister;
|
||||
}
|
||||
SET_NETDEV_DEVLINK_PORT(netdev, &mlx5e_dev->dl_port);
|
||||
mlx5e_dev->netdev = netdev;
|
||||
|
||||
mlx5e_build_nic_netdev(netdev);
|
||||
|
||||
priv = netdev_priv(netdev);
|
||||
mlx5e_dev->priv = priv;
|
||||
|
||||
priv->profile = profile;
|
||||
priv->ppriv = NULL;
|
||||
|
|
@ -6785,7 +6808,7 @@ static int _mlx5e_probe(struct auxiliary_device *adev)
|
|||
err_profile_cleanup:
|
||||
profile->cleanup(priv);
|
||||
err_destroy_netdev:
|
||||
mlx5e_destroy_netdev(priv);
|
||||
mlx5e_destroy_netdev(netdev);
|
||||
err_devlink_port_unregister:
|
||||
mlx5e_devlink_port_unregister(mlx5e_dev);
|
||||
err_devlink_unregister:
|
||||
|
|
@ -6815,17 +6838,20 @@ static void _mlx5e_remove(struct auxiliary_device *adev)
|
|||
{
|
||||
struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
|
||||
struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev);
|
||||
struct mlx5e_priv *priv = mlx5e_dev->priv;
|
||||
struct net_device *netdev = mlx5e_dev->netdev;
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = edev->mdev;
|
||||
|
||||
mlx5_core_uplink_netdev_set(mdev, NULL);
|
||||
mlx5e_dcbnl_delete_app(priv);
|
||||
|
||||
if (priv->profile)
|
||||
mlx5e_dcbnl_delete_app(priv);
|
||||
/* When unload driver, the netdev is in registered state
|
||||
* if it's from legacy mode. If from switchdev mode, it
|
||||
* is already unregistered before changing to NIC profile.
|
||||
*/
|
||||
if (priv->netdev->reg_state == NETREG_REGISTERED) {
|
||||
unregister_netdev(priv->netdev);
|
||||
if (netdev->reg_state == NETREG_REGISTERED) {
|
||||
unregister_netdev(netdev);
|
||||
_mlx5e_suspend(adev, false);
|
||||
} else {
|
||||
struct mlx5_core_dev *pos;
|
||||
|
|
@ -6840,7 +6866,7 @@ static void _mlx5e_remove(struct auxiliary_device *adev)
|
|||
/* Avoid cleanup if profile rollback failed. */
|
||||
if (priv->profile)
|
||||
priv->profile->cleanup(priv);
|
||||
mlx5e_destroy_netdev(priv);
|
||||
mlx5e_destroy_netdev(netdev);
|
||||
mlx5e_devlink_port_unregister(mlx5e_dev);
|
||||
mlx5e_destroy_devlink(mlx5e_dev);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1508,17 +1508,16 @@ mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *
|
|||
{
|
||||
struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
|
||||
struct net_device *netdev;
|
||||
struct mlx5e_priv *priv;
|
||||
int err;
|
||||
|
||||
netdev = mlx5_uplink_netdev_get(dev);
|
||||
if (!netdev)
|
||||
return 0;
|
||||
|
||||
priv = netdev_priv(netdev);
|
||||
rpriv->netdev = priv->netdev;
|
||||
err = mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile,
|
||||
rpriv);
|
||||
/* must not use netdev_priv(netdev), it might not be initialized yet */
|
||||
rpriv->netdev = netdev;
|
||||
err = mlx5e_netdev_change_profile(netdev, dev,
|
||||
&mlx5e_uplink_rep_profile, rpriv);
|
||||
mlx5_uplink_netdev_put(dev, netdev);
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1546,7 +1545,7 @@ mlx5e_vport_uplink_rep_unload(struct mlx5e_rep_priv *rpriv)
|
|||
if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_SWITCH_LEGACY))
|
||||
unregister_netdev(netdev);
|
||||
|
||||
mlx5e_netdev_attach_nic_profile(priv);
|
||||
mlx5e_netdev_attach_nic_profile(netdev, priv->mdev);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -1612,7 +1611,7 @@ mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
|
|||
priv->profile->cleanup(priv);
|
||||
|
||||
err_destroy_netdev:
|
||||
mlx5e_destroy_netdev(netdev_priv(netdev));
|
||||
mlx5e_destroy_netdev(netdev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1667,7 +1666,7 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
|
|||
mlx5e_rep_vnic_reporter_destroy(priv);
|
||||
mlx5e_detach_netdev(priv);
|
||||
priv->profile->cleanup(priv);
|
||||
mlx5e_destroy_netdev(priv);
|
||||
mlx5e_destroy_netdev(netdev);
|
||||
free_ppriv:
|
||||
kvfree(ppriv); /* mlx5e_rep_priv */
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user