ice_vsi_alloc_stat_arrays() returns early for ICE_VSI_CHNL, so a channel
VSI never gets an entry in pf->vsi_stats[]. ice_vsi_realloc_stat_arrays()
dereferences that entry unconditionally, and ice_vsi_rebuild() calls it
before anything else, so the NULL is not filtered out anywhere.
The path is live. ice_prepare_for_reset() removes the queue channels only
for resets other than a PFR, so a PFR leaves the channel VSIs in place,
and ice_rebuild() then calls ice_rebuild_channels(), which rebuilds every
ICE_VSI_CHNL VSI it finds. A PF reset with ADQ (mqprio hardware offload)
configured thus dereferences NULL.
That combination is reset recovery on top of an active mqprio offload,
which is why it went unnoticed. It was found while refactoring this code,
not reported by a user.
I'm leaning towards removing our limited (compared to OOT ADQ) support,
but it's outside of this series. Bug could be triggered by:
tc qdisc del dev "$IF" root 2>/dev/null || true
tc qdisc add dev "$IF" root mqprio num_tc 2 \
map 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 \
queues 2@0 2@2 hw 1 mode channel
sleep 3
ethtool --reset "$IF" irq dma filter offload
Workqueue: ice ice_service_task [ice]
RIP: 0010:ice_vsi_rebuild+0x289/0x380 [ice]
ice_rebuild_channels+0xd6/0x320 [ice]
ice_rebuild+0x4f6/0x540 [ice]
ice_do_reset+0x9f/0x1a0 [ice]
ice_service_task+0x4a/0x460 [ice]
Fixes: 5995ef88e3a8 ("ice: realloc VSI stats arrays")
Signed-off-by: Przemek Kitszel <[email protected]>
---
v5: new patch, split out of "ice: rebuild ring stats arrays instead of
reallocating them in place" (Clashiko)
---
drivers/net/ethernet/intel/ice/ice_lib.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c
b/drivers/net/ethernet/intel/ice/ice_lib.c
index 9e08db376d3d..31af378aa0e7 100644
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -3031,6 +3031,10 @@ ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi)
u16 prev_rxq = vsi->alloc_rxq;
int i;
+ /* channel VSIs have no entry in pf->vsi_stats[] */
+ if (vsi->type == ICE_VSI_CHNL)
+ return 0;
+
vsi_stat = pf->vsi_stats[vsi->idx];
if (req_txq < prev_txq) {
--
2.51.1