Stefan,

here the 6th batch of qwz commits.

It is quite mechanical with exception of one commit where I fix REO layout
to that I had discovered in ath12k, and the next one fixes its lifetime.

It was tested on my device and makes it works better, but I may make typos.

Ok?

From d9ab1f87492f1fb420c1db383b1db95a49954bdf Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <[email protected]>
Date: Sun, 27 Sep 2026 12:54:40 +0200
Subject: [PATCH 1/7] sys/qwz: update RSSI from TX acknowledgments

Backport of sys/dev/ic/qwx.c,v 1.98
---
 sys/dev/ic/qwz.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 54f58f1f9ce..e517b9f417a 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -14561,6 +14561,16 @@ qwz_dp_tx_complete_msdu(struct qwz_softc *sc, struct 
dp_tx_ring *tx_ring,
        } else if (pkt_type == HAL_TX_RATE_STATS_PKT_TYPE_11N)
                tx_data->ni->ni_txmcs = mcs;
 
+       if (ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED &&
+           ts->ack_rssi != 0) {
+               int8_t rssi_dbm = (int8_t)ts->ack_rssi;
+
+               if (!isset(sc->wmi.svc_map,
+                   WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT))
+                       rssi_dbm += ATH12K_DEFAULT_NOISE_FLOOR;
+               tx_data->ni->ni_rssi = rssi_dbm;
+       }
+
        ieee80211_release_node(ic, tx_data->ni);
        tx_data->ni = NULL;
 }
-- 
2.55.0


From 444ab6aeef335b30552052c536ad328ffcdac5f5 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <[email protected]>
Date: Sun, 27 Sep 2026 12:56:21 +0200
Subject: [PATCH 2/7] sys/qwz: clear node flags during deauthentication

Backport of sys/dev/ic/qwx.c,v 1.113
---
 sys/dev/ic/qwz.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index e517b9f417a..b018119e9ba 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -24388,11 +24388,18 @@ qwz_auth(struct qwz_softc *sc)
 int
 qwz_deauth(struct qwz_softc *sc)
 {
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct qwz_node *nq = (struct qwz_node *)ic->ic_bss;
        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;
 
+       if (ic->ic_opmode == IEEE80211_M_STA) {
+               ic->ic_bss->ni_txrate = 0;
+               nq->flags = 0;
+       }
+
        ret = qwz_mac_vdev_stop(sc, arvif, pdev_id);
        if (ret) {
                printf("%s: unable to stop vdev vdev_id %d: %d\n",
-- 
2.55.0


From 941e13bb341b1f37d342a86ac75e363a05d24a4c Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <[email protected]>
Date: Sun, 27 Sep 2026 12:56:08 +0200
Subject: [PATCH 3/7] sys/qwz: keep data interrupts through association

Backport of sys/dev/ic/qwx.c,v 1.125
---
 sys/dev/ic/qwz.c | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index b018119e9ba..cbe8ad6ff4e 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -250,6 +250,7 @@ qwz_init(struct ifnet *ifp)
                        refcnt_init(&sc->task_refs);
                        ifq_clr_oactive(&ifp->if_snd);
                        ifp->if_flags |= IFF_RUNNING;
+                       sc->ops.irq_enable(sc);
                        ieee80211_begin_scan(ifp);
                }
                splx(s);
@@ -357,6 +358,7 @@ qwz_init(struct ifnet *ifp)
                ifq_clr_oactive(&ifp->if_snd);
                ifp->if_flags |= IFF_RUNNING;
 
+               sc->ops.irq_enable(sc);
                ieee80211_begin_scan(ifp);
        }
 
@@ -18969,10 +18971,6 @@ qwz_core_qmi_firmware_ready(struct qwz_softc *sc)
                goto err_core_stop;
        }
 
-#if 0 /* TODO: Is this in the right spot for OpenBSD? */
-       sc->ops.irq_enable(sc);
-#endif
-
 #if 0
        mutex_unlock(&ab->core_lock);
 #endif
@@ -24915,8 +24913,6 @@ qwz_run(struct qwz_softc *sc)
        DNPRINTF(QWZ_D_MAC, "%s: vdev %d up (associated) bssid %s aid %d\n",
            __func__, arvif->vdev_id, ether_sprintf(ni->ni_bssid), arvif->aid);
 
-       /* Enable "ext" IRQs for datapath. */
-       sc->ops.irq_enable(sc);
 
        return 0;
 }
@@ -24930,8 +24926,6 @@ qwz_run_stop(struct qwz_softc *sc)
        struct qwz_node *nq = (void *)ic->ic_bss;
        int ret;
 
-       sc->ops.irq_disable(sc);
-
        if (ic->ic_opmode == IEEE80211_M_STA) {
                ic->ic_bss->ni_txrate = 0;
                nq->flags = 0;
-- 
2.55.0


From 64f0e21feed6cafe1fd93688ed0737247cc467e3 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <[email protected]>
Date: Sun, 27 Sep 2026 12:56:11 +0200
Subject: [PATCH 4/7] sys/qwz: prepare peers before association requests

Backport of sys/dev/ic/qwx.c,v 1.94, sys/dev/ic/qwx.c,v 1.118
---
 sys/dev/ic/qwz.c | 60 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 52 insertions(+), 8 deletions(-)

diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index cbe8ad6ff4e..7eb5465f5d8 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -180,6 +180,7 @@ int qwz_scan(struct qwz_softc *);
 void qwz_scan_abort(struct qwz_softc *);
 int qwz_auth(struct qwz_softc *);
 int qwz_deauth(struct qwz_softc *);
+int qwz_assoc(struct qwz_softc *);
 int qwz_run(struct qwz_softc *);
 int qwz_run_stop(struct qwz_softc *);
 
@@ -1114,6 +1115,7 @@ next_scan:
                break;
 
        case IEEE80211_S_ASSOC:
+               err = qwz_assoc(sc);
                break;
 
        case IEEE80211_S_RUN:
@@ -24408,13 +24410,6 @@ qwz_deauth(struct qwz_softc *sc)
        if (peer == NULL)
                return 0;
 
-       ret = qwz_wmi_set_peer_param(sc, peer->addr, arvif->vdev_id,
-           pdev_id, WMI_PEER_AUTHORIZE, 0);
-       if (ret) {
-               printf("%s: unable to deauthorize BSS peer: %d\n",
-                  sc->sc_dev.dv_xname, ret);
-               return ret;
-       }
 
        ret = qwz_mac_station_remove(sc, arvif, pdev_id, peer);
        if (ret)
@@ -24798,7 +24793,7 @@ qwz_ampdu_tx_start(struct ieee80211com *ic, struct 
ieee80211_node *ni,
 }
 
 int
-qwz_run(struct qwz_softc *sc)
+qwz_assoc(struct qwz_softc *sc)
 {
        struct ieee80211com *ic = &sc->sc_ic;
        struct ieee80211_node *ni = ic->ic_bss;
@@ -24870,6 +24865,43 @@ qwz_run(struct qwz_softc *sc)
                        return ret;
                }
        }
