git: b71d79c270ff - stable/15 - iwm: mask closed_rb_num to the RX ring size

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Fri, 30 Oct 2026 17:39:00 UTC
The branch stable/15 has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=b71d79c270ff7561838cd7dfd2abb8b000cd4d64

commit b71d79c270ff7561838cd7dfd2abb8b000cd4d64
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2026-10-17 21:32:51 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-10-30 17:38:26 +0000

    iwm: mask closed_rb_num to the RX ring size
    
    iwm_notif_intr() reads hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff and
    loops while (sc->rxq.cur != hw) without masking hw to the ring size (512 entries
    for 9000-series MQ RX, 256 for legacy). If the hardware reports a value at or
    above the ring size, cur never equals hw: the loop walks stale ring entries
    indefinitely and the write-pointer update uses a bogus index. Linux iwlwifi
    masks the value (5eae443eb5e2) and OpenBSD has done the same since 9000-series
    support was added (3287dca4fa10).
    
    This was found while debugging an iwm crash on another BSD using the same
    driver lineage (DragonFly, upstream bug 3449)
    
    Locally tested:
    
    * 7260, 9260, STA mode
    
    PR: kern/299427
    Submitted by: David Bidner <david@crap.solutions>
    
    Differential Revision:  https://reviews.freebsd.org/D60824
    
    (cherry picked from commit 461da47e45e7f8ef8754875f4820d3855e7f4097)
---
 sys/dev/iwm/if_iwm.c    | 2 ++
 sys/dev/iwm/if_iwmvar.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c
index 1e9090310ece..e07879ee0291 100644
--- a/sys/dev/iwm/if_iwm.c
+++ b/sys/dev/iwm/if_iwm.c
@@ -5640,6 +5640,8 @@ iwm_notif_intr(struct iwm_softc *sc)
 	}
 
 	hw = le16toh(sc->rxq.stat->closed_rb_num) & 0xfff;
+	/* Mask the returned value to the hardware ring size */
+	hw &= (count - 1);
 
 	/*
 	 * Process responses
diff --git a/sys/dev/iwm/if_iwmvar.h b/sys/dev/iwm/if_iwmvar.h
index f31057c07b9b..c7d5efe6bb95 100644
--- a/sys/dev/iwm/if_iwmvar.h
+++ b/sys/dev/iwm/if_iwmvar.h
@@ -285,6 +285,7 @@ struct iwm_tx_ring {
 	int			cur;
 };
 
+/* Note: these are used as a mask; must be a power of 2 */
 #define IWM_RX_LEGACY_RING_COUNT	256
 #define IWM_RX_MQ_RING_COUNT		512