Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+71 -43
+8 -5
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 962 962 }; 963 963 964 964 struct mlx5e_dev { 965 - struct mlx5e_priv *priv; 965 + struct net_device *netdev; 966 966 struct devlink_port dl_port; 967 967 }; 968 968 ··· 1242 1242 mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *profile); 1243 1243 int mlx5e_attach_netdev(struct mlx5e_priv *priv); 1244 1244 void mlx5e_detach_netdev(struct mlx5e_priv *priv); 1245 - void mlx5e_destroy_netdev(struct mlx5e_priv *priv); 1246 - int mlx5e_netdev_change_profile(struct mlx5e_priv *priv, 1247 - const struct mlx5e_profile *new_profile, void *new_ppriv); 1248 - void mlx5e_netdev_attach_nic_profile(struct mlx5e_priv *priv); 1245 + void mlx5e_destroy_netdev(struct net_device *netdev); 1246 + int mlx5e_netdev_change_profile(struct net_device *netdev, 1247 + struct mlx5_core_dev *mdev, 1248 + const struct mlx5e_profile *new_profile, 1249 + void *new_ppriv); 1250 + void mlx5e_netdev_attach_nic_profile(struct net_device *netdev, 1251 + struct mlx5_core_dev *mdev); 1249 1252 void mlx5e_set_netdev_mtu_boundaries(struct mlx5e_priv *priv); 1250 1253 void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 mtu); 1251 1254
+56 -30
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 6325 6325 6326 6326 void mlx5e_priv_cleanup(struct mlx5e_priv *priv) 6327 6327 { 6328 + bool destroying = test_bit(MLX5E_STATE_DESTROYING, &priv->state); 6328 6329 int i; 6329 6330 6330 6331 /* bail if change profile failed and also rollback failed */ ··· 6353 6352 } 6354 6353 6355 6354 memset(priv, 0, sizeof(*priv)); 6355 + if (destroying) /* restore destroying bit, to allow unload */ 6356 + set_bit(MLX5E_STATE_DESTROYING, &priv->state); 6356 6357 } 6357 6358 6358 6359 static unsigned int mlx5e_get_max_num_txqs(struct mlx5_core_dev *mdev, ··· 6587 6584 return err; 6588 6585 } 6589 6586 6590 - int mlx5e_netdev_change_profile(struct mlx5e_priv *priv, 6591 - const struct mlx5e_profile *new_profile, void *new_ppriv) 6587 + int mlx5e_netdev_change_profile(struct net_device *netdev, 6588 + struct mlx5_core_dev *mdev, 6589 + const struct mlx5e_profile *new_profile, 6590 + void *new_ppriv) 6592 6591 { 6593 - const struct mlx5e_profile *orig_profile = priv->profile; 6594 - struct net_device *netdev = priv->netdev; 6595 - struct mlx5_core_dev *mdev = priv->mdev; 6596 - void *orig_ppriv = priv->ppriv; 6592 + struct mlx5e_priv *priv = netdev_priv(netdev); 6593 + const struct mlx5e_profile *orig_profile; 6597 6594 int err, rollback_err; 6595 + void *orig_ppriv; 6598 6596 6599 - /* cleanup old profile */ 6600 - mlx5e_detach_netdev(priv); 6601 - priv->profile->cleanup(priv); 6602 - mlx5e_priv_cleanup(priv); 6597 + orig_profile = priv->profile; 6598 + orig_ppriv = priv->ppriv; 6599 + 6600 + /* NULL could happen if previous change_profile failed to rollback */ 6601 + if (priv->profile) { 6602 + WARN_ON_ONCE(priv->mdev != mdev); 6603 + /* cleanup old profile */ 6604 + mlx5e_detach_netdev(priv); 6605 + priv->profile->cleanup(priv); 6606 + mlx5e_priv_cleanup(priv); 6607 + } 6608 + /* priv members are not valid from this point ... */ 6603 6609 6604 6610 if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { 6605 6611 mlx5e_netdev_init_profile(netdev, mdev, new_profile, new_ppriv); ··· 6625 6613 return 0; 6626 6614 6627 6615 rollback: 6616 + if (!orig_profile) { 6617 + netdev_warn(netdev, "no original profile to rollback to\n"); 6618 + priv->profile = NULL; 6619 + return err; 6620 + } 6621 + 6628 6622 rollback_err = mlx5e_netdev_attach_profile(netdev, mdev, orig_profile, orig_ppriv); 6629 - if (rollback_err) 6630 - netdev_err(netdev, "%s: failed to rollback to orig profile, %d\n", 6631 - __func__, rollback_err); 6623 + if (rollback_err) { 6624 + netdev_err(netdev, "failed to rollback to orig profile, %d\n", 6625 + rollback_err); 6626 + priv->profile = NULL; 6627 + } 6632 6628 return err; 6633 6629 } 6634 6630 6635 - void mlx5e_netdev_attach_nic_profile(struct mlx5e_priv *priv) 6631 + void mlx5e_netdev_attach_nic_profile(struct net_device *netdev, 6632 + struct mlx5_core_dev *mdev) 6636 6633 { 6637 - mlx5e_netdev_change_profile(priv, &mlx5e_nic_profile, NULL); 6634 + mlx5e_netdev_change_profile(netdev, mdev, &mlx5e_nic_profile, NULL); 6638 6635 } 6639 6636 6640 - void mlx5e_destroy_netdev(struct mlx5e_priv *priv) 6637 + void mlx5e_destroy_netdev(struct net_device *netdev) 6641 6638 { 6642 - struct net_device *netdev = priv->netdev; 6639 + struct mlx5e_priv *priv = netdev_priv(netdev); 6643 6640 6644 - mlx5e_priv_cleanup(priv); 6641 + if (priv->profile) 6642 + mlx5e_priv_cleanup(priv); 6645 6643 free_netdev(netdev); 6646 6644 } 6647 6645 ··· 6659 6637 { 6660 6638 struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 6661 6639 struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev); 6662 - struct mlx5e_priv *priv = mlx5e_dev->priv; 6663 - struct net_device *netdev = priv->netdev; 6640 + struct mlx5e_priv *priv = netdev_priv(mlx5e_dev->netdev); 6641 + struct net_device *netdev = mlx5e_dev->netdev; 6664 6642 struct mlx5_core_dev *mdev = edev->mdev; 6665 6643 struct mlx5_core_dev *pos, *to; 6666 6644 int err, i; ··· 6706 6684 6707 6685 static int _mlx5e_suspend(struct auxiliary_device *adev, bool pre_netdev_reg) 6708 6686 { 6687 + struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 6709 6688 struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev); 6710 - struct mlx5e_priv *priv = mlx5e_dev->priv; 6711 - struct net_device *netdev = priv->netdev; 6712 - struct mlx5_core_dev *mdev = priv->mdev; 6689 + struct mlx5e_priv *priv = netdev_priv(mlx5e_dev->netdev); 6690 + struct net_device *netdev = mlx5e_dev->netdev; 6691 + struct mlx5_core_dev *mdev = edev->mdev; 6713 6692 struct mlx5_core_dev *pos; 6714 6693 int i; 6715 6694 ··· 6771 6748 goto err_devlink_port_unregister; 6772 6749 } 6773 6750 SET_NETDEV_DEVLINK_PORT(netdev, &mlx5e_dev->dl_port); 6751 + mlx5e_dev->netdev = netdev; 6774 6752 6775 6753 mlx5e_build_nic_netdev(netdev); 6776 6754 6777 6755 priv = netdev_priv(netdev); 6778 - mlx5e_dev->priv = priv; 6779 6756 6780 6757 priv->profile = profile; 6781 6758 priv->ppriv = NULL; ··· 6808 6785 err_profile_cleanup: 6809 6786 profile->cleanup(priv); 6810 6787 err_destroy_netdev: 6811 - mlx5e_destroy_netdev(priv); 6788 + mlx5e_destroy_netdev(netdev); 6812 6789 err_devlink_port_unregister: 6813 6790 mlx5e_devlink_port_unregister(mlx5e_dev); 6814 6791 err_devlink_unregister: ··· 6838 6815 { 6839 6816 struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev); 6840 6817 struct mlx5e_dev *mlx5e_dev = auxiliary_get_drvdata(adev); 6841 - struct mlx5e_priv *priv = mlx5e_dev->priv; 6818 + struct net_device *netdev = mlx5e_dev->netdev; 6819 + struct mlx5e_priv *priv = netdev_priv(netdev); 6842 6820 struct mlx5_core_dev *mdev = edev->mdev; 6843 6821 6844 6822 mlx5_core_uplink_netdev_set(mdev, NULL); 6845 - mlx5e_dcbnl_delete_app(priv); 6823 + 6824 + if (priv->profile) 6825 + mlx5e_dcbnl_delete_app(priv); 6846 6826 /* When unload driver, the netdev is in registered state 6847 6827 * if it's from legacy mode. If from switchdev mode, it 6848 6828 * is already unregistered before changing to NIC profile. 6849 6829 */ 6850 - if (priv->netdev->reg_state == NETREG_REGISTERED) { 6851 - unregister_netdev(priv->netdev); 6830 + if (netdev->reg_state == NETREG_REGISTERED) { 6831 + unregister_netdev(netdev); 6852 6832 _mlx5e_suspend(adev, false); 6853 6833 } else { 6854 6834 struct mlx5_core_dev *pos; ··· 6866 6840 /* Avoid cleanup if profile rollback failed. */ 6867 6841 if (priv->profile) 6868 6842 priv->profile->cleanup(priv); 6869 - mlx5e_destroy_netdev(priv); 6843 + mlx5e_destroy_netdev(netdev); 6870 6844 mlx5e_devlink_port_unregister(mlx5e_dev); 6871 6845 mlx5e_destroy_devlink(mlx5e_dev); 6872 6846 }
+7 -8
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
··· 1508 1508 { 1509 1509 struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); 1510 1510 struct net_device *netdev; 1511 - struct mlx5e_priv *priv; 1512 1511 int err; 1513 1512 1514 1513 netdev = mlx5_uplink_netdev_get(dev); 1515 1514 if (!netdev) 1516 1515 return 0; 1517 1516 1518 - priv = netdev_priv(netdev); 1519 - rpriv->netdev = priv->netdev; 1520 - err = mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile, 1521 - rpriv); 1517 + /* must not use netdev_priv(netdev), it might not be initialized yet */ 1518 + rpriv->netdev = netdev; 1519 + err = mlx5e_netdev_change_profile(netdev, dev, 1520 + &mlx5e_uplink_rep_profile, rpriv); 1522 1521 mlx5_uplink_netdev_put(dev, netdev); 1523 1522 return err; 1524 1523 } ··· 1545 1546 if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_SWITCH_LEGACY)) 1546 1547 unregister_netdev(netdev); 1547 1548 1548 - mlx5e_netdev_attach_nic_profile(priv); 1549 + mlx5e_netdev_attach_nic_profile(netdev, priv->mdev); 1549 1550 } 1550 1551 1551 1552 static int ··· 1611 1612 priv->profile->cleanup(priv); 1612 1613 1613 1614 err_destroy_netdev: 1614 - mlx5e_destroy_netdev(netdev_priv(netdev)); 1615 + mlx5e_destroy_netdev(netdev); 1615 1616 return err; 1616 1617 } 1617 1618 ··· 1666 1667 mlx5e_rep_vnic_reporter_destroy(priv); 1667 1668 mlx5e_detach_netdev(priv); 1668 1669 priv->profile->cleanup(priv); 1669 - mlx5e_destroy_netdev(priv); 1670 + mlx5e_destroy_netdev(netdev); 1670 1671 free_ppriv: 1671 1672 kvfree(ppriv); /* mlx5e_rep_priv */ 1672 1673 }