+
+       return 0;
+}
+
+int
+qwz_run(struct qwz_softc *sc)
+{
+       struct ieee80211com *ic = &sc->sc_ic;
+       struct ieee80211_node *ni = ic->ic_bss;
+       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;
+
+       qwz_peer_assoc_prepare(sc, arvif, ni, &peer_arg, 1);
+
+       peer_arg.is_assoc = 1;
+
+       sc->peer_assoc_done = 0;
+       ret = qwz_wmi_send_peer_assoc_cmd(sc, pdev_id, &peer_arg);
+       if (ret) {
+               printf("%s: failed to run peer assoc for %s vdev %i: %d\n",
+                   sc->sc_dev.dv_xname, ether_sprintf(ni->ni_macaddr),
+                   arvif->vdev_id, ret);
+               return ret;
+       }
+
+       while (!sc->peer_assoc_done) {
+               ret = tsleep_nsec(&sc->peer_assoc_done, 0, "qwzassoc",
+                   SEC_TO_NSEC(1));
+               if (ret) {
+                       printf("%s: failed to get peer assoc conf event "
+                           "for %s vdev %i\n", sc->sc_dev.dv_xname,
+                           ether_sprintf(ni->ni_macaddr), arvif->vdev_id);
+                       return ret;
+               }
+       }
 #if 0
        ret = ath12k_setup_peer_smps(ar, arvif, sta->addr,
                                     &sta->deflink.ht_cap,
@@ -24924,8 +24956,20 @@ qwz_run_stop(struct qwz_softc *sc)
        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;
+       struct ath12k_peer *peer = TAILQ_FIRST(&sc->peers);
        int ret;
 
+       if (peer != NULL) {
+               ret = qwz_wmi_set_peer_param(sc, peer->addr, arvif->vdev_id,
+                   pdev_id, WMI_PEER_AUTHORIZE, 0);
+               if (ret) {
+                       printf("%s: unable to deauthorize BSS peer: %d\n",
+                          sc->sc_dev.dv_xname, ret);
+                       return ret;
+               }
+
+       }
+
        if (ic->ic_opmode == IEEE80211_M_STA) {
                ic->ic_bss->ni_txrate = 0;
                nq->flags = 0;
-- 
2.55.0


From b46032b456e356b3befae341d4869c1dd09d5762 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <[email protected]>
Date: Sun, 27 Sep 2026 12:56:14 +0200
Subject: [PATCH 5/7] sys/qwz: configure negotiated HT SMPS

Backport of sys/dev/ic/qwx.c,v 1.92
---
 sys/dev/ic/qwz.c | 46 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 36 insertions(+), 10 deletions(-)

diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 7eb5465f5d8..24ca756e304 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -24792,6 +24792,33 @@ qwz_ampdu_tx_start(struct ieee80211com *ic, struct 
ieee80211_node *ni,
        return 0;
 }
 
+int
+qwz_setup_peer_smps(struct qwz_softc *sc, uint8_t pdev_id, struct qwz_vif 
*arvif,
+    uint8_t *addr, uint16_t htcaps)
+{
+       uint16_t smps;
+       uint32_t val;
+
+       smps = (htcaps & IEEE80211_HTCAP_SMPS_MASK) >>
+           IEEE80211_HTCAP_SMPS_SHIFT;
+
+       switch (smps) {
+       case IEEE80211_HTCAP_SMPS_STA:
+               val = WMI_PEER_SMPS_STATIC;
+               break;
+       case IEEE80211_HTCAP_SMPS_DYN:
+               val = WMI_PEER_SMPS_DYNAMIC;
+               break;
+       case IEEE80211_HTCAP_SMPS_DIS:
+       default:
+               val = WMI_PEER_SMPS_PS_NONE;
+               break;
+       }
+
+       return qwz_wmi_set_peer_param(sc, addr, arvif->vdev_id,
+           pdev_id, WMI_PEER_MIMO_PS_STATE, val);
+}
+
 int
 qwz_assoc(struct qwz_softc *sc)
 {
@@ -24902,15 +24929,16 @@ qwz_run(struct qwz_softc *sc)
                        return ret;
                }
        }
-#if 0
-       ret = ath12k_setup_peer_smps(ar, arvif, sta->addr,
-                                    &sta->deflink.ht_cap,
-                                    
le16_to_cpu(sta->deflink.he_6ghz_capa.capa));
-       if (ret) {
-               ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: 
%d\n",
-                           arvif->vdev_id, ret);
-               return ret;
+       if (ni->ni_flags & IEEE80211_NODE_HT) {
+               ret = qwz_setup_peer_smps(sc, pdev_id, arvif, ni->ni_macaddr,
+                   ni->ni_htcaps);
+               if (ret) {
+                       printf("%s: failed to setup SMPS for vdev %d: %d\n",
+                           sc->sc_dev.dv_xname, arvif->vdev_id, ret);
+                       return ret;
+               }
        }
+#if 0
 
        if (!ath12k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) {
                ath12k_warn(ar->ab, "failed to recalc he txbf for vdev %i on 
bss %pM\n",
@@ -24945,7 +24973,6 @@ qwz_run(struct qwz_softc *sc)
        DNPRINTF(QWZ_D_MAC, "%s: vdev %d up (associated) bssid %s aid %d\n",
            __func__, arvif->vdev_id, ether_sprintf(ni->ni_bssid), arvif->aid);
 
-
        return 0;
 }
 
@@ -24967,7 +24994,6 @@ qwz_run_stop(struct qwz_softc *sc)
                           sc->sc_dev.dv_xname, ret);
                        return ret;
                }
-
        }
 
        if (ic->ic_opmode == IEEE80211_M_STA) {
-- 
2.55.0


From 91870f9306624e78301f76272239208560e169e9 Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <[email protected]>
Date: Sun, 27 Sep 2026 12:57:39 +0200
Subject: [PATCH 6/7] sys/qwz: fix WCN7850 REO layout

Use WCN7850 REO tags and 64-bit TLV headers so commands and completions
use the correct offsets. Correct the status ring size and clear command
payloads before reuse.

The layout follows Linux ath12k's WCN7850 definitions.
---
 sys/dev/ic/qwz.c    | 165 ++++++++++++++++++++++++++------------------
 sys/dev/ic/qwzreg.h |  32 ++++-----
 2 files changed, 113 insertions(+), 84 deletions(-)

diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 24ca756e304..6d79eec5376 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -8004,7 +8004,7 @@ void
 qwz_hal_reo_init_cmd_ring(struct qwz_softc *sc, struct hal_srng *srng)
 {
        struct hal_srng_params params;
-       struct hal_tlv_hdr *tlv;
+       struct hal_tlv_64_hdr *tlv;
        struct hal_reo_get_queue_stats *desc;
        int i, cmd_num = 1;
        int entry_size;
@@ -8017,39 +8017,44 @@ qwz_hal_reo_init_cmd_ring(struct qwz_softc *sc, struct 
hal_srng *srng)
        entry = (uint8_t *)params.ring_base_vaddr;
 
        for (i = 0; i < params.num_entries; i++) {
-               tlv = (struct hal_tlv_hdr *)entry;
+               tlv = (struct hal_tlv_64_hdr *)entry;
                desc = (struct hal_reo_get_queue_stats *)tlv->value;
-               desc->cmd.info0 = FIELD_PREP(HAL_REO_CMD_HDR_INFO0_CMD_NUMBER,
-                   cmd_num++);
+               desc->cmd.info0 = 
htole32(FIELD_PREP(HAL_REO_CMD_HDR_INFO0_CMD_NUMBER,
+                   cmd_num++));
                entry += entry_size;
        }
 }
 
 int
-qwz_hal_reo_cmd_queue_stats(struct hal_tlv_hdr *tlv, struct ath12k_hal_reo_cmd 
*cmd)
+qwz_hal_reo_cmd_queue_stats(struct hal_tlv_64_hdr *tlv,
+    struct ath12k_hal_reo_cmd *cmd)
 {
        struct hal_reo_get_queue_stats *desc;
 
-       tlv->tl = FIELD_PREP(HAL_TLV_HDR_TAG, HAL_REO_GET_QUEUE_STATS) |
-           FIELD_PREP(HAL_TLV_HDR_LEN, sizeof(*desc));
+       tlv->tl = htole64(FIELD_PREP(HAL_TLV_HDR_TAG, HAL_REO_GET_QUEUE_STATS) |
+           FIELD_PREP(HAL_TLV_HDR_LEN, sizeof(*desc)));
 
        desc = (struct hal_reo_get_queue_stats *)tlv->value;
+       memset(&desc->queue_addr_lo, 0,
+           sizeof(*desc) - offsetof(struct hal_reo_get_queue_stats, 
queue_addr_lo));
 
-       desc->cmd.info0 &= ~HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED;
+       desc->cmd.info0 &= ~htole32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
        if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
-               desc->cmd.info0 |= HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED;
+               desc->cmd.info0 |= 
htole32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
 
-       desc->queue_addr_lo = cmd->addr_lo;
+       desc->queue_addr_lo = htole32(cmd->addr_lo);
        desc->info0 = FIELD_PREP(HAL_REO_GET_QUEUE_STATS_INFO0_QUEUE_ADDR_HI,
            cmd->addr_hi);
        if (cmd->flag & HAL_REO_CMD_FLG_STATS_CLEAR)
                desc->info0 |= HAL_REO_GET_QUEUE_STATS_INFO0_CLEAR_STATS;
 
-       return FIELD_GET(HAL_REO_CMD_HDR_INFO0_CMD_NUMBER, desc->cmd.info0);
+       desc->info0 = htole32(desc->info0);
+       return FIELD_GET(HAL_REO_CMD_HDR_INFO0_CMD_NUMBER,
+           le32toh(desc->cmd.info0));
 }
 
 int
-qwz_hal_reo_cmd_flush_cache(struct ath12k_hal *hal, struct hal_tlv_hdr *tlv,
+qwz_hal_reo_cmd_flush_cache(struct ath12k_hal *hal, struct hal_tlv_64_hdr *tlv,
     struct ath12k_hal_reo_cmd *cmd)
 {
        struct hal_reo_flush_cache *desc;
@@ -8062,16 +8067,18 @@ qwz_hal_reo_cmd_flush_cache(struct ath12k_hal *hal, 
struct hal_tlv_hdr *tlv,
                hal->current_blk_index = avail_slot;
        }
 
-       tlv->tl = FIELD_PREP(HAL_TLV_HDR_TAG, HAL_REO_FLUSH_CACHE) |
-           FIELD_PREP(HAL_TLV_HDR_LEN, sizeof(*desc));
+       tlv->tl = htole64(FIELD_PREP(HAL_TLV_HDR_TAG, HAL_REO_FLUSH_CACHE) |
+           FIELD_PREP(HAL_TLV_HDR_LEN, sizeof(*desc)));
 
        desc = (struct hal_reo_flush_cache *)tlv->value;
+       memset(&desc->cache_addr_lo, 0,
+           sizeof(*desc) - offsetof(struct hal_reo_flush_cache, 
cache_addr_lo));
 
-       desc->cmd.info0 &= ~HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED;
+       desc->cmd.info0 &= ~htole32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
        if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
-               desc->cmd.info0 |= HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED;
+               desc->cmd.info0 |= 
htole32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
 
-       desc->cache_addr_lo = cmd->addr_lo;
+       desc->cache_addr_lo = htole32(cmd->addr_lo);
        desc->info0 = FIELD_PREP(HAL_REO_FLUSH_CACHE_INFO0_CACHE_ADDR_HI,
            cmd->addr_hi);
 
@@ -8091,25 +8098,29 @@ qwz_hal_reo_cmd_flush_cache(struct ath12k_hal *hal, 
struct hal_tlv_hdr *tlv,
        if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_ALL)
                desc->info0 |= HAL_REO_FLUSH_CACHE_INFO0_FLUSH_ALL;
 
-       return FIELD_GET(HAL_REO_CMD_HDR_INFO0_CMD_NUMBER, desc->cmd.info0);
+       desc->info0 = htole32(desc->info0);
+       return FIELD_GET(HAL_REO_CMD_HDR_INFO0_CMD_NUMBER,
+           le32toh(desc->cmd.info0));
 }
 
 int
-qwz_hal_reo_cmd_update_rx_queue(struct hal_tlv_hdr *tlv,
+qwz_hal_reo_cmd_update_rx_queue(struct hal_tlv_64_hdr *tlv,
     struct ath12k_hal_reo_cmd *cmd)
 {
        struct hal_reo_update_rx_queue *desc;
 
-       tlv->tl = FIELD_PREP(HAL_TLV_HDR_TAG, HAL_REO_UPDATE_RX_REO_QUEUE) |
-           FIELD_PREP(HAL_TLV_HDR_LEN, sizeof(*desc));
+       tlv->tl = htole64(FIELD_PREP(HAL_TLV_HDR_TAG, 
HAL_REO_UPDATE_RX_REO_QUEUE) |
+           FIELD_PREP(HAL_TLV_HDR_LEN, sizeof(*desc)));
 
        desc = (struct hal_reo_update_rx_queue *)tlv->value;
+       memset(&desc->queue_addr_lo, 0,
+           sizeof(*desc) - offsetof(struct hal_reo_update_rx_queue, 
queue_addr_lo));
 
-       desc->cmd.info0 &= ~HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED;
+       desc->cmd.info0 &= ~htole32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
        if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
-               desc->cmd.info0 |= HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED;
+               desc->cmd.info0 |= 
htole32(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
 
-       desc->queue_addr_lo = cmd->addr_lo;
+       desc->queue_addr_lo = htole32(cmd->addr_lo);
        desc->info0 =
                FIELD_PREP(HAL_REO_UPD_RX_QUEUE_INFO0_QUEUE_ADDR_HI,
                    cmd->addr_hi) |
@@ -8215,20 +8226,25 @@ qwz_hal_reo_cmd_update_rx_queue(struct hal_tlv_hdr *tlv,
            FIELD_PREP(HAL_REO_UPD_RX_QUEUE_INFO2_PN_ERR,
                !!(cmd->upd2 & HAL_REO_CMD_UPD2_PN_ERR));
 
-       return FIELD_GET(HAL_REO_CMD_HDR_INFO0_CMD_NUMBER, desc->cmd.info0);
+       desc->info0 = htole32(desc->info0);
+       desc->info1 = htole32(desc->info1);
+       desc->info2 = htole32(desc->info2);
+       return FIELD_GET(HAL_REO_CMD_HDR_INFO0_CMD_NUMBER,
+           le32toh(desc->cmd.info0));
 }
 
 int
 qwz_hal_reo_cmd_send(struct qwz_softc *sc, struct hal_srng *srng,
     enum hal_reo_cmd_type type, struct ath12k_hal_reo_cmd *cmd)
 {
-       struct hal_tlv_hdr *reo_desc;
+       struct hal_tlv_64_hdr *reo_desc;
        int ret;
 #ifdef notyet
        spin_lock_bh(&srng->lock);
 #endif
        qwz_hal_srng_access_begin(sc, srng);
-       reo_desc = (struct hal_tlv_hdr *)qwz_hal_srng_src_get_next_entry(sc, 
srng);
+       reo_desc = (struct hal_tlv_64_hdr *)
+           qwz_hal_srng_src_get_next_entry(sc, srng);
        if (!reo_desc) {
                ret = ENOBUFS;
                goto out;
@@ -16324,14 +16340,16 @@ void
 qwz_hal_reo_status_queue_stats(struct qwz_softc *sc, uint32_t *reo_desc,
     struct hal_reo_status *status)
 {
-       struct hal_tlv_hdr *tlv = (struct hal_tlv_hdr *)reo_desc;
+       struct hal_tlv_64_hdr *tlv = (struct hal_tlv_64_hdr *)reo_desc;
        struct hal_reo_get_queue_stats_status *desc =
            (struct hal_reo_get_queue_stats_status *)tlv->value;
 
        status->uniform_hdr.cmd_num =
-           FIELD_GET(HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, desc->hdr.info0);
+           FIELD_GET(HAL_REO_STATUS_HDR_INFO0_STATUS_NUM,
+           le32toh(desc->hdr.info0));
        status->uniform_hdr.cmd_status =
-           FIELD_GET(HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, desc->hdr.info0);
+           FIELD_GET(HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS,
+           le32toh(desc->hdr.info0));
 #if 0
        ath12k_dbg(ab, ATH12K_DBG_HAL, "Queue stats status:\n");
        ath12k_dbg(ab, ATH12K_DBG_HAL, "header: cmd_num %d status %d\n",
@@ -16390,16 +16408,16 @@ void
 qwz_hal_reo_flush_queue_status(struct qwz_softc *sc, uint32_t *reo_desc,
     struct hal_reo_status *status)
 {
-       struct hal_tlv_hdr *tlv = (struct hal_tlv_hdr *)reo_desc;
+       struct hal_tlv_64_hdr *tlv = (struct hal_tlv_64_hdr *)reo_desc;
        struct hal_reo_flush_queue_status *desc =
            (struct hal_reo_flush_queue_status *)tlv->value;
 
        status->uniform_hdr.cmd_num = FIELD_GET(
-          HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, desc->hdr.info0);
+          HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, le32toh(desc->hdr.info0));
        status->uniform_hdr.cmd_status = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, desc->hdr.info0);
+           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, le32toh(desc->hdr.info0));
        status->u.flush_queue.err_detected = FIELD_GET(
-           HAL_REO_FLUSH_QUEUE_INFO0_ERR_DETECTED, desc->info0);
+           HAL_REO_FLUSH_QUEUE_INFO0_ERR_DETECTED, le32toh(desc->info0));
 }
 
 void
@@ -16407,37 +16425,39 @@ qwz_hal_reo_flush_cache_status(struct qwz_softc *sc, 
uint32_t *reo_desc,
     struct hal_reo_status *status)
 {
        struct ath12k_hal *hal = &sc->hal;
-       struct hal_tlv_hdr *tlv = (struct hal_tlv_hdr *)reo_desc;
+       struct hal_tlv_64_hdr *tlv = (struct hal_tlv_64_hdr *)reo_desc;
        struct hal_reo_flush_cache_status *desc =
            (struct hal_reo_flush_cache_status *)tlv->value;
 
        status->uniform_hdr.cmd_num = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, desc->hdr.info0);
+           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, le32toh(desc->hdr.info0));
        status->uniform_hdr.cmd_status = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, desc->hdr.info0);
+           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, le32toh(desc->hdr.info0));
 
        status->u.flush_cache.err_detected = FIELD_GET(
-           HAL_REO_FLUSH_CACHE_STATUS_INFO0_IS_ERR, desc->info0);
+           HAL_REO_FLUSH_CACHE_STATUS_INFO0_IS_ERR, le32toh(desc->info0));
        status->u.flush_cache.err_code = FIELD_GET(
-           HAL_REO_FLUSH_CACHE_STATUS_INFO0_BLOCK_ERR_CODE, desc->info0);
+           HAL_REO_FLUSH_CACHE_STATUS_INFO0_BLOCK_ERR_CODE,
+           le32toh(desc->info0));
        if (!status->u.flush_cache.err_code)
                hal->avail_blk_resource |= BIT(hal->current_blk_index);
 
        status->u.flush_cache.cache_controller_flush_status_hit = FIELD_GET(
-           HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_STATUS_HIT, desc->info0);
+           HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_STATUS_HIT,
+           le32toh(desc->info0));
 
        status->u.flush_cache.cache_controller_flush_status_desc_type =
            FIELD_GET(HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_DESC_TYPE,
-           desc->info0);
+           le32toh(desc->info0));
        status->u.flush_cache.cache_controller_flush_status_client_id =
            FIELD_GET(HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_CLIENT_ID,
-           desc->info0);
+           le32toh(desc->info0));
        status->u.flush_cache.cache_controller_flush_status_err =
            FIELD_GET(HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_ERR,
-           desc->info0);
+           le32toh(desc->info0));
        status->u.flush_cache.cache_controller_flush_status_cnt =
            FIELD_GET(HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_COUNT,
-           desc->info0);
+           le32toh(desc->info0));
 }
 
 void
