> -----Original Message-----
> From: Intel-wired-lan <[email protected]> On Behalf
> Of Maciej Fijalkowski
> Sent: Wednesday, July 1, 2026 2:45 PM
> To: [email protected]
> Cc: [email protected]; Karlsson, Magnus
> <[email protected]>; [email protected]; [email protected];
> [email protected]; Kitszel, Przemyslaw <[email protected]>;
> Keller, Jacob E <[email protected]>; Fijalkowski, Maciej
> <[email protected]>; Sashiko AI Review <sashiko-
> [email protected]>
> Subject: [Intel-wired-lan] [PATCH v5 net 4/7] i40e: avoid deadlock
> when calling unregister_netdev()
>
> Sashiko reports:
> ***
> > +err_netdev:
> > if (vsi->netdev_registered) {
> > vsi->netdev_registered = false;
> > unregister_netdev(vsi->netdev);
> Could this result in a deadlock when called during a device rebuild?
> Looking at i40e_rebuild(), it explicitly acquires the RTNL lock before
> proceeding:
> drivers/net/ethernet/intel/i40e/i40e_main.c:i40e_rebuild() {
> ...
> if (!lock_acquired)
> rtnl_lock();
> ret = i40e_setup_pf_switch(pf, reinit, true);
> ...
> }
> If i40e_setup_pf_switch() calls i40e_vsi_reinit_setup() and takes this
> new err_netdev path, unregister_netdev() will unconditionally attempt
> to acquire rtnl_lock(), leading to a deadlock on the non-recursive
> mutex.
> ***
>
> Use unregister_netdevice() when the rebuild path already holds RTNL,
> and keep unregister_netdev() for callers that do not. This avoids both
> recursive RTNL locking and dropping RTNL in the middle of the VSI
> unwind path.
>
> Fixes: bc7d338fbb3f ("i40e: reinit flow for the main VSI")
> Reported-by: Sashiko AI Review <[email protected]>
> Signed-off-by: Maciej Fijalkowski <[email protected]>
> ---
> drivers/net/ethernet/intel/i40e/i40e_main.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c
> b/drivers/net/ethernet/intel/i40e/i40e_main.c
> index a29a89192a7a..e88cf7cfbd84 100644
> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> @@ -14257,7 +14257,8 @@ static int i40e_vsi_setup_vectors(struct
> i40e_vsi *vsi)
> * Returns pointer to the successfully allocated and configured VSI
> sw struct
> * on success, otherwise returns NULL on failure.
> **/
> -static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi)
> +static struct i40e_vsi *i40e_vsi_reinit_setup(struct i40e_vsi *vsi,
> + bool lock_acquired)
> {
> struct i40e_vsi *main_vsi;
> u16 alloc_queue_pairs;
> @@ -14314,7 +14315,10 @@ static struct i40e_vsi
> *i40e_vsi_reinit_setup(struct i40e_vsi *vsi)
> err_netdev:
> if (vsi->netdev_registered) {
> vsi->netdev_registered = false;
> - unregister_netdev(vsi->netdev);
> + if (lock_acquired)
> + unregister_netdevice(vsi->netdev);
> + else
> + unregister_netdev(vsi->netdev);
> free_netdev(vsi->netdev);
> vsi->netdev = NULL;
> }
> @@ -15036,7 +15040,7 @@ static int i40e_setup_pf_switch(struct i40e_pf
> *pf, bool reinit, bool lock_acqui
> main_vsi = i40e_vsi_setup(pf, I40E_VSI_MAIN,
> uplink_seid, 0);
> else if (reinit)
> - main_vsi = i40e_vsi_reinit_setup(main_vsi);
> + main_vsi = i40e_vsi_reinit_setup(main_vsi,
> lock_acquired);
> if (!main_vsi) {
> dev_info(&pf->pdev->dev, "setup of MAIN VSI
> failed\n");
> i40e_cloud_filter_exit(pf);
> --
> 2.43.0
Reviewed-by: Aleksandr Loktionov <[email protected]>