> -----Original Message-----
> From: Kitszel, Przemyslaw <[email protected]>
> Sent: Friday, September 25, 2026 3:16 PM
> To: [email protected]; Jakub Kicinski <[email protected]>
> Cc: Nguyen, Anthony L <[email protected]>; Loktionov,
> Aleksandr <[email protected]>; Schmidt, Michal
> <[email protected]>; [email protected];
> [email protected]; [email protected]; [email protected];
> [email protected]; Kitszel, Przemyslaw
> <[email protected]>
> Subject: [PATCH net v5 2/6] ice: extract __ice_vsi_free_stats()
> 
> Record the length of each ring stats array in struct ice_vsi_stats, so
> that freeing the array entries no longer needs the owning VSI. Keep
> the new fields in sync in both places that size the arrays.
> 
> With that, the body of ice_vsi_free_stats() becomes independent of the
> VSI and can be split out as __ice_vsi_free_stats(). The @free_entries
> parameter is always true here; a later commit adds a caller that frees
> only the array container, after its entries have been handed over to a
> freshly allocated stats structure.
> 
> The free path now stops at the recorded length instead of the VSI
> queue count, so it follows the real allocation rather than a number
> that can disagree with it. Sizing still does not: "ice: rebuild ring
> stats arrays instead of reallocating them in place" starts using the
> lengths to carry entries over, and only "ice: size ring stats arrays
> from the final queue count" makes them authoritative for the
> allocation path.
> 
> Signed-off-by: Przemek Kitszel <[email protected]>
> ---
> v5:
>  - drop the "no functional change intended" claim, the bound of the
> free
>    loop changes owner here (Clashiko)
>  - state that the recorded lengths govern only the free path at this
>    point in the series (Clashiko)
> ---
>  drivers/net/ethernet/intel/ice/ice.h     |  2 +
>  drivers/net/ethernet/intel/ice/ice_lib.c | 52 ++++++++++++++---------
> -
>  2 files changed, 33 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/ice/ice.h
> b/drivers/net/ethernet/intel/ice/ice.h
> index db3c7015c56c..fadfe94bf1c8 100644
> --- a/drivers/net/ethernet/intel/ice/ice.h
> +++ b/drivers/net/ethernet/intel/ice/ice.h
> @@ -328,6 +328,8 @@ enum ice_vsi_state {  struct ice_vsi_stats {
>       struct ice_ring_stats **tx_ring_stats;  /* Tx ring stats array
> */
>       struct ice_ring_stats **rx_ring_stats;  /* Rx ring stats array
> */
> +     u16 tx_ring_stats_len;  /* Length of the Tx ring stats array */
> +     u16 rx_ring_stats_len;  /* Length of the Rx ring stats array */
>  };
> 
>  /* struct that defines a VSI, associated with a dev */ diff --git
> a/drivers/net/ethernet/intel/ice/ice_lib.c
> b/drivers/net/ethernet/intel/ice/ice_lib.c
> index 31af378aa0e7..1414127d32cd 100644
> --- a/drivers/net/ethernet/intel/ice/ice_lib.c
> +++ b/drivers/net/ethernet/intel/ice/ice_lib.c
> @@ -330,42 +330,48 @@ static void ice_vsi_free_arrays(struct ice_vsi
> *vsi)
>       vsi->rxq_map = NULL;
>  }
> 
> +/* free single stats memory */
> +static void __ice_vsi_free_stats(struct ice_vsi_stats *vsi_stat, bool
> +free_entries) {
> +     if (!vsi_stat)
> +             return;
> +
> +     if (free_entries) {
> +             for (int i = 0; i < vsi_stat->tx_ring_stats_len; i++) {
> +                     if (vsi_stat->tx_ring_stats[i]) {
> +                             kfree_rcu(vsi_stat->tx_ring_stats[i], rcu);
> +                             WRITE_ONCE(vsi_stat->tx_ring_stats[i],
> NULL);
> +                     }
> +             }
> +             for (int i = 0; i < vsi_stat->rx_ring_stats_len; i++) {
> +                     if (vsi_stat->rx_ring_stats[i]) {
> +                             kfree_rcu(vsi_stat->rx_ring_stats[i], rcu);
> +                             WRITE_ONCE(vsi_stat->rx_ring_stats[i],
> NULL);
> +                     }
> +             }
> +     }
> +
> +     kfree(vsi_stat->tx_ring_stats);
> +     kfree(vsi_stat->rx_ring_stats);
> +     kfree(vsi_stat);
> +}
> +
>  /**
>   * ice_vsi_free_stats - Free the ring statistics structures
>   * @vsi: VSI pointer
>   */
>  static void ice_vsi_free_stats(struct ice_vsi *vsi)  {
>       struct ice_vsi_stats *vsi_stat;
>       struct ice_pf *pf = vsi->back;
> -     int i;
> 
>       if (vsi->type == ICE_VSI_CHNL)
>               return;
>       if (!pf->vsi_stats)
>               return;
> 
>       vsi_stat = pf->vsi_stats[vsi->idx];
> -     if (!vsi_stat)
> -             return;
> -
> -     ice_for_each_alloc_txq(vsi, i) {
> -             if (vsi_stat->tx_ring_stats[i]) {
> -                     kfree_rcu(vsi_stat->tx_ring_stats[i], rcu);
> -                     WRITE_ONCE(vsi_stat->tx_ring_stats[i], NULL);
> -             }
> -     }
> -
> -     ice_for_each_alloc_rxq(vsi, i) {
> -             if (vsi_stat->rx_ring_stats[i]) {
> -                     kfree_rcu(vsi_stat->rx_ring_stats[i], rcu);
> -                     WRITE_ONCE(vsi_stat->rx_ring_stats[i], NULL);
> -             }
> -     }
> -
> -     kfree(vsi_stat->tx_ring_stats);
> -     kfree(vsi_stat->rx_ring_stats);
> -     kfree(vsi_stat);
> +     __ice_vsi_free_stats(vsi_stat, true);
>       pf->vsi_stats[vsi->idx] = NULL;
>  }
> 
> @@ -539,11 +545,13 @@ static int ice_vsi_alloc_stat_arrays(struct
> ice_vsi *vsi)
>               kzalloc_objs(*vsi_stat->tx_ring_stats, vsi->alloc_txq);
>       if (!vsi_stat->tx_ring_stats)
>               goto err_alloc_tx;
> +     vsi_stat->tx_ring_stats_len = vsi->alloc_txq;
> 
>       vsi_stat->rx_ring_stats =
>               kzalloc_objs(*vsi_stat->rx_ring_stats, vsi->alloc_rxq);
>       if (!vsi_stat->rx_ring_stats)
>               goto err_alloc_rx;
> +     vsi_stat->rx_ring_stats_len = vsi->alloc_rxq;
> 
>       pf->vsi_stats[vsi->idx] = vsi_stat;
> 
> @@ -3055,6 +3063,7 @@ ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi)
>               vsi_stat->tx_ring_stats = tx_ring_stats;
>               return -ENOMEM;
>       }
> +     vsi_stat->tx_ring_stats_len = req_txq;
> 
>       if (req_rxq < prev_rxq) {
>               for (i = req_rxq; i < prev_rxq; i++) { @@ -3074,6
> +3083,7 @@ ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi)
>               vsi_stat->rx_ring_stats = rx_ring_stats;
>               return -ENOMEM;
>       }
> +     vsi_stat->rx_ring_stats_len = req_rxq;
> 
>       return 0;
>  }
> --
> 2.51.1

Reviewed-by: Aleksandr Loktionov <[email protected]>

Reply via email to