@@ -16445,19 +16465,19 @@ qwz_hal_reo_unblk_cache_status(struct qwz_softc *sc, 
uint32_t *reo_desc,
     struct hal_reo_status *status)
 {
        struct ath12k_hal *hal = &sc->hal;
-       struct hal_tlv_hdr *tlv = (struct hal_tlv_hdr *)reo_desc;
+       struct hal_tlv_64_hdr *tlv = (struct hal_tlv_64_hdr *)reo_desc;
        struct hal_reo_unblock_cache_status *desc =
           (struct hal_reo_unblock_cache_status *)tlv->value;
 
        status->uniform_hdr.cmd_num = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, desc->hdr.info0);
+           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, le32toh(desc->hdr.info0));
        status->uniform_hdr.cmd_status = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, desc->hdr.info0);
+           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, le32toh(desc->hdr.info0));
 
        status->u.unblock_cache.err_detected = FIELD_GET(
-           HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_IS_ERR, desc->info0);
+           HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_IS_ERR, le32toh(desc->info0));
        status->u.unblock_cache.unblock_type = FIELD_GET(
-           HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_TYPE, desc->info0);
+           HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_TYPE, le32toh(desc->info0));
 
        if (!status->u.unblock_cache.err_detected &&
            status->u.unblock_cache.unblock_type ==
@@ -16469,68 +16489,75 @@ void
 qwz_hal_reo_flush_timeout_list_status(struct qwz_softc *ab, uint32_t *reo_desc,
     struct hal_reo_status *status)
 {
-       struct hal_tlv_hdr *tlv = (struct hal_tlv_hdr *)reo_desc;
+       struct hal_tlv_64_hdr *tlv = (struct hal_tlv_64_hdr *)reo_desc;
        struct hal_reo_flush_timeout_list_status *desc =
            (struct hal_reo_flush_timeout_list_status *)tlv->value;
 
        status->uniform_hdr.cmd_num = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, desc->hdr.info0);
+           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, le32toh(desc->hdr.info0));
        status->uniform_hdr.cmd_status = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, desc->hdr.info0);
