Download raw body.
Third batch of qwz commits
Stefan,
the 2nd batch without one commit in question was commited, let keep for
after release.
So, here the third batch of qwz commits. Here 11 commits 7 of them almost
just of backports, and 4 had required some working around.
Ok?
From 9e8c94c3aa4aaa9067fec81015af2288e4597f05 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:55:34 +0200
Subject: [PATCH 01/11] sys/qwz: wait for startup allocations
Backport of sys/dev/ic/qwx.c,v 1.127
---
sys/dev/ic/qwz.c | 44 ++++++++++++++++----------------------------
1 file changed, 16 insertions(+), 28 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 69a0cd71e42..71aed7590c1 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -8332,15 +8332,13 @@ qwz_dp_tx_ring_alloc_tx_data(struct qwz_softc *sc, struct dp_tx_ring *tx_ring)
int i, ret;
tx_ring->data = mallocarray(sc->hw_params.tx_ring_size,
- sizeof(struct qwz_tx_data), M_DEVBUF, M_NOWAIT | M_ZERO);
- if (tx_ring->data == NULL)
- return ENOMEM;
+ sizeof(struct qwz_tx_data), M_DEVBUF, M_WAITOK | M_ZERO);
for (i = 0; i < sc->hw_params.tx_ring_size; i++) {
struct qwz_tx_data *tx_data = &tx_ring->data[i];
ret = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
- BUS_DMA_NOWAIT, &tx_data->map);
+ BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &tx_data->map);
if (ret)
return ret;
}
@@ -8941,11 +8939,7 @@ qwz_dp_alloc(struct qwz_softc *sc)
dp->tx_ring[i].tx_status_head = 0;
dp->tx_ring[i].tx_status_tail = DP_TX_COMP_RING_SIZE - 1;
dp->tx_ring[i].tx_status = malloc(size, M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (!dp->tx_ring[i].tx_status) {
- ret = ENOMEM;
- goto fail_cmn_reoq_cleanup;
- }
+ M_WAITOK | M_ZERO);
}
for (i = 0; i < HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX; i++)
@@ -9095,9 +9089,7 @@ qwz_qmi_wlanfw_wlan_cfg_send(struct qwz_softc *sc)
ce_cfg = sc->hw_params.target_ce_config;
svc_cfg = sc->hw_params.svc_to_ce_map;
- req = malloc(sizeof(*req), M_DEVBUF, M_NOWAIT | M_ZERO);
- if (!req)
- return ENOMEM;
+ req = malloc(sizeof(*req), M_DEVBUF, M_WAITOK | M_ZERO);
req->host_version_valid = 1;
strlcpy(req->host_version, ATH12K_HOST_VERSION_STRING,
@@ -20326,9 +20318,7 @@ qwz_ce_alloc_src_ring_transfer_contexts(struct qwz_ce_pipe *pipe,
/* Allocate an array of qwz_tx_data structures. */
txdata = mallocarray(pipe->src_ring->nentries, sizeof(*txdata),
- M_DEVBUF, M_NOWAIT | M_ZERO);
- if (txdata == NULL)
- return ENOMEM;
+ M_DEVBUF, M_WAITOK | M_ZERO);
size = sizeof(*txdata) * pipe->src_ring->nentries;
@@ -20336,7 +20326,8 @@ qwz_ce_alloc_src_ring_transfer_contexts(struct qwz_ce_pipe *pipe,
for (i = 0; i < pipe->src_ring->nentries; i++) {
struct qwz_tx_data *ctx = &txdata[i];
ret = bus_dmamap_create(sc->sc_dmat, attr->src_sz_max, 1,
- attr->src_sz_max, 0, BUS_DMA_NOWAIT, &ctx->map);
+ attr->src_sz_max, 0,
+ BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &ctx->map);
if (ret) {
int j;
for (j = 0; j < i; j++) {
@@ -20363,9 +20354,7 @@ qwz_ce_alloc_dest_ring_transfer_contexts(struct qwz_ce_pipe *pipe,
/* Allocate an array of qwz_rx_data structures. */
rxdata = mallocarray(pipe->dest_ring->nentries, sizeof(*rxdata),
- M_DEVBUF, M_NOWAIT | M_ZERO);
- if (rxdata == NULL)
- return ENOMEM;
+ M_DEVBUF, M_WAITOK | M_ZERO);
size = sizeof(*rxdata) * pipe->dest_ring->nentries;
@@ -20373,7 +20362,8 @@ qwz_ce_alloc_dest_ring_transfer_contexts(struct qwz_ce_pipe *pipe,
for (i = 0; i < pipe->dest_ring->nentries; i++) {
struct qwz_rx_data *ctx = &rxdata[i];
ret = bus_dmamap_create(sc->sc_dmat, attr->src_sz_max, 1,
- attr->src_sz_max, 0, BUS_DMA_NOWAIT, &ctx->map);
+ attr->src_sz_max, 0,
+ BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &ctx->map);
if (ret) {
int j;
for (j = 0; j < i; j++) {
@@ -20397,36 +20387,34 @@ qwz_ce_alloc_ring(struct qwz_softc *sc, int nentries, size_t desc_sz)
(nentries * sizeof(ce_ring->per_transfer_context[0]));
bus_size_t dsize;
- ce_ring = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
- if (ce_ring == NULL)
- return NULL;
+ ce_ring = malloc(size, M_DEVBUF, M_WAITOK | M_ZERO);
ce_ring->nentries = nentries;
ce_ring->nentries_mask = nentries - 1;
ce_ring->desc_sz = desc_sz;
dsize = nentries * desc_sz;
- if (bus_dmamap_create(sc->sc_dmat, dsize, 1, dsize, 0, BUS_DMA_NOWAIT,
- &ce_ring->dmap)) {
+ if (bus_dmamap_create(sc->sc_dmat, dsize, 1, dsize, 0,
+ BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &ce_ring->dmap)) {
free(ce_ring, M_DEVBUF, size);
return NULL;
}
if (bus_dmamem_alloc(sc->sc_dmat, dsize, CE_DESC_RING_ALIGN, 0,
&ce_ring->dsegs, 1, &ce_ring->nsegs,
- BUS_DMA_NOWAIT | BUS_DMA_ZERO)) {
+ BUS_DMA_WAITOK | BUS_DMA_ZERO)) {
qwz_ce_free_ring(sc, ce_ring);
return NULL;
}
if (bus_dmamem_map(sc->sc_dmat, &ce_ring->dsegs, 1, dsize,
- &ce_ring->base_addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) {
+ &ce_ring->base_addr, BUS_DMA_WAITOK | BUS_DMA_COHERENT)) {
qwz_ce_free_ring(sc, ce_ring);
return NULL;
}
if (bus_dmamap_load(sc->sc_dmat, ce_ring->dmap, ce_ring->base_addr,
- dsize, NULL, BUS_DMA_NOWAIT)) {
+ dsize, NULL, BUS_DMA_WAITOK)) {
qwz_ce_free_ring(sc, ce_ring);
return NULL;
}
--
2.55.0
From d588468e2318c36451f82ea32cdeb9cac7004916 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:57:21 +0200
Subject: [PATCH 02/11] sys/qwz: wait for cookie pool allocations
Backport of sys/dev/ic/qwx.c,v 1.127
---
sys/dev/ic/qwz.c | 35 +++++++----------------------------
1 file changed, 7 insertions(+), 28 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 71aed7590c1..be82c1bd8b7 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -8481,14 +8481,7 @@ qwz_dp_cc_desc_init(struct qwz_softc *sc)
/* First ATH12K_NUM_RX_SPT_PAGES of allocated SPT pages are used for RX */
for (i = 0; i < ATH12K_NUM_RX_SPT_PAGES; i++) {
rx_descs = mallocarray(ATH12K_MAX_SPT_ENTRIES, sizeof(*rx_descs),
- M_DEVBUF, M_NOWAIT | M_ZERO);
-
- if (!rx_descs) {
-#ifdef notyet
- spin_unlock_bh(&dp->rx_desc_lock);
-#endif
- return ENOMEM;
- }
+ M_DEVBUF, M_WAITOK | M_ZERO);
ppt_idx = ATH12K_RX_SPT_PAGE_OFFSET + i;
dp->spt_info->rxbaddr[i] = &rx_descs[0];
@@ -8500,7 +8493,8 @@ qwz_dp_cc_desc_init(struct qwz_softc *sc)
&rx_descs[j], entry);
ret = bus_dmamap_create(sc->sc_dmat, size, 1, size,
- 0, BUS_DMA_WAITOK, &rx_descs[j].map);
+ 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
+ &rx_descs[j].map);
if (ret)
return ret;
@@ -8519,16 +8513,8 @@ qwz_dp_cc_desc_init(struct qwz_softc *sc)
spin_lock_bh(&dp->tx_desc_lock[pool_id]);
#endif
for (i = 0; i < ATH12K_TX_SPT_PAGES_PER_POOL; i++) {
- tx_descs = mallocarray(ATH12K_MAX_SPT_ENTRIES, sizeof(*tx_descs),
- M_DEVBUF, M_NOWAIT | M_ZERO);
-
- if (!tx_descs) {
-#ifdef notyet
- spin_unlock_bh(&dp->tx_desc_lock[pool_id]);
-#endif
- /* Caller takes care of TX pending and RX desc cleanup */
- return ENOMEM;
- }
+ tx_descs = mallocarray(ATH12K_MAX_SPT_ENTRIES,
+ sizeof(*tx_descs), M_DEVBUF, M_WAITOK | M_ZERO);
tx_spt_page = i + pool_id * ATH12K_TX_SPT_PAGES_PER_POOL;
ppt_idx = ATH12K_TX_SPT_PAGE_OFFSET + tx_spt_page;
@@ -8660,12 +8646,7 @@ qwz_dp_cc_init(struct qwz_softc *sc)
dp->spt_info = mallocarray(dp->num_spt_pages,
sizeof(struct ath12k_spt_info),
- M_DEVBUF, M_NOWAIT | M_ZERO);
- if (!dp->spt_info) {
- printf("%s: SPT page allocation failure\n",
- sc->sc_dev.dv_xname);
- return ENOMEM;
- }
+ M_DEVBUF, M_WAITOK | M_ZERO);
for (i = 0; i < dp->num_spt_pages; i++) {
dp->spt_info[i].mem = qwz_dmamem_alloc(sc->sc_dmat,
@@ -8718,9 +8699,7 @@ qwz_dp_init_bank_profiles(struct qwz_softc *sc)
dp->num_bank_profiles = sc->hw_params.num_tcl_banks;
dp->bank_profiles = mallocarray(dp->num_bank_profiles,
sizeof(struct ath12k_dp_tx_bank_profile), M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (!dp->bank_profiles)
- return ENOMEM;
+ M_WAITOK | M_ZERO);
return 0;
}
--
2.55.0
From 15a66bf87ee2f5efc4101e3153404eba60fd1b4e Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:55:40 +0200
Subject: [PATCH 03/11] sys/qwz: retain HAL allocations on resume
Based on sys/dev/ic/qwx.c,v 1.97 and sys/dev/ic/qwx.c,v 1.136
Preserve HAL allocation pointers across reinitialization: reuse qwz
allocated ring configuration and claer retained pointer memory. On
failure, free only allocations made by the current attempt.
---
sys/dev/ic/qwz.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index be82c1bd8b7..4c9447c9fbf 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -19174,10 +19174,12 @@ qwz_hal_srng_create_config_wcn7850(struct qwz_softc *sc)
struct ath12k_hal *hal = &sc->hal;
struct hal_srng_config *s;
- hal->srng_config = malloc(sizeof(hw_srng_config_templ),
- M_DEVBUF, M_NOWAIT | M_ZERO);
- if (!hal->srng_config)
- return ENOMEM;
+ if (hal->srng_config == NULL) {
+ hal->srng_config = malloc(sizeof(hw_srng_config_templ),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (hal->srng_config == NULL)
+ return ENOMEM;
+ }
memcpy(hal->srng_config, hw_srng_config_templ,
sizeof(hw_srng_config_templ));
@@ -19442,7 +19444,8 @@ qwz_hal_alloc_cont_rdp(struct qwz_softc *sc)
return ENOMEM;
}
- }
+ } else
+ memset(QWZ_DMA_KVA(hal->rdpmem), 0, size);
hal->rdp.vaddr = QWZ_DMA_KVA(hal->rdpmem);
hal->rdp.paddr = QWZ_DMA_DVA(hal->rdpmem);
@@ -19478,7 +19481,8 @@ qwz_hal_alloc_cont_wrp(struct qwz_softc *sc)
return ENOMEM;
}
- }
+ } else
+ memset(QWZ_DMA_KVA(hal->wrpmem), 0, size);
hal->wrp.vaddr = QWZ_DMA_KVA(hal->wrpmem);
hal->wrp.paddr = QWZ_DMA_DVA(hal->wrpmem);
@@ -19504,8 +19508,8 @@ qwz_hal_srng_init(struct qwz_softc *sc)
{
struct ath12k_hal *hal = &sc->hal;
int ret;
-
- memset(hal, 0, sizeof(*hal));
+ int new_config = hal->srng_config == NULL;
+ int new_rdp = hal->rdpmem == NULL;
ret = sc->hw_params.hal_ops->create_srng_config(sc);
if (ret)
@@ -19525,11 +19529,14 @@ qwz_hal_srng_init(struct qwz_softc *sc)
return 0;
err_free_cont_rdp:
- qwz_hal_free_cont_rdp(sc);
+ if (new_rdp)
+ qwz_hal_free_cont_rdp(sc);
err_hal:
- if (hal->srng_config)
+ if (new_config && hal->srng_config) {
free(hal->srng_config, M_DEVBUF, 0);
+ hal->srng_config = NULL;
+ }
return ret;
}
--
2.55.0
From a16f7b73d6f83db2c8054e1bd1c1da960dc533a5 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:55:37 +0200
Subject: [PATCH 04/11] sys/qwz: synchronize SRNG pointers
Based on sys/dev/ic/qwx.c,v 1.140 and sys/dev/ic/qwx.c,v 1.114
Pair DMA synchronization around shared pointer accesses in SRNG
begin and end; prpeare new or reused pointer buffers for DMA and retain
volatile reads of device updated pointers.
---
sys/dev/ic/qwz.c | 36 +++++++++++++++++++++++++++++++-----
1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 4c9447c9fbf..a4325b80550 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -7322,6 +7322,9 @@ qwz_hal_srng_access_begin(struct qwz_softc *sc, struct hal_srng *srng)
#ifdef notyet
lockdep_assert_held(&srng->lock);
#endif
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(sc->hal.rdpmem), 0,
+ QWZ_DMA_LEN(sc->hal.rdpmem), BUS_DMASYNC_POSTREAD);
+
if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
srng->u.src_ring.cached_tp =
*(volatile uint32_t *)srng->u.src_ring.tp_addr;
@@ -7338,6 +7341,8 @@ qwz_hal_srng_access_begin(struct qwz_softc *sc, struct hal_srng *srng)
srng->u.dst_ring.cached_hp =
*(volatile uint32_t *)srng->u.dst_ring.hp_addr;
}
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(sc->hal.rdpmem), 0,
+ QWZ_DMA_LEN(sc->hal.rdpmem), BUS_DMASYNC_PREREAD);
}
void
@@ -7346,8 +7351,13 @@ qwz_hal_srng_access_end(struct qwz_softc *sc, struct hal_srng *srng)
#ifdef notyet
lockdep_assert_held(&srng->lock);
#endif
- /* TODO: See if we need a write memory barrier here */
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(sc->hal.rdpmem), 0,
+ QWZ_DMA_LEN(sc->hal.rdpmem), BUS_DMASYNC_POSTREAD);
+
if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) {
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(sc->hal.wrpmem), 0,
+ QWZ_DMA_LEN(sc->hal.wrpmem), BUS_DMASYNC_POSTWRITE);
+
/* For LMAC rings, ring pointer updates are done through FW and
* hence written to a shared memory location that is read by FW
*/
@@ -7356,9 +7366,12 @@ qwz_hal_srng_access_end(struct qwz_softc *sc, struct hal_srng *srng)
*(volatile uint32_t *)srng->u.src_ring.tp_addr;
*srng->u.src_ring.hp_addr = srng->u.src_ring.hp;
} else {
- srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
+ srng->u.dst_ring.last_hp =
+ *(volatile uint32_t *)srng->u.dst_ring.hp_addr;
*srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp;
}
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(sc->hal.wrpmem), 0,
+ QWZ_DMA_LEN(sc->hal.wrpmem), BUS_DMASYNC_PREWRITE);
} else {
if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
srng->u.src_ring.last_tp =
@@ -7367,12 +7380,15 @@ qwz_hal_srng_access_end(struct qwz_softc *sc, struct hal_srng *srng)
(unsigned long)srng->u.src_ring.hp_addr -
(unsigned long)sc->mem, srng->u.src_ring.hp);
} else {
- srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
+ srng->u.dst_ring.last_hp =
+ *(volatile uint32_t *)srng->u.dst_ring.hp_addr;
sc->ops.write32(sc,
(unsigned long)srng->u.dst_ring.tp_addr -
(unsigned long)sc->mem, srng->u.dst_ring.tp);
}
}
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(sc->hal.rdpmem), 0,
+ QWZ_DMA_LEN(sc->hal.rdpmem), BUS_DMASYNC_PREREAD);
#ifdef notyet
srng->timestamp = jiffies;
#endif
@@ -19444,11 +19460,16 @@ qwz_hal_alloc_cont_rdp(struct qwz_softc *sc)
return ENOMEM;
}
- } else
+ } else {
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(hal->rdpmem), 0,
+ QWZ_DMA_LEN(hal->rdpmem), BUS_DMASYNC_POSTREAD);
memset(QWZ_DMA_KVA(hal->rdpmem), 0, size);
+ }
hal->rdp.vaddr = QWZ_DMA_KVA(hal->rdpmem);
hal->rdp.paddr = QWZ_DMA_DVA(hal->rdpmem);
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(hal->rdpmem), 0,
+ QWZ_DMA_LEN(hal->rdpmem), BUS_DMASYNC_PREREAD);
return 0;
}
@@ -19481,11 +19502,16 @@ qwz_hal_alloc_cont_wrp(struct qwz_softc *sc)
return ENOMEM;
}
- } else
+ } else {
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(hal->wrpmem), 0,
+ QWZ_DMA_LEN(hal->wrpmem), BUS_DMASYNC_POSTWRITE);
memset(QWZ_DMA_KVA(hal->wrpmem), 0, size);
+ }
hal->wrp.vaddr = QWZ_DMA_KVA(hal->wrpmem);
hal->wrp.paddr = QWZ_DMA_DVA(hal->wrpmem);
+ bus_dmamap_sync(sc->sc_dmat, QWZ_DMA_MAP(hal->wrpmem), 0,
+ QWZ_DMA_LEN(hal->wrpmem), BUS_DMASYNC_PREWRITE);
return 0;
}
--
2.55.0
From ca0fe312e0570770fe65fd4af9cdbaaca2e43962 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:54:55 +0200
Subject: [PATCH 05/11] sys/qwz: mark running after MAC startup
Backport of sys/dev/ic/qwx.c,v 1.122 and sys/dev/ic/qwx.c,v 1.134
---
sys/dev/ic/qwz.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index a4325b80550..c024e386e54 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -334,17 +334,16 @@ qwz_init(struct ifnet *ifp)
}
if (ifp->if_flags & IFF_UP) {
- refcnt_init(&sc->task_refs);
-
- ifq_clr_oactive(&ifp->if_snd);
- ifp->if_flags |= IFF_RUNNING;
-
error = qwz_mac_start(sc);
if (error) {
splx(s);
return error;
}
+ refcnt_init(&sc->task_refs);
+ ifq_clr_oactive(&ifp->if_snd);
+ ifp->if_flags |= IFF_RUNNING;
+
ieee80211_begin_scan(ifp);
}
--
2.55.0
From 0a3211cf61b38c8b39d2b57ae2abe16c110d0546 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:54:52 +0200
Subject: [PATCH 06/11] sys/qwz: propagate firmware startup errors
Backport of sys/dev/ic/qwx.c,v 1.128
---
sys/dev/ic/qwz.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index c024e386e54..f9886ac7ee5 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -18854,7 +18854,7 @@ err_firmware_stop:
return ret;
}
-void
+int
qwz_qmi_fw_ready(struct qwz_softc *sc)
{
int ret = 0;
@@ -18866,8 +18866,8 @@ qwz_qmi_fw_ready(struct qwz_softc *sc)
ret = qwz_core_qmi_firmware_ready(sc);
if (ret) {
set_bit(ATH12K_FLAG_QMI_FAIL, sc->sc_flags);
- return;
}
+ return ret;
}
int
@@ -18935,8 +18935,7 @@ qwz_qmi_event_server_arrive(struct qwz_softc *sc)
}
}
- qwz_qmi_fw_ready(sc);
- return 0;
+ return qwz_qmi_fw_ready(sc);
}
int
--
2.55.0
From a490164e88d696d1b32daa4abe8f8424db2822ad Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:54:49 +0200
Subject: [PATCH 07/11] sys/qwz: initialize QRTR before power-up
Backport of sys/dev/ic/qwx.c,v 1.132
---
sys/dev/ic/qwz.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index f9886ac7ee5..0d4fae305ec 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -286,15 +286,15 @@ qwz_init(struct ifnet *ifp)
sc->scan.state = ATH12K_SCAN_IDLE;
sc->vdev_id_11d_scan = QWZ_11D_INVALID_VDEV_ID;
+ memset(&sc->qrtr_server, 0, sizeof(sc->qrtr_server));
+ sc->qrtr_server.node = QRTR_NODE_BCAST;
+
error = qwz_core_init(sc);
if (error) {
splx(s);
return error;
}
- memset(&sc->qrtr_server, 0, sizeof(sc->qrtr_server));
- sc->qrtr_server.node = QRTR_NODE_BCAST;
-
/* wait for QRTR init to be done */
while (sc->qrtr_server.node == QRTR_NODE_BCAST) {
error = tsleep_nsec(&sc->qrtr_server, 0, "qwzqrtr",
--
2.55.0
From b00a52cba15ae30b99f5a96de911e548295763a1 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:55:46 +0200
Subject: [PATCH 08/11] sys/qwz: retain the host VIF
Backport of sys/dev/ic/qwx.c,v 1.138 and sys/dev/ic/qwxvar.h,v 1.38
---
sys/dev/ic/qwz.c | 168 ++++++++++++++++++--------------------------
sys/dev/ic/qwzvar.h | 7 +-
2 files changed, 69 insertions(+), 106 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 0d4fae305ec..0cc052f8231 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -159,6 +159,7 @@ int qwz_wmi_vdev_install_key(struct qwz_softc *,
int qwz_dp_peer_rx_pn_replay_config(struct qwz_softc *, struct qwz_vif *,
struct ieee80211_node *, struct ieee80211_key *, int);
void qwz_setkey_clear(struct qwz_softc *);
+void qwz_vif_purge(struct qwz_softc *);
int qwz_scan(struct qwz_softc *);
void qwz_scan_abort(struct qwz_softc *);
@@ -406,7 +407,7 @@ qwz_stop(struct ifnet *ifp)
clear_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags);
/* Tear down firmware-side association so we can re-associate. */
- if (!TAILQ_EMPTY(&sc->vif_list)) {
+ if (sc->num_created_vdevs != 0) {
if (ic->ic_state == IEEE80211_S_RUN)
qwz_run_stop(sc);
if (ic->ic_state >= IEEE80211_S_AUTH)
@@ -494,7 +495,7 @@ int
qwz_tx(struct qwz_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
struct ieee80211_frame *wh;
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
+ struct qwz_vif *arvif = &sc->sc_vif;
uint8_t pdev_id = 0; /* TODO: derive pdev ID somehow? */
uint8_t frame_type;
@@ -767,7 +768,7 @@ qwz_add_sta_key(struct qwz_softc *sc, struct ieee80211_node *ni,
struct ieee80211com *ic = &sc->sc_ic;
struct qwz_node *nq = (struct qwz_node *)ni;
struct ath12k_peer *peer;
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
+ struct qwz_vif *arvif = &sc->sc_vif;
int ret = 0;
uint32_t flags = 0;
const int want_keymask = (QWZ_NODE_FLAG_HAVE_PAIRWISE_KEY |
@@ -844,7 +845,7 @@ qwz_del_sta_key(struct qwz_softc *sc, struct ieee80211_node *ni,
{
struct ieee80211com *ic = &sc->sc_ic;
struct qwz_node *nq = (struct qwz_node *)ni;
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
+ struct qwz_vif *arvif = &sc->sc_vif;
int ret = 0;
ret = qwz_wmi_install_key_cmd(sc, arvif, ni->ni_macaddr, k, 0, 1);
@@ -11424,7 +11425,7 @@ void
qwz_scan_event(struct qwz_softc *sc, struct mbuf *m)
{
struct wmi_scan_event scan_ev = { 0 };
- struct qwz_vif *arvif;
+ struct qwz_vif *arvif = &sc->sc_vif;
if (qwz_pull_scan_ev(sc, m, &scan_ev) != 0) {
printf("%s: failed to extract scan event",
@@ -11434,12 +11435,7 @@ qwz_scan_event(struct qwz_softc *sc, struct mbuf *m)
#ifdef notyet
rcu_read_lock();
#endif
- TAILQ_FOREACH(arvif, &sc->vif_list, entry) {
- if (arvif->vdev_id == scan_ev.vdev_id)
- break;
- }
-
- if (!arvif) {
+ if (arvif->vdev_id != scan_ev.vdev_id) {
printf("%s: received scan event for unknown vdev\n",
sc->sc_dev.dv_xname);
#if 0
@@ -11533,7 +11529,7 @@ qwz_pull_chan_info_ev(struct qwz_softc *sc, uint8_t *evt_buf, uint32_t len,
void
qwz_chan_info_event(struct qwz_softc *sc, struct mbuf *m)
{
- struct qwz_vif *arvif;
+ struct qwz_vif *arvif = &sc->sc_vif;
struct wmi_chan_info_event ch_info_ev = {0};
struct qwz_survey_info *survey;
int idx;
@@ -11562,11 +11558,7 @@ qwz_chan_info_event(struct qwz_softc *sc, struct mbuf *m)
#ifdef notyet
rcu_read_lock();
#endif
- TAILQ_FOREACH(arvif, &sc->vif_list, entry) {
- if (arvif->vdev_id == ch_info_ev.vdev_id)
- break;
- }
- if (!arvif) {
+ if (arvif->vdev_id != ch_info_ev.vdev_id) {
printf("%s: invalid vdev id in chan info ev %d\n",
sc->sc_dev.dv_xname, ch_info_ev.vdev_id);
#ifdef notyet
@@ -11845,7 +11837,7 @@ qwz_wmi_process_mgmt_tx_comp(struct qwz_softc *sc,
struct wmi_mgmt_tx_compl_event *tx_compl_param)
{
struct ieee80211com *ic = &sc->sc_ic;
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
+ struct qwz_vif *arvif = &sc->sc_vif;
struct ifnet *ifp = &ic->ic_if;
struct qwz_tx_data *tx_data;
@@ -12028,7 +12020,7 @@ void
qwz_vdev_install_key_compl_event(struct qwz_softc *sc, struct mbuf *m)
{
struct wmi_vdev_install_key_complete_arg install_key_compl = { 0 };
- struct qwz_vif *arvif;
+ struct qwz_vif *arvif = &sc->sc_vif;
if (qwz_pull_vdev_install_key_compl_ev(sc, m,
&install_key_compl) != 0) {
@@ -12043,11 +12035,7 @@ qwz_vdev_install_key_compl_event(struct qwz_softc *sc, struct mbuf *m)
ether_sprintf((u_char *)install_key_compl.macaddr),
install_key_compl.status);
- TAILQ_FOREACH(arvif, &sc->vif_list, entry) {
- if (arvif->vdev_id == install_key_compl.vdev_id)
- break;
- }
- if (!arvif) {
+ if (arvif->vdev_id != install_key_compl.vdev_id) {
printf("%s: invalid vdev id in install key compl ev %d\n",
sc->sc_dev.dv_xname, install_key_compl.vdev_id);
return;
@@ -12910,7 +12898,7 @@ qwz_peer_map_event(struct qwz_softc *sc, uint8_t vdev_id, uint16_t peer_id,
struct ieee80211_node *ni;
struct qwz_node *nq;
struct ath12k_peer *peer;
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list);
+ struct qwz_vif *arvif = &sc->sc_vif;
peer = qwz_peer_find_by_addr(sc, mac_addr);
if (peer == NULL || peer->vdev_id != vdev_id)
@@ -12929,7 +12917,7 @@ qwz_peer_map_event(struct qwz_softc *sc, uint8_t vdev_id, uint16_t peer_id,
nq = (struct qwz_node *)ni;
nq->peer_id = peer_id;
}
- if (ic->ic_opmode == IEEE80211_M_STA && arvif != NULL &&
+ if (ic->ic_opmode == IEEE80211_M_STA &&
arvif->vdev_id == vdev_id) {
arvif->ast_hash = ast_hash;
arvif->ast_idx = hw_peer_id;
@@ -18745,6 +18733,7 @@ qwz_core_deinit(struct qwz_softc *sc)
mutex_unlock(&ab->core_lock);
#endif
sc->ops.power_down(sc);
+ qwz_vif_purge(sc);
qwz_free_peers(sc);
#if 0
ath12k_mac_destroy(ab);
@@ -21347,26 +21336,17 @@ qwz_mac_config_mon_status_default(struct qwz_softc *sc, int enable)
int
qwz_mac_txpower_recalc(struct qwz_softc *sc, struct qwz_pdev *pdev)
{
- struct qwz_vif *arvif;
- int ret, txpower = -1;
+ struct qwz_vif *arvif = &sc->sc_vif;
+ int ret, txpower;
uint32_t param;
uint32_t min_tx_power = sc->target_caps.hw_min_tx_power;
uint32_t max_tx_power = sc->target_caps.hw_max_tx_power;
#ifdef notyet
lockdep_assert_held(&ar->conf_mutex);
#endif
- TAILQ_FOREACH(arvif, &sc->vif_list, entry) {
- if (arvif->txpower <= 0)
- continue;
-
- if (txpower == -1)
- txpower = arvif->txpower;
- else
- txpower = MIN(txpower, arvif->txpower);
- }
-
- if (txpower == -1)
+ if (arvif->txpower <= 0)
return 0;
+ txpower = arvif->txpower;
/* txpwr is set as 2 units per dBm in FW*/
txpower = MIN(MAX(min_tx_power, txpower), max_tx_power) * 2;
@@ -21524,10 +21504,9 @@ qwz_mac_setup_vdev_params_mbssid(struct qwz_vif *arvif,
}
int
-qwz_mac_setup_vdev_create_params(struct qwz_vif *arvif, struct qwz_pdev *pdev,
- struct vdev_create_params *params)
+qwz_mac_setup_vdev_create_params(struct qwz_softc *sc, struct qwz_vif *arvif,
+ struct qwz_pdev *pdev, struct vdev_create_params *params)
{
- struct qwz_softc *sc = arvif->sc;
int ret;
params->if_id = arvif->vdev_id;
@@ -21833,42 +21812,54 @@ qwz_mac_vdev_start(struct qwz_softc *sc, struct qwz_vif *arvif, int pdev_id)
}
void
-qwz_vif_free(struct qwz_softc *sc, struct qwz_vif *arvif)
+qwz_vif_purge(struct qwz_softc *sc)
{
- struct qwz_txmgmt_queue *txmgmt;
+ struct qwz_txmgmt_queue *txmgmt = &sc->sc_vif.txmgmt;
int i;
- if (arvif == NULL)
- return;
-
- txmgmt = &arvif->txmgmt;
for (i = 0; i < nitems(txmgmt->data); i++) {
struct qwz_tx_data *tx_data = &txmgmt->data[i];
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_data->ni) {
+ ieee80211_release_node(&sc->sc_ic, tx_data->ni);
+ tx_data->ni = NULL;
+ }
+ }
+ txmgmt->cur = txmgmt->queued = 0;
+}
+
+void
+qwz_vif_free(struct qwz_softc *sc)
+{
+ struct qwz_txmgmt_queue *txmgmt = &sc->sc_vif.txmgmt;
+ int i;
+
+ qwz_vif_purge(sc);
+ for (i = 0; i < nitems(txmgmt->data); i++) {
+ struct qwz_tx_data *tx_data = &txmgmt->data[i];
+
if (tx_data->map) {
bus_dmamap_destroy(sc->sc_dmat, tx_data->map);
tx_data->map = NULL;
}
}
-
- free(arvif, M_DEVBUF, sizeof(*arvif));
}
-struct qwz_vif *
+int
qwz_vif_alloc(struct qwz_softc *sc)
{
- struct qwz_vif *arvif;
+ struct qwz_vif *arvif = &sc->sc_vif;
struct qwz_txmgmt_queue *txmgmt;
int i, ret = 0;
const bus_size_t size = IEEE80211_MAX_LEN;
- arvif = malloc(sizeof(*arvif), M_DEVBUF, M_NOWAIT | M_ZERO);
- if (arvif == NULL)
- return NULL;
arvif->bank_id = -1;
txmgmt = &arvif->txmgmt;
@@ -21876,16 +21867,14 @@ qwz_vif_alloc(struct qwz_softc *sc)
struct qwz_tx_data *tx_data = &txmgmt->data[i];
ret = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
- BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &tx_data->map);
+ BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &tx_data->map);
if (ret) {
- qwz_vif_free(sc, arvif);
- return NULL;
+ qwz_vif_free(sc);
+ return ret;
}
}
- arvif->sc = sc;
-
- return arvif;
+ return 0;
}
int
@@ -21893,7 +21882,7 @@ qwz_mac_op_add_interface(struct qwz_pdev *pdev)
{
struct qwz_softc *sc = pdev->sc;
struct ieee80211com *ic = &sc->sc_ic;
- struct qwz_vif *arvif = NULL;
+ struct qwz_vif *arvif = &sc->sc_vif;
struct vdev_create_params vdev_param = { 0 };
#if 0
struct peer_create_params peer_param;
@@ -21924,11 +21913,9 @@ qwz_mac_op_add_interface(struct qwz_pdev *pdev)
goto err;
}
- arvif = qwz_vif_alloc(sc);
- if (arvif == NULL) {
- ret = ENOMEM;
- goto err;
- }
+ /* Management DMA maps persist across firmware VDEV creation. */
+ memset(arvif, 0, offsetof(struct qwz_vif, txmgmt));
+ arvif->bank_id = -1;
#if 0
INIT_DELAYED_WORK(&arvif->connection_loss_work,
ath12k_mac_vif_sta_connection_loss_work);
@@ -21983,7 +21970,7 @@ qwz_mac_op_add_interface(struct qwz_pdev *pdev)
__func__, arvif->vdev_id, arvif->vdev_type,
arvif->vdev_subtype, sc->free_vdev_map);
- ret = qwz_mac_setup_vdev_create_params(arvif, pdev, &vdev_param);
+ ret = qwz_mac_setup_vdev_create_params(sc, arvif, pdev, &vdev_param);
if (ret) {
printf("%s: failed to create vdev parameters %d: %d\n",
sc->sc_dev.dv_xname, arvif->vdev_id, ret);
@@ -22003,13 +21990,6 @@ qwz_mac_op_add_interface(struct qwz_pdev *pdev)
ether_sprintf(ic->ic_myaddr), arvif->vdev_id);
sc->allocated_vdev_map |= 1U << arvif->vdev_id;
sc->free_vdev_map &= ~(1U << arvif->vdev_id);
-#ifdef notyet
- spin_lock_bh(&ar->data_lock);
-#endif
- TAILQ_INSERT_TAIL(&sc->vif_list, arvif, entry);
-#ifdef notyet
- spin_unlock_bh(&ar->data_lock);
-#endif
ret = qwz_mac_op_update_vif_offload(sc, pdev, arvif);
if (ret)
goto err_vdev_del;
@@ -22147,19 +22127,11 @@ err_peer_del:
#endif
err_vdev_del:
qwz_mac_vdev_delete(sc, arvif);
-#ifdef notyet
- spin_lock_bh(&ar->data_lock);
-#endif
- TAILQ_REMOVE(&sc->vif_list, arvif, entry);
-#ifdef notyet
- spin_unlock_bh(&ar->data_lock);
-#endif
err:
#ifdef notyet
mutex_unlock(&ar->conf_mutex);
#endif
- qwz_vif_free(sc, arvif);
return ret;
}
@@ -23882,17 +23854,12 @@ int
qwz_scan(struct qwz_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list);
+ struct qwz_vif *arvif = &sc->sc_vif;
struct scan_req_params *arg = NULL;
struct ieee80211_channel *chan, *lastc;
int ret = 0, num_channels, i;
uint32_t scan_timeout;
- if (arvif == NULL) {
- printf("%s: no vdev found\n", sc->sc_dev.dv_xname);
- return EINVAL;
- }
-
/*
* TODO Will we need separate scan iterations on devices with
* multiple radios?
@@ -24150,11 +24117,7 @@ qwz_auth(struct qwz_softc *sc)
struct qwz_pdev *pdev;
int ret;
- arvif = TAILQ_FIRST(&sc->vif_list);
- if (arvif == NULL) {
- printf("%s: no vdev found\n", sc->sc_dev.dv_xname);
- return EINVAL;
- }
+ arvif = &sc->sc_vif;
pdev = qwz_get_pdev_for_chan(sc, ni->ni_chan);
if (pdev == NULL) {
@@ -24206,7 +24169,7 @@ qwz_auth(struct qwz_softc *sc)
int
qwz_deauth(struct qwz_softc *sc)
{
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
+ struct qwz_vif *arvif = &sc->sc_vif;
uint8_t pdev_id = 0; /* TODO: derive pdev ID somehow? */
struct ath12k_peer *peer = TAILQ_FIRST(&sc->peers);
int ret;
@@ -24501,7 +24464,7 @@ qwz_rx_agg_start(struct qwz_softc *sc, struct ieee80211_node *ni, uint8_t tid,
uint16_t ssn, uint16_t winsize)
{
struct ieee80211com *ic = &sc->sc_ic;
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
+ struct qwz_vif *arvif = &sc->sc_vif;
uint8_t pdev_id = 0; /* XXX derive pdev ID somehow */
enum hal_pn_type pn_type;
@@ -24521,7 +24484,7 @@ qwz_rx_agg_start(struct qwz_softc *sc, struct ieee80211_node *ni, uint8_t tid,
void
qwz_rx_agg_stop(struct qwz_softc *sc, struct ieee80211_node *ni, uint8_t tid)
{
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
+ struct qwz_vif *arvif = &sc->sc_vif;
uint8_t pdev_id = 0; /* XXX derive pdev ID somehow */
struct qwz_node *nq = (struct qwz_node *)ni;
struct ath12k_peer *peer;
@@ -24616,7 +24579,7 @@ qwz_run(struct qwz_softc *sc)
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = ic->ic_bss;
struct qwz_node *nq = (struct qwz_node *)ni;
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
+ struct qwz_vif *arvif = &sc->sc_vif;
uint8_t pdev_id = 0; /* TODO: derive pdev ID somehow? */
struct peer_assoc_params peer_arg;
int ret;
@@ -24736,7 +24699,7 @@ int
qwz_run_stop(struct qwz_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
- struct qwz_vif *arvif = TAILQ_FIRST(&sc->vif_list); /* XXX */
+ struct qwz_vif *arvif = &sc->sc_vif;
uint8_t pdev_id = 0; /* TODO: derive pdev ID somehow? */
struct qwz_node *nq = (void *)ic->ic_bss;
int ret;
@@ -24794,10 +24757,13 @@ qwz_attach(struct qwz_softc *sc)
for (i = 0; i < nitems(sc->pdevs); i++)
sc->pdevs[i].sc = sc;
- TAILQ_INIT(&sc->vif_list);
TAILQ_INIT(&sc->peers);
sc->bss_peer_id = HAL_INVALID_PEERID;
+ error = qwz_vif_alloc(sc);
+ if (error)
+ return error;
+
error = qwz_init(ifp);
if (error)
return error;
@@ -24811,6 +24777,8 @@ qwz_attach(struct qwz_softc *sc)
void
qwz_detach(struct qwz_softc *sc)
{
+ qwz_vif_free(sc);
+
if (sc->fwmem) {
qwz_dmamem_free(sc->sc_dmat, sc->fwmem);
sc->fwmem = NULL;
diff --git a/sys/dev/ic/qwzvar.h b/sys/dev/ic/qwzvar.h
index d60edfedaca..faaa661e881 100644
--- a/sys/dev/ic/qwzvar.h
+++ b/sys/dev/ic/qwzvar.h
@@ -1814,11 +1814,8 @@ struct qwz_vif {
uint8_t search_type;
int8_t bank_id; /* WCN7850/WiFi7 TX bank profile id, -1 if unset */
- struct qwz_softc *sc;
-
uint16_t tx_seq_no;
struct wmi_wmm_params_all_arg wmm_params;
- TAILQ_ENTRY(qwz_vif) entry;
union {
struct {
uint32_t uapsd;
@@ -1866,8 +1863,6 @@ struct qwz_vif {
struct qwz_txmgmt_queue txmgmt;
};
-TAILQ_HEAD(qwz_vif_list, qwz_vif);
-
struct qwz_survey_info {
int8_t noise;
uint64_t time;
@@ -2075,7 +2070,7 @@ struct qwz_softc {
uint32_t pktlog_defs_checksum;
- struct qwz_vif_list vif_list;
+ struct qwz_vif sc_vif;
struct qwz_pdev pdevs[MAX_RADIOS];
struct {
enum WMI_HOST_WLAN_BAND supported_bands;
--
2.55.0
From e6d8c2b673c76cac3a104d4da04c61d18ae51790 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:55:50 +0200
Subject: [PATCH 09/11] sys/qwz: allocate management maps at attach
Backport of sys/dev/ic/qwx.c,v 1.139 , sys/dev/ic/qwxvar.h,v 1.39
and sys/dev/pci/if_qwx_pci.c,v 1.40
---
sys/dev/ic/qwz.c | 12 +++---------
sys/dev/ic/qwzvar.h | 5 ++++-
sys/dev/pci/if_qwz_pci.c | 17 ++++++++++++++++-
3 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 0cc052f8231..3304c56c4f1 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -24739,7 +24739,7 @@ qwz_radiotap_attach(struct qwz_softc *sc)
}
#endif
-int
+void
qwz_attach(struct qwz_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
@@ -24760,24 +24760,18 @@ qwz_attach(struct qwz_softc *sc)
TAILQ_INIT(&sc->peers);
sc->bss_peer_id = HAL_INVALID_PEERID;
- error = qwz_vif_alloc(sc);
- if (error)
- return error;
-
error = qwz_init(ifp);
if (error)
- return error;
+ return;
/* Turn device off until interface comes up. */
qwz_core_deinit(sc);
-
- return 0;
}
void
qwz_detach(struct qwz_softc *sc)
{
- qwz_vif_free(sc);
+ qwz_vif_purge(sc);
if (sc->fwmem) {
qwz_dmamem_free(sc->sc_dmat, sc->fwmem);
diff --git a/sys/dev/ic/qwzvar.h b/sys/dev/ic/qwzvar.h
index faaa661e881..a0ceda486f2 100644
--- a/sys/dev/ic/qwzvar.h
+++ b/sys/dev/ic/qwzvar.h
@@ -2140,7 +2140,9 @@ int qwz_ext_intr(void *);
int qwz_dp_service_srng(struct qwz_softc *, int);
int qwz_init_hw_params(struct qwz_softc *);
-int qwz_attach(struct qwz_softc *);
+int qwz_vif_alloc(struct qwz_softc *);
+void qwz_vif_free(struct qwz_softc *);
+void qwz_attach(struct qwz_softc *);
void qwz_detach(struct qwz_softc *);
int qwz_activate(struct device *, int);
@@ -2149,6 +2151,7 @@ void qwz_ce_cleanup_pipes(struct qwz_softc *);
int qwz_ioctl(struct ifnet *, u_long, caddr_t);
void qwz_start(struct ifnet *);
+void qwz_stop(struct ifnet *);
void qwz_watchdog(struct ifnet *);
int qwz_media_change(struct ifnet *);
void qwz_init_task(void *);
diff --git a/sys/dev/pci/if_qwz_pci.c b/sys/dev/pci/if_qwz_pci.c
index 4decda11fe3..e2de2b790f5 100644
--- a/sys/dev/pci/if_qwz_pci.c
+++ b/sys/dev/pci/if_qwz_pci.c
@@ -858,12 +858,16 @@ qwz_pci_attach(struct device *parent, struct device *self, void *aux)
if (error)
goto err_pci_disable_msi;
+ error = qwz_vif_alloc(sc);
+ if (error)
+ goto err_pci_disable_msi;
+
psc->chan_ctxt = qwz_dmamem_alloc(sc->sc_dmat,
sizeof(struct qwz_mhi_chan_ctxt) * psc->max_chan, 0);
if (psc->chan_ctxt == NULL) {
printf("%s: could not allocate channel context array\n",
sc->sc_dev.dv_xname);
- goto err_pci_disable_msi;
+ goto err_vif_free;
}
if (psc->sc_pci_ops->alloc_xfer_rings(psc)) {
@@ -1037,6 +1041,8 @@ err_pci_free_xfer_rings:
err_pci_free_chan_ctxt:
qwz_dmamem_free(sc->sc_dmat, psc->chan_ctxt);
psc->chan_ctxt = NULL;
+err_vif_free:
+ qwz_vif_free(sc);
err_pci_disable_msi:
err_pci_free_region:
pci_intr_disestablish(psc->sc_pc, psc->sc_ih[0]);
@@ -1048,6 +1054,14 @@ qwz_pci_detach(struct device *self, int flags)
{
struct qwz_pci_softc *psc = (struct qwz_pci_softc *)self;
struct qwz_softc *sc = &psc->sc_sc;
+ struct ifnet *ifp = &sc->sc_ic.ic_if;
+
+ rw_enter_write(&sc->ioctl_rwl);
+ if (ifp->if_flags & IFF_RUNNING)
+ qwz_stop(ifp);
+ if (sc->fw_initialized)
+ qwz_core_deinit(sc);
+ rw_exit(&sc->ioctl_rwl);
if (psc->sc_ih[0]) {
pci_intr_disestablish(psc->sc_pc, psc->sc_ih[0]);
@@ -1055,6 +1069,7 @@ qwz_pci_detach(struct device *self, int flags)
}
qwz_detach(sc);
+ qwz_vif_free(sc);
qwz_pci_free_event_rings(psc);
qwz_pci_free_xfer_rings(psc);
--
2.55.0
From 54b6bfef1690273d98522ae898f8092b914fad96 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:57:09 +0200
Subject: [PATCH 10/11] sys/qwz: skip uninitialized CE polling
Based on sys/dev/ic/qwx.c,v 1.135
Track successful CE initialization to decide whether completion
polling is valid; provide dircet TX buffer reclamation for cold
cleanup after hardware reset, when ring polling is no longer safe.
---
sys/dev/ic/qwz.c | 23 +++++++++++++++++++++--
sys/dev/ic/qwzvar.h | 1 +
2 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 3304c56c4f1..e8ea6c328c8 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -20537,14 +20537,30 @@ void
qwz_ce_cleanup_pipes(struct qwz_softc *sc)
{
struct qwz_ce_pipe *pipe;
- int pipe_num;
+ int pipe_num, i;
for (pipe_num = 0; pipe_num < sc->hw_params.ce_count; pipe_num++) {
pipe = &sc->ce.ce_pipe[pipe_num];
qwz_ce_rx_pipe_cleanup(pipe);
/* Cleanup any src CE's which have interrupts disabled */
- qwz_ce_poll_send_completed(sc, pipe_num);
+ if (sc->ce_initialized)
+ qwz_ce_poll_send_completed(sc, pipe_num);
+ else if (pipe->src_ring) {
+ for (i = 0; i < pipe->src_ring->nentries; i++) {
+ struct qwz_tx_data *tx_data =
+ pipe->src_ring->per_transfer_context[i];
+
+ if (tx_data == NULL || tx_data->m == NULL)
+ continue;
+ 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;
+ }
+ }
}
}
@@ -20670,6 +20686,8 @@ qwz_ce_init_pipes(struct qwz_softc *sc)
int i;
int ret;
+ sc->ce_initialized = 0;
+
qwz_ce_get_shadow_config(sc, &sc->qmi_ce_cfg.shadow_reg_v3,
&sc->qmi_ce_cfg.shadow_reg_v3_len);
@@ -20722,6 +20740,7 @@ qwz_ce_init_pipes(struct qwz_softc *sc)
}
}
+ sc->ce_initialized = 1;
return 0;
}
diff --git a/sys/dev/ic/qwzvar.h b/sys/dev/ic/qwzvar.h
index a0ceda486f2..8cd3efde026 100644
--- a/sys/dev/ic/qwzvar.h
+++ b/sys/dev/ic/qwzvar.h
@@ -2006,6 +2006,7 @@ struct qwz_softc {
int attached;
int fw_initialized;
+ int ce_initialized;
struct {
u_char *data;
size_t size;
--
2.55.0
From dfd8c8bc6dd756d61e2a0df4cd0c9be5f0f58ba9 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <kirill@korins.ky>
Date: Sun, 27 Sep 2026 12:57:12 +0200
Subject: [PATCH 11/11] sys/qwz: unwind cold startup failures
Based on sys/dev/ic/qwx.c,v 1.134
Track powerup and completed core initialization so failed cold starts
reset hardware before reclaiming initialized DMA resources. Release
partial TX allocations and RX rings; ordinary interface down and up
continues to retain firmware.
---
sys/dev/ic/qwz.c | 124 +++++++++++++++++++++++++++++++--------
sys/dev/ic/qwzvar.h | 1 +
sys/dev/pci/if_qwz_pci.c | 4 +-
3 files changed, 103 insertions(+), 26 deletions(-)
diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index e8ea6c328c8..2e2eb80461c 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -140,6 +140,8 @@ int qwz_wmi_peer_rx_reorder_queue_setup(struct qwz_softc *, int, int,
uint8_t *, uint64_t, uint8_t, uint8_t, uint32_t);
const void **qwz_wmi_tlv_parse_alloc(struct qwz_softc *, const void *, size_t);
int qwz_core_init(struct qwz_softc *);
+void qwz_power_down(struct qwz_softc *);
+void qwz_core_init_cleanup(struct qwz_softc *, int);
int qwz_qmi_event_server_arrive(struct qwz_softc *);
int qwz_mac_register(struct qwz_softc *);
int qwz_mac_start(struct qwz_softc *);
@@ -214,7 +216,7 @@ qwz_free_peers(struct qwz_softc *sc)
int
qwz_init(struct ifnet *ifp)
{
- int error;
+ int error, core_ready = 0;
struct qwz_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
int s = splnet();
@@ -289,6 +291,7 @@ qwz_init(struct ifnet *ifp)
memset(&sc->qrtr_server, 0, sizeof(sc->qrtr_server));
sc->qrtr_server.node = QRTR_NODE_BCAST;
+ set_bit(ATH12K_FLAG_QMI_FAIL, sc->sc_flags);
error = qwz_core_init(sc);
if (error) {
@@ -302,16 +305,14 @@ qwz_init(struct ifnet *ifp)
SEC_TO_NSEC(5));
if (error) {
printf("%s: qrtr init timeout\n", sc->sc_dev.dv_xname);
- splx(s);
- return error;
+ goto fail;
}
}
error = qwz_qmi_event_server_arrive(sc);
- if (error) {
- splx(s);
- return error;
- }
+ if (error)
+ goto fail;
+ core_ready = 1;
if (sc->attached) {
/* Update MAC in case the upper layers changed it. */
@@ -336,10 +337,8 @@ qwz_init(struct ifnet *ifp)
if (ifp->if_flags & IFF_UP) {
error = qwz_mac_start(sc);
- if (error) {
- splx(s);
- return error;
- }
+ if (error)
+ goto fail;
refcnt_init(&sc->task_refs);
ifq_clr_oactive(&ifp->if_snd);
@@ -351,6 +350,11 @@ qwz_init(struct ifnet *ifp)
sc->fw_initialized = 1;
splx(s);
return 0;
+
+fail:
+ qwz_core_init_cleanup(sc, core_ready);
+ splx(s);
+ return error;
}
void
@@ -7802,6 +7806,7 @@ qwz_dp_link_desc_setup(struct qwz_softc *sc,
return 0;
fail_desc_bank_free:
+ qwz_power_down(sc);
qwz_dp_link_desc_bank_free(sc, link_desc_banks);
return ret;
@@ -8300,6 +8305,7 @@ qwz_dp_srng_common_setup(struct qwz_softc *sc)
return 0;
err:
+ qwz_power_down(sc);
qwz_dp_srng_common_cleanup(sc);
return ret;
@@ -8329,12 +8335,16 @@ qwz_dp_tx_ring_free_tx_data(struct qwz_softc *sc, struct dp_tx_ring *tx_ring)
for (i = 0; i < sc->hw_params.tx_ring_size; i++) {
struct qwz_tx_data *tx_data = &tx_ring->data[i];
- if (tx_data->map) {
+ 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);
- bus_dmamap_destroy(sc->sc_dmat, tx_data->map);
+ m_freem(tx_data->m);
}
-
- m_freem(tx_data->m);
+ if (tx_data->ni)
+ ieee80211_release_node(&sc->sc_ic, tx_data->ni);
+ if (tx_data->map)
+ bus_dmamap_destroy(sc->sc_dmat, tx_data->map);
}
free(tx_ring->data, M_DEVBUF,
@@ -8703,6 +8713,7 @@ qwz_dp_cc_init(struct qwz_softc *sc)
return 0;
free:
+ qwz_power_down(sc);
qwz_dp_cc_cleanup(sc);
return ret;
}
@@ -8822,7 +8833,15 @@ qwz_dp_rx_alloc(struct qwz_softc *sc)
void
qwz_dp_rx_free(struct qwz_softc *sc)
{
- /* FIXME */
+ struct qwz_dp *dp = &sc->dp;
+ int i;
+
+ qwz_dp_srng_cleanup(sc, &dp->rx_refill_buf_ring.refill_buf_ring);
+ for (i = 0; i < sc->hw_params.num_rxmda_per_pdev; i++)
+ qwz_dp_srng_cleanup(sc, &dp->rx_mac_buf_ring[i]);
+ for (i = 0; i < sc->hw_params.num_rxdma_dst_ring; i++)
+ qwz_dp_srng_cleanup(sc, &dp->rxdma_err_dst_ring[i]);
+ qwz_dp_srng_cleanup(sc, &dp->rxdma_mon_buf_ring.refill_buf_ring);
}
int
@@ -8898,7 +8917,7 @@ qwz_dp_alloc(struct qwz_softc *sc)
if (ret) {
printf("%s: failed to setup link desc: %d\n",
sc->sc_dev.dv_xname, ret);
- return ret;
+ goto fail_link_desc_cleanup;
}
ret = qwz_dp_cc_init(sc);
@@ -8926,7 +8945,7 @@ qwz_dp_alloc(struct qwz_softc *sc)
#endif
ret = qwz_dp_tx_ring_alloc_tx_data(sc, &dp->tx_ring[i]);
if (ret)
- goto fail_cmn_reoq_cleanup;
+ goto fail_tx_data_cleanup;
dp->tx_ring[i].cur = 0;
dp->tx_ring[i].queued = 0;
@@ -8948,16 +8967,27 @@ qwz_dp_alloc(struct qwz_softc *sc)
return 0;
fail_dp_rx_free:
+ qwz_power_down(sc);
qwz_dp_rx_free(sc);
-fail_cmn_reoq_cleanup:
+fail_tx_data_cleanup:
+ qwz_power_down(sc);
+ for (i = 0; i < sc->hw_params.max_tx_ring; i++) {
+ qwz_dp_tx_ring_free_tx_data(sc, &dp->tx_ring[i]);
+ free(dp->tx_ring[i].tx_status, M_DEVBUF, size);
+ dp->tx_ring[i].tx_status = NULL;
+ }
qwz_dp_reoq_lut_cleanup(sc);
fail_cmn_srng_cleanup:
+ qwz_power_down(sc);
qwz_dp_srng_common_cleanup(sc);
fail_dp_bank_profiles_cleanup:
+ qwz_power_down(sc);
qwz_dp_deinit_bank_profiles(sc);
fail_hw_cc_cleanup:
+ qwz_power_down(sc);
qwz_dp_cc_cleanup(sc);
fail_link_desc_cleanup:
+ qwz_power_down(sc);
qwz_dp_link_desc_cleanup(sc, dp->link_desc_banks, HAL_WBM_IDLE_LINK,
&dp->wbm_idle_ring);
@@ -9012,6 +9042,7 @@ qwz_dp_free(struct qwz_softc *sc)
qwz_dp_link_desc_cleanup(sc, dp->link_desc_banks,
HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring);
+ qwz_dp_rx_free(sc);
qwz_dp_cc_cleanup(sc);
qwz_dp_reoq_lut_cleanup(sc);
qwz_dp_srng_common_cleanup(sc);
@@ -13107,6 +13138,7 @@ qwz_dp_pdev_reo_setup(struct qwz_softc *sc)
HAL_REO_DST, i, 0, DP_REO_DST_RING_SIZE);
if (ret) {
printf("%s: failed to setup reo_dst_ring\n", __func__);
+ qwz_power_down(sc);
qwz_dp_pdev_reo_cleanup(sc);
return ret;
}
@@ -14022,6 +14054,7 @@ qwz_dp_pdev_alloc(struct qwz_softc *sc)
return 0;
err:
+ qwz_power_down(sc);
qwz_dp_pdev_free(sc);
return ret;
@@ -18616,7 +18649,7 @@ qwz_core_start(struct qwz_softc *sc)
if (ret) {
printf("%s: failed to send dbs mode: %d\n",
__func__, ret);
- goto err_hif_stop;
+ goto err_reo_cleanup;
}
ret = qwz_wmi_wait_for_hw_mode_ready(sc);
@@ -18638,14 +18671,17 @@ qwz_core_start(struct qwz_softc *sc)
return 0;
err_reo_cleanup:
+ qwz_power_down(sc);
qwz_dp_pdev_reo_cleanup(sc);
err_mac_destroy:
#if 0
ath12k_mac_destroy(ab);
#endif
err_hif_stop:
+ qwz_power_down(sc);
sc->ops.stop(sc);
err_wmi_detach:
+ qwz_power_down(sc);
qwz_wmi_detach(sc);
return ret;
}
@@ -18653,9 +18689,12 @@ err_wmi_detach:
void
qwz_core_stop(struct qwz_softc *sc)
{
- if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags))
+ if (sc->powered &&
+ !test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags) &&
+ !test_bit(ATH12K_FLAG_QMI_FAIL, sc->sc_flags))
qwz_qmi_firmware_stop(sc);
+ qwz_power_down(sc);
sc->ops.stop(sc);
qwz_wmi_detach(sc);
qwz_dp_pdev_reo_cleanup(sc);
@@ -18708,6 +18747,7 @@ err_mac_unregister:
ath12k_mac_unregister(ab);
#endif
err_dp_pdev_free:
+ qwz_power_down(sc);
qwz_dp_pdev_free(sc);
#if 0
err_pdev_debug:
@@ -18732,7 +18772,6 @@ qwz_core_deinit(struct qwz_softc *sc)
#ifdef notyet
mutex_unlock(&ab->core_lock);
#endif
- sc->ops.power_down(sc);
qwz_vif_purge(sc);
qwz_free_peers(sc);
#if 0
@@ -18748,6 +18787,8 @@ qwz_core_deinit(struct qwz_softc *sc)
hal->num_shadow_reg_configured = 0;
sc->fw_initialized = 0;
+ sc->pdevs_active = 0;
+ set_bit(ATH12K_FLAG_QMI_FAIL, sc->sc_flags);
splx(s);
}
@@ -18790,7 +18831,8 @@ qwz_core_qmi_firmware_ready(struct qwz_softc *sc)
default:
printf("%s: invalid crypto_mode: %d\n",
sc->sc_dev.dv_xname, sc->crypto_mode);
- return EINVAL;
+ ret = EINVAL;
+ goto err_dp_free;
}
if (sc->frame_mode == ATH12K_HW_TXRX_RAW)
@@ -18833,12 +18875,15 @@ err_core_stop:
ath12k_mac_destroy(ab);
#endif
err_dp_free:
+ qwz_power_down(sc);
qwz_dp_free(sc);
#if 0
mutex_unlock(&ab->core_lock);
#endif
err_firmware_stop:
- qwz_qmi_firmware_stop(sc);
+ if (sc->powered)
+ qwz_qmi_firmware_stop(sc);
+ qwz_power_down(sc);
return ret;
}
@@ -18927,6 +18972,34 @@ qwz_qmi_event_server_arrive(struct qwz_softc *sc)
return qwz_qmi_fw_ready(sc);
}
+void
+qwz_power_down(struct qwz_softc *sc)
+{
+ if (!sc->powered)
+ return;
+
+ sc->ops.irq_disable(sc);
+ sc->ops.power_down(sc);
+ sc->powered = 0;
+ sc->ce_initialized = 0;
+}
+
+void
+qwz_core_init_cleanup(struct qwz_softc *sc, int core_ready)
+{
+ if (core_ready) {
+ qwz_core_deinit(sc);
+ return;
+ }
+
+ qwz_power_down(sc);
+ sc->ops.stop(sc);
+ qwz_qmi_deinit_service(sc);
+ sc->hal.num_shadow_reg_configured = 0;
+ sc->pdevs_active = 0;
+ set_bit(ATH12K_FLAG_QMI_FAIL, sc->sc_flags);
+}
+
int
qwz_core_init(struct qwz_softc *sc)
{
@@ -18939,11 +19012,12 @@ qwz_core_init(struct qwz_softc *sc)
return error;
}
+ sc->powered = 1;
error = sc->ops.power_up(sc);
if (error) {
printf("%s: failed to power up :%d\n",
sc->sc_dev.dv_xname, error);
- qwz_qmi_deinit_service(sc);
+ qwz_core_init_cleanup(sc, 0);
}
return error;
diff --git a/sys/dev/ic/qwzvar.h b/sys/dev/ic/qwzvar.h
index 8cd3efde026..6f748f92b59 100644
--- a/sys/dev/ic/qwzvar.h
+++ b/sys/dev/ic/qwzvar.h
@@ -2007,6 +2007,7 @@ struct qwz_softc {
int attached;
int fw_initialized;
int ce_initialized;
+ int powered;
struct {
u_char *data;
size_t size;
diff --git a/sys/dev/pci/if_qwz_pci.c b/sys/dev/pci/if_qwz_pci.c
index e2de2b790f5..4bd8819d41a 100644
--- a/sys/dev/pci/if_qwz_pci.c
+++ b/sys/dev/pci/if_qwz_pci.c
@@ -1662,7 +1662,8 @@ qwz_pcic_ce_irq_disable_sync(struct qwz_softc *sc)
void
qwz_pci_stop(struct qwz_softc *sc)
{
- qwz_pcic_ce_irq_disable_sync(sc);
+ if (sc->powered)
+ qwz_pcic_ce_irq_disable_sync(sc);
qwz_ce_cleanup_pipes(sc);
}
@@ -2371,6 +2372,7 @@ qwz_pci_power_down(struct qwz_softc *sc)
/* Restore ASPM in case firmware bootup fails. */
qwz_pci_aspm_restore(sc);
+ qwz_pcic_ce_irq_disable_sync(sc);
qwz_pci_force_wake(sc);
qwz_mhi_stop_channels(psc);
--
2.55.0
--
wbr, Kirill
Third batch of qwz commits