? sys/arch/amd64/conf/MYKERNEL
Index: sys/dev/pci/if_iwm.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.87
diff -u -u -p -r1.87 if_iwm.c
--- sys/dev/pci/if_iwm.c	24 Jun 2021 09:17:53 -0000	1.87
+++ sys/dev/pci/if_iwm.c	4 Aug 2023 15:03:34 -0000
@@ -150,6 +150,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_iwm.c,v 1
 #define le16_to_cpup(_a_) (le16toh(*(const uint16_t *)(_a_)))
 #define le32_to_cpup(_a_) (le32toh(*(const uint32_t *)(_a_)))
 
+#define IWM_DEBUG
+
 #ifdef IWM_DEBUG
 #define DPRINTF(x)	do { if (iwm_debug > 0) printf x; } while (0)
 #define DPRINTFN(n, x)	do { if (iwm_debug >= (n)) printf x; } while (0)
@@ -4063,7 +4065,7 @@ iwm_rx_tx_cmd(struct iwm_softc *sc, stru
 	bus_dmamap_sync(sc->sc_dmat, data->map, 0, IWM_RBUF_SIZE,
 	    BUS_DMASYNC_POSTREAD);
 
-	sc->sc_tx_timer = 0;
+	sc->sc_tx_timer[qid] = 0;
 
 	iwm_rx_tx_cmd_single(sc, pkt, in);
 
@@ -6863,7 +6865,7 @@ iwm_start(struct ifnet *ifp)
 		}
 
 		if (ifp->if_flags & IFF_UP) {
-			sc->sc_tx_timer = 15;
+			sc->sc_tx_timer[ac] = 15;
 			ifp->if_timer = 1;
 		}
 	}
@@ -6889,7 +6891,8 @@ iwm_stop(struct ifnet *ifp, int disable)
 
 	callout_stop(&sc->sc_calib_to);
 	iwm_led_blink_stop(sc);
-	ifp->if_timer = sc->sc_tx_timer = 0;
+    memset(sc->sc_tx_timer, 0, sizeof(sc->sc_tx_timer));
+	ifp->if_timer = 0;
 	iwm_stop_device(sc);
 }
 
@@ -6899,18 +6902,25 @@ iwm_watchdog(struct ifnet *ifp)
 	struct iwm_softc *sc = ifp->if_softc;
 
 	ifp->if_timer = 0;
-	if (sc->sc_tx_timer > 0) {
-		if (--sc->sc_tx_timer == 0) {
-			aprint_error_dev(sc->sc_dev, "device timeout\n");
+    /*
+	 * We maintain a separate timer for each Tx queue because
+	 * Tx aggregation queues can get "stuck" while other queues
+	 * keep working. The Linux and OpenBSD drivers use a similar workaround.
+	 */
+	for (int i = 0; i < IWM_MAX_QUEUES; i++) {
+        if (sc->sc_tx_timer[i] > 0) {
+            if (--sc->sc_tx_timer[i] == 0) {
+                aprint_error_dev(sc->sc_dev, "device timeout\n");
 #ifdef IWM_DEBUG
-			iwm_nic_error(sc);
+                iwm_nic_error(sc);
 #endif
-			ifp->if_flags &= ~IFF_UP;
-			iwm_stop(ifp, 1);
-			if_statinc(ifp, if_oerrors);
-			return;
-		}
-		ifp->if_timer = 1;
+                ifp->if_flags &= ~IFF_UP;
+                iwm_stop(ifp, 1);
+                if_statinc(ifp, if_oerrors);
+                return;
+            }
+            ifp->if_timer = 1;
+        }
 	}
 
 	ieee80211_watchdog(&sc->sc_ic);
Index: sys/dev/pci/if_iwmvar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_iwmvar.h,v
retrieving revision 1.20
diff -u -u -p -r1.20 if_iwmvar.h
--- sys/dev/pci/if_iwmvar.h	22 May 2020 20:27:16 -0000	1.20
+++ sys/dev/pci/if_iwmvar.h	4 Aug 2023 15:03:34 -0000
@@ -454,7 +454,7 @@ struct iwm_softc {
 
 	struct iwm_bf_data sc_bf;
 
-	int sc_tx_timer;
+	int sc_tx_timer[IWM_MAX_QUEUES];
 	int sc_rx_ba_sessions;
 
 	int sc_scan_last_antenna;