+           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, le32toh(desc->hdr.info0));
 
        status->u.timeout_list.err_detected = FIELD_GET(
-           HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_IS_ERR, desc->info0);
+           HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_IS_ERR, le32toh(desc->info0));
        status->u.timeout_list.list_empty = FIELD_GET(
-           HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_LIST_EMPTY, desc->info0);
+           HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_LIST_EMPTY,
+           le32toh(desc->info0));
 
        status->u.timeout_list.release_desc_cnt = FIELD_GET(
-           HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_REL_DESC_COUNT, desc->info1);
+           HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_REL_DESC_COUNT,
+           le32toh(desc->info1));
        status->u.timeout_list.fwd_buf_cnt = FIELD_GET(
-           HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_FWD_BUF_COUNT, desc->info1);
+           HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_FWD_BUF_COUNT,
+           le32toh(desc->info1));
 }
 
 void
 qwz_hal_reo_desc_thresh_reached_status(struct qwz_softc *sc, uint32_t 
*reo_desc,
     struct hal_reo_status *status)
 {
-       struct hal_tlv_hdr *tlv = (struct hal_tlv_hdr *)reo_desc;
+       struct hal_tlv_64_hdr *tlv = (struct hal_tlv_64_hdr *)reo_desc;
        struct hal_reo_desc_thresh_reached_status *desc =
            (struct hal_reo_desc_thresh_reached_status *)tlv->value;
 
        status->uniform_hdr.cmd_num = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, desc->hdr.info0);
+           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, le32toh(desc->hdr.info0));
        status->uniform_hdr.cmd_status = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, desc->hdr.info0);
+           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, le32toh(desc->hdr.info0));
 
        status->u.desc_thresh_reached.threshold_idx = FIELD_GET(
-           HAL_REO_DESC_THRESH_STATUS_INFO0_THRESH_INDEX, desc->info0);
+           HAL_REO_DESC_THRESH_STATUS_INFO0_THRESH_INDEX,
+           le32toh(desc->info0));
 
        status->u.desc_thresh_reached.link_desc_counter0 = FIELD_GET(
-           HAL_REO_DESC_THRESH_STATUS_INFO1_LINK_DESC_COUNTER0, desc->info1);
+           HAL_REO_DESC_THRESH_STATUS_INFO1_LINK_DESC_COUNTER0,
+           le32toh(desc->info1));
 
        status->u.desc_thresh_reached.link_desc_counter1 = FIELD_GET(
-           HAL_REO_DESC_THRESH_STATUS_INFO2_LINK_DESC_COUNTER1, desc->info2);
+           HAL_REO_DESC_THRESH_STATUS_INFO2_LINK_DESC_COUNTER1,
+           le32toh(desc->info2));
 
        status->u.desc_thresh_reached.link_desc_counter2 = FIELD_GET(
-           HAL_REO_DESC_THRESH_STATUS_INFO3_LINK_DESC_COUNTER2, desc->info3);
+           HAL_REO_DESC_THRESH_STATUS_INFO3_LINK_DESC_COUNTER2,
+           le32toh(desc->info3));
 
        status->u.desc_thresh_reached.link_desc_counter_sum = FIELD_GET(
            HAL_REO_DESC_THRESH_STATUS_INFO4_LINK_DESC_COUNTER_SUM,
-           desc->info4);
+           le32toh(desc->info4));
 }
 
 void
 qwz_hal_reo_update_rx_reo_queue_status(struct qwz_softc *ab, uint32_t 
*reo_desc,
     struct hal_reo_status *status)
 {
-       struct hal_tlv_hdr *tlv = (struct hal_tlv_hdr *)reo_desc;
+       struct hal_tlv_64_hdr *tlv = (struct hal_tlv_64_hdr *)reo_desc;
        struct hal_reo_status_hdr *desc =
            (struct hal_reo_status_hdr *)tlv->value;
 
        status->uniform_hdr.cmd_num = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, desc->info0);
+           HAL_REO_STATUS_HDR_INFO0_STATUS_NUM, le32toh(desc->info0));
        status->uniform_hdr.cmd_status = FIELD_GET(
-           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, desc->info0);
+           HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS, le32toh(desc->info0));
 }
 
 int
@@ -16541,6 +16568,7 @@ qwz_dp_process_reo_status(struct qwz_softc *sc)
        struct dp_reo_cmd *cmd, *tmp;
        int found = 0, ret = 0;
        uint32_t *reo_desc;
+       struct hal_tlv_64_hdr *tlv;
        uint16_t tag;
        struct hal_reo_status reo_status;
 
