i40e_vsi_setup() registers the netdev before rings and q_vectors are fully allocated and mapped. Once register_netdev() returns, userspace can reach netdev callbacks such as ndo_open(), so the VSI backing state must already be ready. Move register_netdev() to the end of the setup path, after ring/q_vector allocation, ring mapping and RSS configuration. Keep freeing an allocated but not registered netdev on the error path. Fixes: 41c445ff0f48 ("i40e: main driver core") Reported-by: Sashiko AI Review Signed-off-by: Maciej Fijalkowski --- drivers/net/ethernet/intel/i40e/i40e_main.c | 29 ++++++++++++--------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index fcdd13af08ea..a9ec53cfd905 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -14454,15 +14454,6 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, goto err_netdev; SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port); } - ret = register_netdev(vsi->netdev); - if (ret) - goto err_dl_port; - vsi->netdev_registered = true; - netif_carrier_off(vsi->netdev); -#ifdef CONFIG_I40E_DCB - /* Setup DCB netlink interface */ - i40e_dcbnl_setup(vsi); -#endif /* CONFIG_I40E_DCB */ fallthrough; case I40E_VSI_FDIR: /* set up vectors and rings if needed */ @@ -14490,6 +14481,19 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, if (ret) goto err_config; } + + if (vsi->netdev) { + ret = register_netdev(vsi->netdev); + if (ret) + goto err_config; + vsi->netdev_registered = true; + netif_carrier_off(vsi->netdev); +#ifdef CONFIG_I40E_DCB + /* Setup DCB netlink interface */ + i40e_dcbnl_setup(vsi); +#endif /* CONFIG_I40E_DCB */ + } + return vsi; err_config: @@ -14500,13 +14504,14 @@ struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type, if (vsi->netdev_registered) { vsi->netdev_registered = false; unregister_netdev(vsi->netdev); - free_netdev(vsi->netdev); - vsi->netdev = NULL; } -err_dl_port: if (vsi->type == I40E_VSI_MAIN) i40e_devlink_destroy_port(pf); err_netdev: + if (vsi->netdev) { + free_netdev(vsi->netdev); + vsi->netdev = NULL; + } i40e_aq_delete_element(&pf->hw, vsi->seid, NULL); err_vsi: i40e_vsi_clear(vsi); -- 2.43.0