| Message ID | 20260928065306.1514795-2-xiaolinkui@126.com |
|---|---|
| State | Superseded |
| Headers | show |
| Series | [iwl-net,v2,1/2] ice: detach the VF representor when ice_start_vfs() fails | expand |
On 28.09.2026 08:53, Linkui Xiao wrote: > 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); Nit: For consistency with the teardown: loop (which frees IRQs before releasing the VSI), consider swapping the order here too - currently this branch releases the VSI first, then frees IRQs, the opposite order. Not functionally significant, just readability. > goto teardown; > } > } Reviewed-by: Tomasz Lichwala <tomasz.lichwala@linux.intel.com>
> -----Original Message----- > From: Linkui Xiao <xiaolinkui@126.com> > Sent: Monday, September 28, 2026 8:53 AM > To: Nguyen, Anthony L <anthony.l.nguyen@intel.com>; Kitszel, > Przemyslaw <przemyslaw.kitszel@intel.com>; andrew+netdev@lunn.ch; > davem@davemloft.net; edumazet@google.com; kuba@kernel.org; > pabeni@redhat.com > Cc: intel-wired-lan@lists.osuosl.org; netdev@vger.kernel.org; linux- > kernel@vger.kernel.org; Linkui Xiao <xiaolinkui@kylinos.cn>; > stable@vger.kernel.org > Subject: [PATCH iwl-net v2 2/2] ice: release the VF MSI-X window when > ice_start_vfs() fails > > From: Linkui Xiao <xiaolinkui@kylinos.cn> > > 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@vger.kernel.org > Signed-off-by: Linkui Xiao <xiaolinkui@kylinos.cn> > --- > 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@intel.com>
On 2026/9/28 21:08, Tomasz Lichwala wrote: > > > On 28.09.2026 08:53, Linkui Xiao wrote: > >> 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); > > Nit: For consistency with the teardown: loop (which frees IRQs before releasing the VSI), consider swapping the order here too - currently this branch releases the VSI first, then frees IRQs, the opposite order. Not functionally significant, just readability. Thanks for the review, Tomasz. Agreed this is only a readability nit. The two calls are independent and the current order is functionally safe, so I'll keep v2 as is. No v3 planned for this change. Thanks, Linkui > >> goto teardown; >> } >> } > > Reviewed-by: Tomasz Lichwala <tomasz.lichwala@linux.intel.com> >
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);