@@ -16554,7 +16582,8 @@ qwz_dp_process_reo_status(struct qwz_softc *sc)
        while ((reo_desc = qwz_hal_srng_dst_get_next_entry(sc, srng))) {
                ret = 1;
 
-               tag = FIELD_GET(HAL_SRNG_TLV_HDR_TAG, *reo_desc);
+               tlv = (struct hal_tlv_64_hdr *)reo_desc;
+               tag = FIELD_GET(HAL_SRNG_TLV_HDR_TAG, le64toh(tlv->tl));
                switch (tag) {
                case HAL_REO_GET_QUEUE_STATS_STATUS:
                        qwz_hal_reo_status_queue_stats(sc, reo_desc,
diff --git a/sys/dev/ic/qwzreg.h b/sys/dev/ic/qwzreg.h
index 602fc4de356..a71db13cbb4 100644
--- a/sys/dev/ic/qwzreg.h
+++ b/sys/dev/ic/qwzreg.h
@@ -7888,7 +7888,7 @@ enum hal_tlv_tag {
        HAL_MPDU_INFO                          = 150 /* 0x96 */,
        HAL_PDG_USER_SETUP                     = 151 /* 0x97 */,
        HAL_TX_11AH_SETUP                      = 152 /* 0x98 */,
-       HAL_REO_UPDATE_RX_REO_QUEUE_STATUS     = 153 /* 0x99 */,
+       HAL_REO_UPDATE_RX_REO_QUEUE_STATUS     = 172 /* 0xac */,
        HAL_TX_PEER_ENTRY                      = 154 /* 0x9a */,
        HAL_TX_RAW_OR_NATIVE_FRAME_SETUP       = 155 /* 0x9b */,
        HAL_EXAMPLE_STRUCT_NAME                = 156 /* 0x9c */,
@@ -8041,15 +8041,15 @@ enum hal_tlv_tag {
        HAL_NO_ACK_REPORT                      = 303 /* 0x12f */,
        HAL_ACK_REPORT                         = 304 /* 0x130 */,
        HAL_UNIFORM_REO_CMD_HEADER             = 305 /* 0x131 */,
-       HAL_REO_GET_QUEUE_STATS                = 306 /* 0x132 */,
-       HAL_REO_FLUSH_QUEUE                    = 307 /* 0x133 */,
-       HAL_REO_FLUSH_CACHE                    = 308 /* 0x134 */,
-       HAL_REO_UNBLOCK_CACHE                  = 309 /* 0x135 */,
+       HAL_REO_GET_QUEUE_STATS                = 281 /* 0x119 */,
+       HAL_REO_FLUSH_QUEUE                    = 282 /* 0x11a */,
+       HAL_REO_FLUSH_CACHE                    = 283 /* 0x11b */,
+       HAL_REO_UNBLOCK_CACHE                  = 284 /* 0x11c */,
        HAL_UNIFORM_REO_STATUS_HEADER          = 310 /* 0x136 */,
-       HAL_REO_GET_QUEUE_STATS_STATUS         = 311 /* 0x137 */,
-       HAL_REO_FLUSH_QUEUE_STATUS             = 312 /* 0x138 */,
-       HAL_REO_FLUSH_CACHE_STATUS             = 313 /* 0x139 */,
-       HAL_REO_UNBLOCK_CACHE_STATUS           = 314 /* 0x13a */,
+       HAL_REO_GET_QUEUE_STATS_STATUS         = 285 /* 0x11d */,
+       HAL_REO_FLUSH_QUEUE_STATUS             = 286 /* 0x11e */,
+       HAL_REO_FLUSH_CACHE_STATUS             = 287 /* 0x11f */,
+       HAL_REO_UNBLOCK_CACHE_STATUS           = 288 /* 0x120 */,
        HAL_TQM_FLUSH_CACHE                    = 315 /* 0x13b */,
        HAL_TQM_UNBLOCK_CACHE                  = 316 /* 0x13c */,
        HAL_TQM_FLUSH_CACHE_STATUS             = 317 /* 0x13d */,
@@ -8076,11 +8076,11 @@ enum hal_tlv_tag {
        HAL_TQM_SYNC_CMD_STATUS                = 338 /* 0x152 */,
        HAL_TQM_THRESHOLD_DROP_NOTIFICATION_STATUS = 339 /* 0x153 */,
        HAL_TQM_DESCRIPTOR_THRESHOLD_REACHED_STATUS = 340 /* 0x154 */,
-       HAL_REO_FLUSH_TIMEOUT_LIST             = 341 /* 0x155 */,
-       HAL_REO_FLUSH_TIMEOUT_LIST_STATUS      = 342 /* 0x156 */,
+       HAL_REO_FLUSH_TIMEOUT_LIST             = 305 /* 0x131 */,
+       HAL_REO_FLUSH_TIMEOUT_LIST_STATUS      = 306 /* 0x132 */,
        HAL_REO_TO_PPE_RING                    = 343 /* 0x157 */,
        HAL_RX_MPDU_INFO                       = 344 /* 0x158 */,
-       HAL_REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS = 345 /* 0x159 */,
+       HAL_REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS = 307 /* 0x133 */,
        HAL_SCHEDULER_RX_SIFS_RESPONSE_TRIGGER_STATUS = 346 /* 0x15a */,
        HAL_EXAMPLE_USER_TLV_32_NAME           = 347 /* 0x15b */,
        HAL_RX_PPDU_START_USER_INFO            = 348 /* 0x15c */,
@@ -8154,7 +8154,7 @@ enum hal_tlv_tag {
        HAL_TQM_UPDATE_TX_MPDU_QUEUE_HEAD      = 416 /* 0x1a0 */,
        HAL_TQM_UPDATE_TX_MSDU_FLOW_STATUS     = 417 /* 0x1a1 */,
        HAL_TQM_UPDATE_TX_MPDU_QUEUE_HEAD_STATUS = 418 /* 0x1a2 */,
-       HAL_REO_UPDATE_RX_REO_QUEUE            = 419 /* 0x1a3 */,
+       HAL_REO_UPDATE_RX_REO_QUEUE            = 339 /* 0x153 */,
        HAL_CE_DST_DESC                        = 420 /* 0x1a4 */,
        HAL_TLV_BASE                           = 511 /* 0x1ff */,
 };
@@ -10163,7 +10163,7 @@ struct hal_reo_status_hdr {
  *             enum %HAL_REO_EXEC_STATUS_.
  */
 #define HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_SSN               GENMASK(11, 0)
-#define HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_CUR_IDX           GENMASK(19, 12)
+#define HAL_REO_GET_QUEUE_STATS_STATUS_INFO0_CUR_IDX           GENMASK(21, 12)
 
 #define HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MPDU_COUNT                
GENMASK(6, 0)
 #define HAL_REO_GET_QUEUE_STATS_STATUS_INFO1_MSDU_COUNT                
GENMASK(31, 7)
@@ -10177,7 +10177,7 @@ struct hal_reo_status_hdr {
 
 #define HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_LATE_RX_MPDU      GENMASK(11, 0)
 #define HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_WINDOW_JMP2K      GENMASK(15, 12)
-#define HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_HOLE_COUNT                
GENMASK(31, 16)
+#define HAL_REO_GET_QUEUE_STATS_STATUS_INFO4_HOLE_COUNT                
GENMASK(27, 12)
 
 #define HAL_REO_GET_QUEUE_STATS_STATUS_INFO5_LOOPING_CNT       GENMASK(31, 28)
 
@@ -10187,7 +10187,7 @@ struct hal_reo_get_queue_stats_status {
        uint32_t pn[4];
        uint32_t last_rx_enqueue_timestamp;
        uint32_t last_rx_dequeue_timestamp;
-       uint32_t rx_bitmap[8];
+       uint32_t rx_bitmap[9];
        uint32_t info1;
        uint32_t info2;
        uint32_t info3;
-- 
2.55.0


From c64ddb4c420cc7487c97acda497a0491099d6b1a Mon Sep 17 00:00:00 2001
From: "Kirill A. Korinsky" <[email protected]>
Date: Sun, 27 Sep 2026 12:57:48 +0200
Subject: [PATCH 7/7] sys/qwz: fix REO queue lifetime

Track REO completions before publication and wait for peer unmap,
deletion, and cache flushes before reusing queue DMA. Submission errors
and timeouts retain ownership; hardware failures block reuse until cold
cleanup. HAL error conventions and flush semantics follow ath12k;
tracking and the reuse barrier adapt qwz's retained pool.
---
 sys/dev/ic/qwz.c    | 328 +++++++++++++++++++++++---------------------
 sys/dev/ic/qwzvar.h |  24 ++--
 2 files changed, 181 insertions(+), 171 deletions(-)

diff --git a/sys/dev/ic/qwz.c b/sys/dev/ic/qwz.c
index 6d79eec5376..3e93b6bb40d 100644
--- a/sys/dev/ic/qwz.c
+++ b/sys/dev/ic/qwz.c
@@ -169,6 +169,7 @@ int qwz_dp_rx_h_null_q_desc(struct qwz_softc *, struct 
qwz_rx_msdu *,
     struct qwz_rx_msdu_list *);
 void qwz_dp_service_mon_ring(void *);
 void qwz_peer_frags_flush(struct qwz_softc *, struct ath12k_peer *);
+int qwz_peer_rx_tid_cleanup(struct qwz_softc *, struct ath12k_peer *);
 int qwz_wmi_vdev_install_key(struct qwz_softc *,
     struct wmi_vdev_install_key_arg *, uint8_t);
 int qwz_dp_peer_rx_pn_replay_config(struct qwz_softc *, struct qwz_vif *,
@@ -8062,7 +8063,7 @@ qwz_hal_reo_cmd_flush_cache(struct ath12k_hal *hal, 
struct hal_tlv_64_hdr *tlv,
 
        if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_BLOCK_LATER) {
                if (avail_slot >= HAL_MAX_AVAIL_BLK_RES)
-                       return ENOSPC;
+                       return -ENOSPC;
 
                hal->current_blk_index = avail_slot;
        }
@@ -8235,18 +8236,23 @@ qwz_hal_reo_cmd_update_rx_queue(struct hal_tlv_64_hdr 
*tlv,
 
 int
 qwz_hal_reo_cmd_send(struct qwz_softc *sc, struct hal_srng *srng,
-    enum hal_reo_cmd_type type, struct ath12k_hal_reo_cmd *cmd)
+    enum hal_reo_cmd_type type, struct ath12k_hal_reo_cmd *cmd,
+    struct dp_reo_cmd *dp_cmd)
 {
        struct hal_tlv_64_hdr *reo_desc;
+       struct dp_reo_cmd *pending;
+       uint32_t hp, reap_hp;
        int ret;
 #ifdef notyet
        spin_lock_bh(&srng->lock);
 #endif
        qwz_hal_srng_access_begin(sc, srng);
+       hp = srng->u.src_ring.hp;
+       reap_hp = srng->u.src_ring.reap_hp;
        reo_desc = (struct hal_tlv_64_hdr *)
            qwz_hal_srng_src_get_next_entry(sc, srng);
        if (!reo_desc) {
-               ret = ENOBUFS;
+               ret = -ENOBUFS;
                goto out;
        }
 
@@ -8265,15 +8271,35 @@ qwz_hal_reo_cmd_send(struct qwz_softc *sc, struct 
hal_srng *srng,
        case HAL_REO_CMD_FLUSH_TIMEOUT_LIST:
                printf("%s: unsupported reo command %d\n",
                   sc->sc_dev.dv_xname, type);
-               ret = ENOTSUP;
+               ret = -ENOTSUP;
                break;
        default:
                printf("%s: unknown reo command %d\n",
                    sc->sc_dev.dv_xname, type);
-               ret = EINVAL;
+               ret = -EINVAL;
                break;
        }
 
+       if (ret <= 0) {
+               if (ret == 0)
+                       ret = -EINVAL;
+               goto rollback;
+       }
+       TAILQ_FOREACH(pending, &sc->dp.reo_cmd_list, entry) {
+               if (pending->cmd_num == ret) {
+                       ret = -EBUSY;
+                       goto rollback;
+               }
+       }
+       if (dp_cmd != NULL) {
+               dp_cmd->cmd_num = ret;
+               TAILQ_INSERT_TAIL(&sc->dp.reo_cmd_list, dp_cmd, entry);
+       }
+       goto out;
+
+rollback:
+       srng->u.src_ring.hp = hp;
+       srng->u.src_ring.reap_hp = reap_hp;
 out:
        qwz_hal_srng_access_end(sc, srng);
 #ifdef notyet
@@ -8994,13 +9020,11 @@ qwz_dp_alloc(struct qwz_softc *sc)
        dp->sc = sc;
 
        TAILQ_INIT(&dp->reo_cmd_list);
-       TAILQ_INIT(&dp->reo_cmd_cache_flush_list);
 #if 0
        INIT_LIST_HEAD(&dp->dp_full_mon_mpdu_list);
        spin_lock_init(&dp->reo_cmd_lock);
 #endif
 
-       dp->reo_cmd_cache_flush_count = 0;
        dp->idle_link_rbm = qwz_dp_get_idle_link_rbm(sc);
 
        ret = qwz_wbm_idle_ring_setup(sc, &n_link_desc);
@@ -9108,7 +9132,6 @@ qwz_dp_reo_cmd_list_cleanup(struct qwz_softc *sc)
 {
        struct qwz_dp *dp = &sc->dp;
        struct dp_reo_cmd *cmd, *tmp;
-       struct dp_reo_cache_flush_elem *cmd_cache, *tmp_cache;
        struct dp_rx_tid *rx_tid;
 #ifdef notyet
        spin_lock_bh(&dp->reo_cmd_lock);
@@ -9119,15 +9142,6 @@ qwz_dp_reo_cmd_list_cleanup(struct qwz_softc *sc)
                qwz_dp_rx_tid_clear(sc, rx_tid);
                free(cmd, M_DEVBUF, sizeof(*cmd));
        }
-
-       TAILQ_FOREACH_SAFE(cmd_cache, &dp->reo_cmd_cache_flush_list,
-           entry, tmp_cache) {
-               TAILQ_REMOVE(&dp->reo_cmd_cache_flush_list, cmd_cache, entry);
-               dp->reo_cmd_cache_flush_count--;
-               rx_tid = &cmd_cache->data;
-               qwz_dp_rx_tid_clear(sc, rx_tid);
-               free(cmd_cache, M_DEVBUF, sizeof(*cmd_cache));
-       }
 #ifdef notyet
        spin_unlock_bh(&dp->reo_cmd_lock);
 #endif
@@ -9169,6 +9183,8 @@ qwz_dp_free(struct qwz_softc *sc)
                }
        }
 
+       memset(dp->rx_tid_retire, 0, sizeof(dp->rx_tid_retire));
+
        /* Deinit any SOC level resource */
 }
 
@@ -16573,7 +16589,6 @@ qwz_dp_process_reo_status(struct qwz_softc *sc)
        struct hal_reo_status reo_status;
 
        srng = &sc->hal.srng_list[dp->reo_status_ring.ring_id];
-       memset(&reo_status, 0, sizeof(reo_status));
 #ifdef notyet
        spin_lock_bh(&srng->lock);
 #endif
@@ -16581,6 +16596,7 @@ qwz_dp_process_reo_status(struct qwz_softc *sc)
 
        while ((reo_desc = qwz_hal_srng_dst_get_next_entry(sc, srng))) {
                ret = 1;
+               memset(&reo_status, 0, sizeof(reo_status));
 
                tlv = (struct hal_tlv_64_hdr *)reo_desc;
                tag = FIELD_GET(HAL_SRNG_TLV_HDR_TAG, le64toh(tlv->tl));
@@ -16596,6 +16612,10 @@ qwz_dp_process_reo_status(struct qwz_softc *sc)
                case HAL_REO_FLUSH_CACHE_STATUS:
                        qwz_hal_reo_flush_cache_status(sc, reo_desc,
                            &reo_status);
+                       if (reo_status.u.flush_cache.err_detected ||
+                           reo_status.u.flush_cache.err_code ||
+                           
reo_status.u.flush_cache.cache_controller_flush_status_err)
+                               reo_status.uniform_hdr.cmd_status = 
HAL_REO_CMD_FAILED;
                        break;
                case HAL_REO_UNBLOCK_CACHE_STATUS:
                        qwz_hal_reo_unblk_cache_status(sc, reo_desc,
@@ -16632,8 +16652,9 @@ qwz_dp_process_reo_status(struct qwz_softc *sc)
                spin_unlock_bh(&dp->reo_cmd_lock);
 #endif
                if (found) {
-                       cmd->handler(dp, (void *)&cmd->data,
-                           reo_status.uniform_hdr.cmd_status);
+                       if (cmd->handler != NULL)
+                               cmd->handler(dp, (void *)&cmd->data,
+                                   reo_status.uniform_hdr.cmd_status);
                        free(cmd, M_DEVBUF, sizeof(*cmd));
                }
                found = 0;
@@ -22609,6 +22630,13 @@ qwz_peer_delete(struct qwz_softc *sc, uint32_t 
vdev_id, uint8_t pdev_id,
                }
        }
 
+       ret = qwz_peer_rx_tid_cleanup(sc, peer);
+       if (ret) {
+               printf("%s: failed to retire peer RX queues: %d\n",
+                   sc->sc_dev.dv_xname, ret);
+               return ret;
+       }
+
        TAILQ_REMOVE(&sc->peers, peer, entry);
        qwz_node_clear_peer_id(sc, peer);
        free(peer, M_DEVBUF, sizeof(*peer));
@@ -22673,44 +22701,27 @@ qwz_dp_tx_send_reo_cmd(struct qwz_softc *sc, struct 
dp_rx_tid *rx_tid,
     void (*cb)(struct qwz_dp *, void *, enum hal_reo_cmd_status))
 {
        struct qwz_dp *dp = &sc->dp;
-       struct dp_reo_cmd *dp_cmd;
+       struct dp_reo_cmd *dp_cmd = NULL;
        struct hal_srng *cmd_ring;
        int cmd_num;
 
        if (test_bit(ATH12K_FLAG_CRASH_FLUSH, sc->sc_flags))
                return ESHUTDOWN;
 
-       cmd_ring = &sc->hal.srng_list[dp->reo_cmd_ring.ring_id];
-       cmd_num = qwz_hal_reo_cmd_send(sc, cmd_ring, type, cmd);
-       /* cmd_num should start from 1, during failure return the error code */
-       if (cmd_num < 0)
-               return cmd_num;
-
-       /* reo cmd ring descriptors has cmd_num starting from 1 */
-       if (cmd_num == 0)
-               return EINVAL;
-
-       if (!cb)
-               return 0;
-
-       /* Can this be optimized so that we keep the pending command list only
-        * for tid delete command to free up the resource on the command status
-        * indication?
-        */
-       dp_cmd = malloc(sizeof(*dp_cmd), M_DEVBUF, M_ZERO | M_NOWAIT);
-       if (!dp_cmd)
-               return ENOMEM;
+       if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS) {
+               dp_cmd = malloc(sizeof(*dp_cmd), M_DEVBUF, M_ZERO | M_NOWAIT);
+               if (dp_cmd == NULL)
+                       return ENOMEM;
+               memcpy(&dp_cmd->data, rx_tid, sizeof(*rx_tid));
+               dp_cmd->handler = cb;
+       }
 
-       memcpy(&dp_cmd->data, rx_tid, sizeof(struct dp_rx_tid));
-       dp_cmd->cmd_num = cmd_num;
-       dp_cmd->handler = cb;
-#ifdef notyet
-       spin_lock_bh(&dp->reo_cmd_lock);
-#endif
-       TAILQ_INSERT_TAIL(&dp->reo_cmd_list, dp_cmd, entry);
-#ifdef notyet
-       spin_unlock_bh(&dp->reo_cmd_lock);
-#endif
+       cmd_ring = &sc->hal.srng_list[dp->reo_cmd_ring.ring_id];
+       cmd_num = qwz_hal_reo_cmd_send(sc, cmd_ring, type, cmd, dp_cmd);
+       if (cmd_num < 0) {
+               free(dp_cmd, M_DEVBUF, sizeof(*dp_cmd));
+               return -cmd_num;
+       }
        return 0;
 }
 
@@ -22825,141 +22836,131 @@ qwz_hal_reo_qdesc_setup(void *vaddr, int tid, 
uint32_t ba_window_size,
 }
 
 void
-qwz_dp_reo_cmd_free(struct qwz_dp *dp, void *ctx,
+qwz_dp_rx_tid_retire_done(struct qwz_dp *dp, void *ctx,
     enum hal_reo_cmd_status status)
 {
-       struct qwz_softc *sc = dp->sc;
        struct dp_rx_tid *rx_tid = ctx;
-
-       if (status != HAL_REO_CMD_SUCCESS)
-               printf("%s: failed to flush rx tid hw desc, tid %d status %d\n",
-                   sc->sc_dev.dv_xname, rx_tid->tid, status);
-
-       qwz_dp_rx_tid_clear(sc, rx_tid);
+       struct qwz_rx_tid_retire *retire = &dp->rx_tid_retire[rx_tid->tid];
+
+       KASSERT(retire->data.mem == rx_tid->mem);
+       KASSERT(retire->state == QWZ_RX_TID_DELETE_PENDING ||
+           retire->state == QWZ_RX_TID_FLUSH_PENDING);
+
+       if (status != HAL_REO_CMD_SUCCESS) {
+               retire->state = QWZ_RX_TID_RETIRE_FAILED;
+               printf("%s: RX queue retirement failed, tid %u status %d\n",
+                   dp->sc->sc_dev.dv_xname, rx_tid->tid, status);
+       } else if (retire->state == QWZ_RX_TID_DELETE_PENDING) {
+               retire->flush_offset = retire->data.size;
+               retire->state = QWZ_RX_TID_FLUSH_READY;
+       } else if (retire->flush_offset != 0) {
+               retire->state = QWZ_RX_TID_FLUSH_READY;
+       } else {
+               memset(retire, 0, sizeof(*retire));
+       }
+       wakeup(dp->rx_tid_retire);
 }
 
-void
-qwz_dp_reo_cache_flush(struct qwz_softc *sc, struct dp_rx_tid *rx_tid)
+int
+qwz_dp_rx_tid_retire_submit(struct qwz_softc *sc,
+    struct qwz_rx_tid_retire *retire)
 {
        struct ath12k_hal_reo_cmd cmd = {0};
-       unsigned long tot_desc_sz, desc_sz;
+       enum qwz_rx_tid_retire_state state = retire->state;
+       enum hal_reo_cmd_type type;
+       uint32_t offset = retire->flush_offset;
+       uint64_t paddr = retire->data.paddr;
        int ret;
 
-       tot_desc_sz = rx_tid->size;
-       desc_sz = qwz_hal_reo_qdesc_size(0, HAL_DESC_REO_NON_QOS_TID);
-
-       while (tot_desc_sz > desc_sz) {
-               tot_desc_sz -= desc_sz;
-               cmd.addr_lo = (rx_tid->paddr + tot_desc_sz) & 0xffffffff;
-               cmd.addr_hi = rx_tid->paddr >> 32;
-               ret = qwz_dp_tx_send_reo_cmd(sc, rx_tid,
-                   HAL_REO_CMD_FLUSH_CACHE, &cmd, NULL);
-               if (ret) {
-                       printf("%s: failed to send HAL_REO_CMD_FLUSH_CACHE, "
-                           "tid %d (%d)\n", sc->sc_dev.dv_xname, rx_tid->tid,
-                           ret);
-               }
-       }
-
-       memset(&cmd, 0, sizeof(cmd));
-       cmd.addr_lo = rx_tid->paddr & 0xffffffff;
-       cmd.addr_hi = rx_tid->paddr >> 32;
-       cmd.flag |= HAL_REO_CMD_FLG_NEED_STATUS;
-       ret = qwz_dp_tx_send_reo_cmd(sc, rx_tid, HAL_REO_CMD_FLUSH_CACHE,
-           &cmd, qwz_dp_reo_cmd_free);
+       cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
+       if (state == QWZ_RX_TID_DELETE_READY) {
+               /* WCN7850 requires VLD to remain set until the cache flush. */
+               cmd.upd0 = HAL_REO_CMD_UPD0_VLD;
+               cmd.upd1 = HAL_REO_CMD_UPD1_VLD;
+               type = HAL_REO_CMD_UPDATE_RX_QUEUE;
+               retire->state = QWZ_RX_TID_DELETE_PENDING;
+       } else {
+               KASSERT(state == QWZ_RX_TID_FLUSH_READY);
+               KASSERT(offset >= sizeof(struct hal_rx_reo_queue));
+               retire->flush_offset -= sizeof(struct hal_rx_reo_queue);
+               paddr += retire->flush_offset;
+               if (retire->flush_offset == 0)
+                       cmd.flag |= HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS;
+               type = HAL_REO_CMD_FLUSH_CACHE;
+               retire->state = QWZ_RX_TID_FLUSH_PENDING;
+       }
+       cmd.addr_lo = paddr & 0xffffffff;
+       cmd.addr_hi = paddr >> 32;
+       ret = qwz_dp_tx_send_reo_cmd(sc, &retire->data, type, &cmd,
+           qwz_dp_rx_tid_retire_done);
        if (ret) {
-               printf("%s: failed to send HAL_REO_CMD_FLUSH_CACHE cmd, "
-                   "tid %d (%d)\n", sc->sc_dev.dv_xname, rx_tid->tid, ret);
-               qwz_dp_rx_tid_clear(sc, rx_tid);
+               retire->state = state;
+               retire->flush_offset = offset;
        }
+       return ret;
 }
 
-void
-qwz_dp_rx_tid_del_func(struct qwz_dp *dp, void *ctx,
-    enum hal_reo_cmd_status status)
+int
+qwz_dp_rx_tid_retire_wait(struct qwz_softc *sc)
 {
-       struct qwz_softc *sc = dp->sc;
-       struct dp_rx_tid *rx_tid = ctx;
-       struct dp_reo_cache_flush_elem *elem, *tmp;
+       struct qwz_dp *dp = &sc->dp;
+       struct qwz_rx_tid_retire *retire;
+       uint64_t deadline = getnsecuptime() + SEC_TO_NSEC(3);
        uint64_t now;
+       int i, pending, error, ret;
 
-       if (status == HAL_REO_CMD_DRAIN) {
-               qwz_dp_rx_tid_clear(sc, rx_tid);
-               return;
-       } else if (status != HAL_REO_CMD_SUCCESS) {
-               /* Shouldn't happen! Cleanup in case of other failure? */
-               printf("%s: failed to delete rx tid %d hw descriptor %d\n",
-                   sc->sc_dev.dv_xname, rx_tid->tid, status);
-               return;
-       }
-
-       elem = malloc(sizeof(*elem), M_DEVBUF, M_ZERO | M_NOWAIT);
-       if (!elem) {
-               qwz_dp_rx_tid_clear(sc, rx_tid);
-               return;
-       }
-
-       now = getnsecuptime();
-       elem->ts = now;
-       memcpy(&elem->data, rx_tid, sizeof(*rx_tid));
-
-       qwz_dp_rx_tid_clear(sc, rx_tid);
-
-#ifdef notyet
-       spin_lock_bh(&dp->reo_cmd_lock);
-#endif
-       TAILQ_INSERT_TAIL(&dp->reo_cmd_cache_flush_list, elem, entry);
-       dp->reo_cmd_cache_flush_count++;
-
-       /* Flush and invalidate aged REO desc from HW cache */
-       TAILQ_FOREACH_SAFE(elem, &dp->reo_cmd_cache_flush_list, entry, tmp) {
-               if (dp->reo_cmd_cache_flush_count > DP_REO_DESC_FREE_THRESHOLD 
||
-                   now >= elem->ts + 
MSEC_TO_NSEC(DP_REO_DESC_FREE_TIMEOUT_MS)) {
-                       TAILQ_REMOVE(&dp->reo_cmd_cache_flush_list, elem, 
entry);
-                       dp->reo_cmd_cache_flush_count--;
-#ifdef notyet
-                       spin_unlock_bh(&dp->reo_cmd_lock);
-#endif
-                       qwz_dp_reo_cache_flush(sc, &elem->data);
-                       free(elem, M_DEVBUF, sizeof(*elem));
-#ifdef notyet
-                       spin_lock_bh(&dp->reo_cmd_lock);
-#endif
+       for (;;) {
+               pending = 0;
+               error = 0;
+               for (i = 0; i < nitems(dp->rx_tid_retire); i++) {
+                       retire = &dp->rx_tid_retire[i];
+                       switch (retire->state) {
+                       case QWZ_RX_TID_REUSABLE:
+                               break;
+                       case QWZ_RX_TID_DELETE_READY:
+                       case QWZ_RX_TID_FLUSH_READY:
+                               ret = qwz_dp_rx_tid_retire_submit(sc, retire);
+                               if (ret && !error)
+                                       error = ret;
+                               pending = 1;
+                               break;
+                       case QWZ_RX_TID_DELETE_PENDING:
+                       case QWZ_RX_TID_FLUSH_PENDING:
+                               pending = 1;
+                               break;
+                       case QWZ_RX_TID_RETIRE_FAILED:
+                               error = EIO;
+                               break;
+                       }
                }
+               if (error)
+                       return error;
+               if (!pending)
+                       return 0;
+               now = getnsecuptime();
+               if (now >= deadline)
+                       return ETIMEDOUT;
+               ret = tsleep_nsec(dp->rx_tid_retire, 0, "qwzreo",
+                   deadline - now);
+               if (ret)
+                       return ret;
        }
-#ifdef notyet
-       spin_unlock_bh(&dp->reo_cmd_lock);
-#endif
 }
 
 void
 qwz_peer_rx_tid_delete(struct qwz_softc *sc, struct ath12k_peer *peer,
     uint8_t tid)
 {
-       struct ath12k_hal_reo_cmd cmd = {0};
        struct dp_rx_tid *rx_tid = &peer->rx_tid[tid];
-       int ret;
+       struct qwz_rx_tid_retire *retire = &sc->dp.rx_tid_retire[tid];
 
        if (!rx_tid->active)
                return;
 
+       KASSERT(retire->state == QWZ_RX_TID_REUSABLE);
+       retire->data = *rx_tid;
+       retire->state = QWZ_RX_TID_DELETE_READY;
        rx_tid->active = 0;
-
-       cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
-       cmd.addr_lo = rx_tid->paddr & 0xffffffff;
-       cmd.addr_hi = rx_tid->paddr >> 32;
-       cmd.upd0 |= HAL_REO_CMD_UPD0_VLD;
-       ret = qwz_dp_tx_send_reo_cmd(sc, rx_tid, HAL_REO_CMD_UPDATE_RX_QUEUE,
-           &cmd, qwz_dp_rx_tid_del_func);
-       if (ret) {
-               if (ret != ESHUTDOWN) {
-                       printf("%s: failed to send "
-                           "HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n",
-                           sc->sc_dev.dv_xname, tid, ret);
-               }
-
-               qwz_dp_rx_tid_clear(sc, rx_tid);
-       }
 }
 
 void
@@ -23006,11 +23007,11 @@ qwz_peer_frags_flush(struct qwz_softc *sc, struct 
ath12k_peer *peer)
        }
 }
 
-void
+int
 qwz_peer_rx_tid_cleanup(struct qwz_softc *sc, struct ath12k_peer *peer)
 {
        struct dp_rx_tid *rx_tid;
-       int i;
+       int i, ret;
 #ifdef notyet
        lockdep_assert_held(&ar->ab->base_lock);
 #endif
@@ -23025,6 +23026,12 @@ qwz_peer_rx_tid_cleanup(struct qwz_softc *sc, struct 
ath12k_peer *peer)
                spin_lock_bh(&ar->ab->base_lock);
 #endif
        }
+       ret = qwz_dp_rx_tid_retire_wait(sc);
+       if (ret)
+               return ret;
+       for (i = 0; i <= HAL_DESC_REO_NON_QOS_TID; i++)
+               qwz_dp_rx_tid_clear(sc, &peer->rx_tid[i]);
+       return 0;
 }
 
 int
@@ -23105,6 +23112,9 @@ qwz_peer_rx_tid_setup(struct qwz_softc *sc, struct 
ieee80211_node *ni,
        peer = qwz_peer_find_by_id(sc, nq->peer_id);
        if (peer == NULL)
                return ENOENT;
+       if (peer->delete_pending || peer->unmapped ||
+           dp->rx_tid_retire[tid].state != QWZ_RX_TID_REUSABLE)
+               return EBUSY;
 
 #ifdef notyet
        spin_lock_bh(&ab->base_lock);
@@ -23712,8 +23722,6 @@ qwz_mac_station_remove(struct qwz_softc *sc, struct 
qwz_vif *arvif,
 {
        int ret;
 
-       qwz_peer_rx_tid_cleanup(sc, peer);
-
        ret = qwz_peer_delete(sc, arvif->vdev_id, pdev_id, peer);
        if (ret) {
                printf("%s: unable to delete BSS peer: %d\n",
diff --git a/sys/dev/ic/qwzvar.h b/sys/dev/ic/qwzvar.h
index 924adab0ce2..05984dd8697 100644
--- a/sys/dev/ic/qwzvar.h
+++ b/sys/dev/ic/qwzvar.h
@@ -1146,18 +1146,23 @@ struct dp_rx_tid {
 #endif
 };
 
-#define DP_REO_DESC_FREE_THRESHOLD  64
-#define DP_REO_DESC_FREE_TIMEOUT_MS 1000
 #define DP_MON_PURGE_TIMEOUT_MS     100
 #define DP_MON_SERVICE_BUDGET       128
 
-struct dp_reo_cache_flush_elem {
-       TAILQ_ENTRY(dp_reo_cache_flush_elem) entry;
-       struct dp_rx_tid data;
-       uint64_t ts;
+enum qwz_rx_tid_retire_state {
+       QWZ_RX_TID_REUSABLE,
+       QWZ_RX_TID_DELETE_READY,
+       QWZ_RX_TID_DELETE_PENDING,
+       QWZ_RX_TID_FLUSH_READY,
+       QWZ_RX_TID_FLUSH_PENDING,
+       QWZ_RX_TID_RETIRE_FAILED,
 };
 
-TAILQ_HEAD(dp_reo_cmd_cache_flush_head, dp_reo_cache_flush_elem);
+struct qwz_rx_tid_retire {
+       struct dp_rx_tid data;
+       enum qwz_rx_tid_retire_state state;
+       uint32_t flush_offset;
+};
 
 struct dp_reo_cmd {
        TAILQ_ENTRY(dp_reo_cmd) entry;
@@ -1257,18 +1262,14 @@ struct qwz_dp {
        struct dp_tx_ring tx_ring[DP_TCL_NUM_RING_MAX];
        struct hal_wbm_idle_scatter_list scatter_list[DP_IDLE_SCATTER_BUFS_MAX];
        struct dp_reo_cmd_head reo_cmd_list;
-       struct dp_reo_cmd_cache_flush_head reo_cmd_cache_flush_list;
 #if 0
        struct list_head dp_full_mon_mpdu_list;
 #endif
-       uint32_t reo_cmd_cache_flush_count;
        enum hal_rx_buf_return_buf_manager idle_link_rbm;
 #if 0
        /**
         * protects access to below fields,
         * - reo_cmd_list
-        * - reo_cmd_cache_flush_list
-        * - reo_cmd_cache_flush_count
         */
        spinlock_t reo_cmd_lock;
 #endif
@@ -1302,6 +1303,7 @@ struct qwz_dp {
         * support for HostAP mode gets added to the driver.
         */
        struct qwz_dmamem *rx_tid_mem[HAL_DESC_REO_NON_QOS_TID + 1];
+       struct qwz_rx_tid_retire rx_tid_retire[HAL_DESC_REO_NON_QOS_TID + 1];
 };
 
 #define ATH12K_SHADOW_DP_TIMER_INTERVAL 20
-- 
2.55.0



-- 
wbr, Kirill

Reply via email to