Download raw body.
First batch of qwz backports and fixes
Stefan,
here the first batch of my series fixes for qwz.
I used git format-patch format to keep all 10 planned commits in a form
which can be applied, read and audited.
It is focuses on memory correctenese and task guards.
It contains 8 backports and two new fixes.
Tested on my qwz device, after I've applied it, it still connects to wifi
and network seems to work stable.
Ok?
From 185033fda81a90cddd2fa3adbe928a26c0bf8f98 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:57:54 +0200
Subject: [PATCH 01/10] sys/qwz: reject state changes while stopped
Backport sys/dev/ic/qwx.c,v 1.75 and following fix from v 1.123
---
sys/dev/ic/qwz.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index b7cf65d7f33..95a3a2ac36c 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -859,6 +859,11 @@ qwz_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
struct ifnet *ifp = &ic->ic_if;
struct qwz_softc *sc = ifp->if_softc;
+ /* We may get triggered by received frames during qwz_stop(). */
+ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags) ||
+ !(ifp->if_flags & IFF_RUNNING))
+ return 0;
+
/*
* Prevent attempts to transition towards the same state, unless
* we are scanning in which case a SCAN -> SCAN transition
--
2.55.0
From 40ca9f19bb9bb5fab0ece54614c54f9b91b51cfe Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:57:57 +0200
Subject: [PATCH 02/10] sys/qwz: retain active key task arguments
Remove active key operations from the pending queue before waiting
for firmware, retaining their node reference and a local key copy.
Recheck association state after waits before updating key state or
marking the port valid.
---
sys/dev/ic/qwz.c | 47 +++++++++++++++++++++++++++++++++++------------
1 file changed, 35 insertions(+), 12 deletions(-)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index 95a3a2ac36c..d34db2918f7 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -743,6 +743,12 @@ qwz_add_sta_key(struct qwz_softc *sc, struct ieee80211_node *ni,
return ret;
}
+ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags) ||
+ (ic->ic_if.if_flags & IFF_RUNNING) == 0 ||
+ ic->ic_state != IEEE80211_S_RUN ||
+ sc->ns_nstate != IEEE80211_S_RUN)
+ return ESHUTDOWN;
+
ret = qwz_dp_peer_rx_pn_replay_config(sc, arvif, ni, k, 0);
if (ret) {
printf("%s: failed to offload PN replay detection %d\n",
@@ -767,6 +773,12 @@ qwz_add_sta_key(struct qwz_softc *sc, struct ieee80211_node *ni,
return ret;
}
+ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags) ||
+ (ic->ic_if.if_flags & IFF_RUNNING) == 0 ||
+ ic->ic_state != IEEE80211_S_RUN ||
+ sc->ns_nstate != IEEE80211_S_RUN)
+ return ESHUTDOWN;
+
ni->ni_port_valid = 1;
ieee80211_set_link_state(ic, LINK_STATE_UP);
}
@@ -778,6 +790,7 @@ int
qwz_del_sta_key(struct qwz_softc *sc, struct ieee80211_node *ni,
struct ieee80211_key *k)
{
+ struct ieee80211com *ic = &sc->sc_ic;
struct qwz_node *nq = (struct qwz_node *)ni;
struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
int ret = 0;
@@ -789,6 +802,12 @@ qwz_del_sta_key(struct qwz_softc *sc, struct ieee80211_node *ni,
return ret;
}
+ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags) ||
+ (ic->ic_if.if_flags & IFF_RUNNING) == 0 ||
+ ic->ic_state != IEEE80211_S_RUN ||
+ sc->ns_nstate != IEEE80211_S_RUN)
+ return ESHUTDOWN;
+
ret = qwz_dp_peer_rx_pn_replay_config(sc, arvif, ni, k, 1);
if (ret) {
printf("%s: failed to disable PN replay detection %d\n",
@@ -809,26 +828,30 @@ qwz_setkey_task(void *arg)
{
struct qwz_softc *sc = arg;
struct ieee80211com *ic = &sc->sc_ic;
- struct qwz_setkey_task_arg *a;
+ struct qwz_setkey_task_arg a;
+ struct ieee80211_key k;
int err = 0, s = splnet();
while (sc->setkey_nkeys > 0) {
if (err || test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags))
break;
- a = &sc->setkey_arg[sc->setkey_tail];
- KASSERT(a->cmd == QWZ_ADD_KEY || a->cmd == QWZ_DEL_KEY);
- if (ic->ic_state == IEEE80211_S_RUN) {
- if (a->cmd == QWZ_ADD_KEY)
- err = qwz_add_sta_key(sc, a->ni, a->k);
- else
- err = qwz_del_sta_key(sc, a->ni, a->k);
- }
- ieee80211_release_node(ic, a->ni);
- a->ni = NULL;
- a->k = NULL;
+ a = sc->setkey_arg[sc->setkey_tail];
+ memset(&sc->setkey_arg[sc->setkey_tail], 0,
+ sizeof(sc->setkey_arg[sc->setkey_tail]));
sc->setkey_tail = (sc->setkey_tail + 1) %
nitems(sc->setkey_arg);
sc->setkey_nkeys--;
+ KASSERT(a.cmd == QWZ_ADD_KEY || a.cmd == QWZ_DEL_KEY);
+ if (ic->ic_state == IEEE80211_S_RUN &&
+ sc->ns_nstate == IEEE80211_S_RUN) {
+ k = *a.k;
+ if (a.cmd == QWZ_ADD_KEY)
+ err = qwz_add_sta_key(sc, a.ni, &k);
+ else
+ err = qwz_del_sta_key(sc, a.ni, &k);
+ explicit_bzero(&k, sizeof(k));
+ }
+ ieee80211_release_node(ic, a.ni);
}
refcnt_rele_wake(&sc->task_refs);
--
2.55.0
From 7d66b6fb2d910c6aeb88a2e3a24eb44a3c549d2a Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:58:00 +0200
Subject: [PATCH 03/10] sys/qwz: release HTT node references
Backport of sys/dev/ic/qwx.c,v 1.81
---
sys/dev/ic/qwz.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index d34db2918f7..eb47f846a12 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -14249,6 +14249,7 @@ void
qwz_dp_tx_free_txbuf(struct qwz_softc *sc, int msdu_id,
struct dp_tx_ring *tx_ring)
{
+ struct ieee80211com *ic = &sc->sc_ic;
struct qwz_tx_data *tx_data;
if (msdu_id >= sc->hw_params.tx_ring_size)
@@ -14260,6 +14261,9 @@ qwz_dp_tx_free_txbuf(struct qwz_softc *sc, int msdu_id,
m_freem(tx_data->m);
tx_data->m = NULL;
+ ieee80211_release_node(ic, tx_data->ni);
+ tx_data->ni = NULL;
+
if (tx_ring->queued > 0)
tx_ring->queued--;
}
--
2.55.0
From 90d71f756643e6bcc2762e4b9a6c947c963ab85d Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:58:03 +0200
Subject: [PATCH 04/10] sys/qwz: guard reclaimed TX slots
Backport of sys/dev/ic/qwx.c,v 1.82
---
sys/dev/ic/qwz.c | 41 ++++++++++++++++++++++++++---------------
1 file changed, 26 insertions(+), 15 deletions(-)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index eb47f846a12..9a510adc8ea 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -14257,15 +14257,21 @@ qwz_dp_tx_free_txbuf(struct qwz_softc *sc, int msdu_id,
tx_data = &tx_ring->data[msdu_id];
- bus_dmamap_unload(sc->sc_dmat, tx_data->map);
- m_freem(tx_data->m);
- tx_data->m = NULL;
+ if (tx_data->m) {
+ bus_dmamap_sync(sc->sc_dmat, tx_data->map, 0,
+ tx_data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, tx_data->map);
+ m_freem(tx_data->m);
+ tx_data->m = NULL;
- ieee80211_release_node(ic, tx_data->ni);
- tx_data->ni = NULL;
+ if (tx_ring->queued > 0)
+ tx_ring->queued--;
+ }
- if (tx_ring->queued > 0)
- tx_ring->queued--;
+ if (tx_data->ni) {
+ ieee80211_release_node(ic, tx_data->ni);
+ tx_data->ni = NULL;
+ }
}
void
@@ -14401,11 +14407,19 @@ qwz_dp_tx_complete_msdu(struct qwz_softc *sc, struct dp_tx_ring *tx_ring,
return;
}
- bus_dmamap_sync(sc->sc_dmat, tx_data->map, 0,
- tx_data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->sc_dmat, tx_data->map);
- m_freem(tx_data->m);
- tx_data->m = NULL;
+ if (tx_data->m) {
+ bus_dmamap_sync(sc->sc_dmat, tx_data->map, 0,
+ tx_data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, tx_data->map);
+ m_freem(tx_data->m);
+ tx_data->m = NULL;
+
+ if (tx_ring->queued > 0)
+ tx_ring->queued--;
+ }
+
+ if (tx_data->ni == NULL)
+ return;
pkt_type = FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE, ts->rate_stats);
mcs = FIELD_GET(HAL_TX_RATE_STATS_INFO0_MCS, ts->rate_stats);
@@ -14415,9 +14429,6 @@ qwz_dp_tx_complete_msdu(struct qwz_softc *sc, struct dp_tx_ring *tx_ring,
ieee80211_release_node(ic, tx_data->ni);
tx_data->ni = NULL;
-
- if (tx_ring->queued > 0)
- tx_ring->queued--;
}
#define QWZ_TX_COMPL_NEXT(x) (((x) + 1) % DP_TX_COMP_RING_SIZE)
--
2.55.0
From 3c437d839588313797bdee131225e38eed2672d8 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:58:06 +0200
Subject: [PATCH 05/10] sys/qwz: consume empty CE completions
Backport of sys/dev/ic/qwx.c,v 1.141
---
sys/dev/ic/qwz.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index 9a510adc8ea..c45878c5ac1 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -20908,10 +20908,6 @@ qwz_ce_completed_recv_next(struct qwz_ce_pipe *pipe,
}
*nbytes = qwz_hal_ce_dst_status_get_length(desc);
- if (*nbytes == 0) {
- ret = EIO;
- goto err;
- }
if (per_transfer_contextp) {
*per_transfer_contextp =
@@ -20935,6 +20931,8 @@ int
qwz_ce_recv_process_cb(struct qwz_ce_pipe *pipe)
{
struct qwz_softc *sc = pipe->sc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ifnet *ifp = &ic->ic_if;
struct mbuf *m;
struct mbuf_list ml = MBUF_LIST_INITIALIZER();
void *transfer_context;
@@ -20950,9 +20948,8 @@ qwz_ce_recv_process_cb(struct qwz_ce_pipe *pipe)
rx_data->m = NULL;
max_nbytes = m->m_pkthdr.len;
- if (max_nbytes < nbytes) {
- printf("%s: received more than expected (nbytes %d, "
- "max %d)", __func__, nbytes, max_nbytes);
+ if (nbytes == 0 || max_nbytes < nbytes) {
+ ifp->if_ierrors++;
m_freem(m);
continue;
}
--
2.55.0
From c969d09449e136e81fc1f1478a0bc0fa15142392 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:58:09 +0200
Subject: [PATCH 06/10] sys/qwz: propagate RX reconstruction errors
Backport from sys/dev/ic/qwx.c,v 1.85 that dp_rx_h_undecap returns error.
---
sys/dev/ic/qwz.c | 43 +++++++++++++++++++++++--------------------
1 file changed, 23 insertions(+), 20 deletions(-)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index c45878c5ac1..fd2f634db07 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -15162,7 +15162,7 @@ qwz_dp_rx_h_ppdu(struct qwz_softc *sc, struct hal_rx_desc *rx_desc,
qwz_dp_rx_h_rate(sc, rx_desc, rxi);
}
-void
+int
qwz_dp_rx_h_undecap_nwifi(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
uint8_t *first_hdr, enum hal_encrypt_type enctype)
{
@@ -15174,12 +15174,12 @@ qwz_dp_rx_h_undecap_nwifi(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
uint16_t qos_ctl;
if (m == NULL)
- return;
+ return ENOBUFS;
if (m->m_len < sizeof(*wh) &&
(m = m_pullup(m, sizeof(*wh))) == NULL) {
msdu->m = NULL;
- return;
+ return ENOBUFS;
}
msdu->m = m;
@@ -15187,23 +15187,23 @@ qwz_dp_rx_h_undecap_nwifi(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
wh = mtod(m, struct ieee80211_frame *);
if ((le32toh(mpdu->info6) & RX_MPDU_START_INFO6_NON_QOS) ||
ieee80211_has_qos(wh))
- return;
+ return 0;
hdrlen = ieee80211_get_hdrlen(wh);
if (hdrlen > sizeof(decap_hdr))
- return;
+ return EINVAL;
if (m->m_len < hdrlen &&
(m = m_pullup(m, hdrlen)) == NULL) {
msdu->m = NULL;
- return;
+ return ENOBUFS;
}
msdu->m = m;
wh = mtod(m, struct ieee80211_frame *);
hdrlen = ieee80211_get_hdrlen(wh);
if (hdrlen > sizeof(decap_hdr))
- return;
+ return EINVAL;
memcpy(decap_hdr, wh, hdrlen);
wh = (struct ieee80211_frame *)decap_hdr;
@@ -15217,17 +15217,18 @@ qwz_dp_rx_h_undecap_nwifi(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
M_PREPEND(m, sizeof(qos_ctl), M_DONTWAIT);
if (m == NULL) {
msdu->m = NULL;
- return;
+ return ENOBUFS;
}
memcpy(mtod(m, void *), &qos_ctl, sizeof(qos_ctl));
M_PREPEND(m, hdrlen, M_DONTWAIT);
if (m == NULL) {
msdu->m = NULL;
- return;
+ return ENOBUFS;
}
msdu->m = m;
memcpy(mtod(m, void *), decap_hdr, hdrlen);
+ return 0;
}
void
@@ -15304,7 +15305,7 @@ qwz_dp_rx_h_msdu_start_decap_type(struct qwz_softc *sc, struct hal_rx_desc *desc
return sc->hal_rx_ops->rx_desc_get_decap_type(desc);
}
-void
+int
qwz_dp_rx_h_undecap_eth(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
struct hal_rx_desc *rx_desc)
{
@@ -15318,7 +15319,7 @@ qwz_dp_rx_h_undecap_eth(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
struct mbuf *m = msdu->m;
if (m->m_pkthdr.len < ETHER_HDR_LEN)
- return;
+ return EINVAL;
eth = mtod(m, struct ether_header *);
memcpy(da, eth->ether_dhost, IEEE80211_ADDR_LEN);
@@ -15341,7 +15342,7 @@ qwz_dp_rx_h_undecap_eth(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
M_PREPEND(m, 8, M_DONTWAIT);
if (m == NULL) {
msdu->m = NULL;
- return;
+ return ENOBUFS;
}
msdu->m = m;
memcpy(mtod(m, void *), llc, 8);
@@ -15350,7 +15351,7 @@ qwz_dp_rx_h_undecap_eth(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
M_PREPEND(m, hdrlen, M_DONTWAIT);
if (m == NULL) {
msdu->m = NULL;
- return;
+ return ENOBUFS;
}
msdu->m = m;
p = mtod(m, uint8_t *);
@@ -15373,9 +15374,10 @@ qwz_dp_rx_h_undecap_eth(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
/* Override addr1/addr3 with actual DA/SA from Ethernet header. */
memcpy(p + 4, da, IEEE80211_ADDR_LEN);
memcpy(p + 16, sa, IEEE80211_ADDR_LEN);
+ return 0;
}
-void
+int
qwz_dp_rx_h_undecap(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
struct hal_rx_desc *rx_desc, enum hal_encrypt_type enctype,
int decrypted)
@@ -15386,15 +15388,14 @@ qwz_dp_rx_h_undecap(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
switch (decap) {
case DP_RX_DECAP_TYPE_NATIVE_WIFI:
- qwz_dp_rx_h_undecap_nwifi(sc, msdu, NULL, enctype);
- break;
+ return qwz_dp_rx_h_undecap_nwifi(sc, msdu, NULL, enctype);
case DP_RX_DECAP_TYPE_RAW:
qwz_dp_rx_h_undecap_raw(sc, msdu, enctype, decrypted);
break;
case DP_RX_DECAP_TYPE_ETHERNET2_DIX:
- qwz_dp_rx_h_undecap_eth(sc, msdu, rx_desc);
- break;
+ return qwz_dp_rx_h_undecap_eth(sc, msdu, rx_desc);
}
+ return 0;
}
int
@@ -15404,7 +15405,7 @@ qwz_dp_rx_h_mpdu(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
struct ieee80211com *ic = &sc->sc_ic;
int fill_crypto_hdr = 0;
enum hal_encrypt_type enctype;
- int is_decrypted = 0;
+ int is_decrypted = 0, ret;
#if 0
struct ath12k_skb_rxcb *rxcb;
#endif
@@ -15479,7 +15480,9 @@ qwz_dp_rx_h_mpdu(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
#if 0
ath12k_dp_rx_h_csum_offload(ar, msdu);
#endif
- qwz_dp_rx_h_undecap(sc, msdu, rx_desc, enctype, is_decrypted);
+ ret = qwz_dp_rx_h_undecap(sc, msdu, rx_desc, enctype, is_decrypted);
+ if (ret)
+ return ret;
if (is_decrypted && !fill_crypto_hdr &&
qwz_dp_rx_h_msdu_start_decap_type(sc, rx_desc) !=
--
2.55.0
From 290754ceb568e984d8378094490b0c2708d2d526 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:58:12 +0200
Subject: [PATCH 07/10] sys/qwz: include RX padding in length checks
The shared RX handler strips the descriptor and L3 padding before
setting the packet length. Include both in the bound, matching the
WBM null-queue path.
---
sys/dev/ic/qwz.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index fd2f634db07..883a4adef31 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -15547,7 +15547,8 @@ qwz_dp_rx_process_msdu(struct qwz_softc *sc, struct qwz_rx_msdu *msdu,
m_adj(msdu->m, hal_rx_desc_sz);
msdu->m->m_len = msdu->m->m_pkthdr.len = msdu_len;
} else if (!msdu->is_continuation) {
- if ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE) {
+ if (msdu_len + hal_rx_desc_sz + l3_pad_bytes >
+ DP_RX_BUFFER_SIZE) {
#if 0
uint8_t *hdr_status;
--
2.55.0
From 07b171019e2f25af40901272a48a6956000c071d Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:58:16 +0200
Subject: [PATCH 08/10] sys/qwz: close the stop task scheduling window
Backport of sys/dev/ic/qwx.c,v 1.109 by only moving ~IFF_RUNNING.
---
sys/dev/ic/qwz.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index 883a4adef31..f09517e7011 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -350,6 +350,11 @@ qwz_stop(struct ifnet *ifp)
qwz_setkey_clear(sc);
+ ifp->if_timer = sc->sc_tx_timer = 0;
+
+ ifp->if_flags &= ~IFF_RUNNING;
+ ifq_clr_oactive(&ifp->if_snd);
+
clear_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags);
/* Tear down firmware-side association so we can re-associate. */
@@ -360,11 +365,6 @@ qwz_stop(struct ifnet *ifp)
qwz_deauth(sc);
}
- ifp->if_timer = sc->sc_tx_timer = 0;
-
- ifp->if_flags &= ~IFF_RUNNING;
- ifq_clr_oactive(&ifp->if_snd);
-
sc->sc_newstate(ic, IEEE80211_S_INIT, -1);
sc->ns_nstate = IEEE80211_S_INIT;
sc->scan.state = ATH12K_SCAN_IDLE;
--
2.55.0
From 05231b85b6dae594f0aa0b1ea4d24d308a4e284b Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:58:19 +0200
Subject: [PATCH 09/10] sys/qwz: skip recovery from stopped tasks
Backport of sys/dev/ic/qwx.c,v 1.124
---
sys/dev/ic/qwz.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index f09517e7011..829e3742d73 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -1008,7 +1008,8 @@ next_scan:
break;
}
out:
- if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags)) {
+ if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags) &&
+ (ifp->if_flags & IFF_RUNNING)) {
if (err)
task_add(systq, &sc->init_task);
else
--
2.55.0
From a7592c2210dcff02196b811a8c30710f0c70616d Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 17:58:22 +0200
Subject: [PATCH 10/10] sys/qwz: avoid waiting for recovery locks
Backport of sys/dev/ic/qwx.c,v 1.129
---
sys/dev/ic/qwz.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git sys/dev/ic/qwz.c sys/dev/ic/qwz.c
index 829e3742d73..17ef50cc9c0 100644
--- sys/dev/ic/qwz.c
+++ sys/dev/ic/qwz.c
@@ -22165,7 +22165,16 @@ qwz_init_task(void *arg)
struct qwz_softc *sc = arg;
struct ifnet *ifp = &sc->sc_ic.ic_if;
int s = splnet();
- rw_enter_write(&sc->ioctl_rwl);
+
+ /*
+ * Do not sleep for this lock. The init task is a one-shot
+ * recovery mechanism. If the ioctl handler is busy then
+ * we are being reconfigured or reset already.
+ */
+ if (rw_enter(&sc->ioctl_rwl, RW_WRITE | RW_NOSLEEP) != 0) {
+ splx(s);
+ return;
+ }
if (ifp->if_flags & IFF_RUNNING)
qwz_stop(ifp);
--
2.55.0
--
wbr, Kirill
First batch of qwz backports and fixes