RE: [PATCH iwl-net v2 2/2] ice: release the VF MSI-X window when ice_start_vfs() fails

From: Loktionov, Aleksandr

Date: Mon Sep 28 2026 - 11:20:01 EST




> -----Original Message-----
> From: Linkui Xiao <xiaolinkui@xxxxxxx>
> Sent: Monday, September 28, 2026 8:53 AM
> To: Nguyen, Anthony L <anthony.l.nguyen@xxxxxxxxx>; Kitszel,
> Przemyslaw <przemyslaw.kitszel@xxxxxxxxx>; andrew+netdev@xxxxxxx;
> davem@xxxxxxxxxxxxx; edumazet@xxxxxxxxxx; kuba@xxxxxxxxxx;
> pabeni@xxxxxxxxxx
> Cc: intel-wired-lan@xxxxxxxxxxxxxxxx; netdev@xxxxxxxxxxxxxxx; linux-
> kernel@xxxxxxxxxxxxxxx; Linkui Xiao <xiaolinkui@xxxxxxxxxx>;
> stable@xxxxxxxxxxxxxxx
> Subject: [PATCH iwl-net v2 2/2] ice: release the VF MSI-X window when
> ice_start_vfs() fails
>
> From: Linkui Xiao <xiaolinkui@xxxxxxxxxx>
>
> ice_init_vf_vsi_res() reserves the VF MSI-X window with
> ice_virt_get_irqs(), which does bitmap_set() on the PF-wide
> pf->virt_irq_tracker.bm, but nothing hands that window back when VF
> creation fails. ice_virt_free_irqs() is not called anywhere on this
> failure path: not from the release_vsi label of ice_init_vf_vsi_res(),
> not from the ice_eswitch_attach_vf() failure branch, and not from the
> teardown loop of ice_start_vfs(), which only undoes the queue mappings
> and the VF VSI. The caller does not help either, because
> err_unroll_vf_entries -> ice_free_vf_entries() -> ice_put_vf() ->
> ice_sriov_free_vf() only does mutex_destroy() and kfree_rcu().
>
> The tracker is allocated once per PF in ice_init_virt_irq_tracker()
> and freed only in ice_deinit_virt_irq_tracker(), and
> ice_set_per_vf_res() sizes the VFs from pf-
> >virt_irq_tracker.num_entries rather than from the number of free
> bits. So each failed "echo N > sriov_numvfs" leaks the window reserved
> for every VF that got as far as ice_init_vf_vsi_res(), and once the
> tracker is exhausted ice_virt_get_irqs() keeps returning -ENOENT,
> which means SR-IOV cannot be enabled again without reloading the
> driver. The hardware and the software bookkeeping also end up
> disagreeing, because ice_dis_vf_mappings() clears
> VPINT_ALLOC/VPINT_ALLOC_PCI and re-points GLINT_VECT2FUNC of exactly
> those vectors back at the PF.
>
> Return the window on the failure paths, in the order ice_free_vfs()
> uses: ice_virt_free_irqs() after ice_eswitch_detach_vf() in the
> teardown loop, and right after the VF VSI is released in the two
> branches that fail before the loop can reach that VF.
>
> The missing release is older than this change: the teardown loop has
> never returned the window. It turns into an accumulating leak because
> the tracker is now PF-wide and outlives a single SR-IOV enable.
>
> Fixes: a203163274a4 ("ice: simplify VF MSI-X managing")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Linkui Xiao <xiaolinkui@xxxxxxxxxx>
> ---
> Changes in v2:
> - New patch. Returns the VF MSI-X window that ice_init_vf_vsi_res()
> reserves
> when ice_start_vfs() fails. The missing release is older than the
> representor bug that patch 1/2 fixes, so it stays a separate patch.
> (Sashiko AI review)
>
> drivers/net/ethernet/intel/ice/ice_sriov.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c
> b/drivers/net/ethernet/intel/ice/ice_sriov.c
> index 95abc6704820..df84dbe12cba 100644
> --- a/drivers/net/ethernet/intel/ice/ice_sriov.c
> +++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
> @@ -446,8 +446,10 @@ static int ice_init_vf_vsi_res(struct ice_vf *vf)
> return -ENOMEM;
>
> vsi = ice_vf_vsi_setup(vf);
> - if (!vsi)
> - return -ENOMEM;
> + if (!vsi) {
> + err = -ENOMEM;
> + goto free_irqs;
> + }
>
> err = ice_vf_init_host_cfg(vf, vsi);
> if (err)
> @@ -457,6 +459,9 @@ static int ice_init_vf_vsi_res(struct ice_vf *vf)
>
> release_vsi:
> ice_vf_vsi_release(vf);
> +free_irqs:
> + ice_virt_free_irqs(pf, vf->first_vector_idx, vf->num_msix);
> +
> return err;
> }
>
> @@ -490,6 +495,8 @@ static int ice_start_vfs(struct ice_pf *pf)
> dev_err(ice_pf_to_dev(pf), "Failed to
> attach VF %d to eswitch, error %d",
> vf->vf_id, retval);
> ice_vf_vsi_release(vf);
> + ice_virt_free_irqs(pf, vf-
> >first_vector_idx,
> + vf->num_msix);
> goto teardown;
> }
> }
> @@ -511,6 +518,7 @@ static int ice_start_vfs(struct ice_pf *pf)
> mutex_lock(&vf->cfg_lock);
>
> ice_eswitch_detach_vf(pf, vf);
> + ice_virt_free_irqs(pf, vf->first_vector_idx, vf-
> >num_msix);
> ice_dis_vf_mappings(vf);
> ice_vf_vsi_release(vf);
> mutex_unlock(&vf->cfg_lock);
> --
> 2.25.1

Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@xxxxxxxxx>