[PATCH ath-next v3 09/13] wifi: ath12k: ng: add REO queue descriptor helpers

From: Pradeep Kumar Chitrapu

Date: Tue Nov 03 2026 - 20:16:41 EST


Wi-Fi 8 RX TID setup needs host-created REO queue descriptors so the
common datapath can program per-TID reorder state without relying on the
Wi-Fi 7 descriptor layout.

Add helpers to size, initialize, and release Wi-Fi 8 REO queue
descriptors. Keep non-QoS queues simple and allocate extension
descriptors only for QoS TIDs that can use a larger reorder window.

Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@xxxxxxxxxxxxxxxx>
---
drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h | 98 +++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c | 106 +++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h | 15 ++++
3 files changed, 219 insertions(+)

diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h b/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h
index e2947dd112ce..a7db304a197c 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h
@@ -1108,10 +1108,22 @@ struct hal_uniform_tqm_cmd_hdr {
#define HAL_TQM_MSDU_RBM_OVERRIDE GENMASK(23, 20)
#define HAL_TQM_MSDU_RESERVED_4 GENMASK(31, 24)

+#define HAL_DESC_REO_OWNED 4
+#define HAL_DESC_REO_QUEUE_DESC 8
+#define HAL_DESC_REO_QUEUE_EXT_DESC 10
+
+#define HAL_DESC_HDR_INFO0_OWNER GENMASK(3, 0)
+#define HAL_DESC_HDR_INFO0_BUF_TYPE GENMASK(7, 4)
+#define HAL_DESC_HDR_INFO0_DBG_RESERVED GENMASK(31, 8)
+
struct hal_desc_header {
__le32 info0;
} __packed;

+struct hal_rx_mpdu_link_ptr {
+ struct ath12k_buffer_addr addr_info;
+} __packed;
+
/* Per-MSDU entry within a Wi-Fi 8 link descriptor. */
struct hal_rx_msdu_details {
struct ath12k_buffer_addr buf_addr_info;
@@ -1596,6 +1608,92 @@ struct hal_tqm2sw_completion_ring {
__le32 info4;
} __packed;

+struct hal_rx_reo_queue_ext {
+ struct hal_desc_header desc_hdr;
+ __le32 rsvd;
+ struct hal_rx_mpdu_link_ptr mpdu_link[31];
+} __packed;
+
+#define HAL_RX_REO_QUEUE_INFO0_VLD BIT(0)
+#define HAL_RX_REO_QUEUE_INFO0_ASSOCIATED_LINK_DESCRIPTOR_COUNTER GENMASK(2, 1)
+#define HAL_RX_REO_QUEUE_INFO0_LINK_LIST_TIMER_IDX GENMASK(8, 5)
+#define HAL_RX_REO_QUEUE_INFO0_RTY BIT(10)
+#define HAL_RX_REO_QUEUE_INFO0_BA_WINDOW_SIZE GENMASK(22, 13)
+#define HAL_RX_REO_QUEUE_INFO0_PN_CHECK_NEEDED BIT(23)
+#define HAL_RX_REO_QUEUE_INFO0_PN_SIZE GENMASK(28, 27)
+#define HAL_RX_REO_QUEUE_INFO0_IGNORE_AMPDU_FLAG BIT(29)
+
+#define HAL_RX_REO_QUEUE_INFO1_SVLD BIT(0)
+#define HAL_RX_REO_QUEUE_INFO1_SSN GENMASK(12, 1)
+
+#define HAL_RX_REO_QUEUE_INFO2_STATS_ID GENMASK(10, 0)
+
+struct hal_rx_reo_queue {
+ struct hal_desc_header desc_hdr;
+ __le16 receive_queue_number;
+ __le16 rsvd0;
+ __le32 info0;
+ __le16 info1;
+ __le16 rsvd1;
+ __le32 pn_31_0;
+ __le16 pn_47_32;
+ __le16 rsvd2;
+ __le32 rsvd3[2];
+ __le32 last_rx_enqueue_timestamp;
+ __le32 last_rx_dequeue_timestamp;
+ __le32 ptr_to_next_aging_queue_31_0;
+ __le32 rsvd4;
+ __le32 ptr_to_previous_aging_queue_31_0;
+ __le16 rsvd5;
+ __le16 info2;
+ __le32 rx_bitmap_31_0;
+ __le32 rx_bitmap_63_32;
+ __le32 rx_bitmap_95_64;
+ __le32 rx_bitmap_127_96;
+ __le32 rx_bitmap_159_128;
+ __le32 rx_bitmap_191_160;
+ __le32 rx_bitmap_223_192;
+ __le32 rx_bitmap_255_224;
+ __le32 rx_bitmap_287_256;
+ __le32 rsvd6;
+ __le16 rsvd7;
+ __le16 duplicate_count;
+ __le32 rsvd8;
+ __le32 mpdu_frames_processed_count;
+ __le32 msdu_frames_processed_count;
+ __le32 total_processed_byte_count;
+ __le16 rsvd9;
+ __le16 hole_count;
+ __le16 aging_drop_mpdu_count;
+ __le16 rsvd10;
+ __le32 sawf_dropped_msdu_frames_processed_cnt;
+ __le32 rx_bitmap_319_288;
+ __le32 rx_bitmap_351_320;
+ __le32 rx_bitmap_383_352;
+ __le32 rx_bitmap_415_384;
+ __le32 rx_bitmap_447_416;
+ __le32 rx_bitmap_479_448;
+ __le32 rx_bitmap_511_480;
+ __le32 rx_bitmap_543_512;
+ __le32 rx_bitmap_575_544;
+ __le32 rx_bitmap_607_576;
+ __le32 rx_bitmap_639_608;
+ __le32 rx_bitmap_671_640;
+ __le32 rx_bitmap_703_672;
+ __le32 rx_bitmap_735_704;
+ __le32 rx_bitmap_767_736;
+ __le32 rx_bitmap_799_768;
+ __le32 rx_bitmap_831_800;
+ __le32 rx_bitmap_863_832;
+ __le32 rx_bitmap_895_864;
+ __le32 rx_bitmap_927_896;
+ __le32 rx_bitmap_959_928;
+ __le32 rx_bitmap_991_960;
+ __le32 rx_bitmap_1023_992;
+ __le32 rsvd11[9];
+ struct hal_rx_reo_queue_ext ext_desc[];
+};
+
#define HAL_TX_MSDU_EXT_INFO0_BUF_PTR_LO GENMASK(31, 0)

#define HAL_TX_MSDU_EXT_INFO1_BUF_PTR_HI GENMASK(7, 0)
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
index 12a37c395bb0..ad00c182c2bd 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
@@ -9,6 +9,26 @@
#include "hal_rx.h"
#include "hal.h"

+static void ath12k_wifi8_hal_reo_set_desc_hdr(struct hal_desc_header *hdr,
+ u8 owner, u8 buffer_type,
+ u32 magic)
+{
+ hdr->info0 = le32_encode_bits(owner, HAL_DESC_HDR_INFO0_OWNER) |
+ le32_encode_bits(buffer_type, HAL_DESC_HDR_INFO0_BUF_TYPE) |
+ le32_encode_bits(magic, HAL_DESC_HDR_INFO0_DBG_RESERVED);
+}
+
+static u32 ath12k_wifi8_hal_reo_num_ext_desc(u32 ba_window_size)
+{
+ if (ba_window_size <= 217)
+ return 1;
+
+ if (ba_window_size <= 434)
+ return 2;
+
+ return REO_QUEUE_EXT_DESC_MAX;
+}
+
static void ath12k_wifi8_reo_dest_ring_ctrl_setup(struct ath12k_base *ab,
u32 start, u32 end, u32 reg_add)
{
@@ -886,3 +906,89 @@ void ath12k_wifi8_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,

ath12k_wifi8_hal_reo_status_hdr_parse(desc, status);
}
+
+u32 ath12k_wifi8_hal_reo_qdesc_size(u32 ba_window_size, u8 tid)
+{
+ u32 num_ext_desc = ath12k_wifi8_hal_reo_num_ext_desc(ba_window_size);
+
+ if (tid != HAL_DESC_REO_NON_QOS_TID)
+ num_ext_desc = REO_QUEUE_EXT_DESC_MAX;
+
+ return sizeof(struct hal_rx_reo_queue) +
+ num_ext_desc * sizeof(struct hal_rx_reo_queue_ext);
+}
+
+void ath12k_wifi8_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
+ int tid, u32 ba_window_size,
+ u32 start_seq, enum hal_pn_type type)
+{
+ static const u32 reo_queue_desc_magic[REO_QUEUE_EXT_DESC_MAX] = {
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1,
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2,
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3,
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_4,
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_5,
+ };
+ struct hal_rx_reo_queue_ext *ext_desc;
+ u32 num_ext_desc;
+ int i;
+
+ ath12k_wifi8_hal_reo_set_desc_hdr(&qdesc->desc_hdr,
+ HAL_DESC_REO_OWNED,
+ HAL_DESC_REO_QUEUE_DESC,
+ REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_0);
+
+ qdesc->receive_queue_number = cpu_to_le16(tid);
+
+ qdesc->info0 =
+ le32_encode_bits(1, HAL_RX_REO_QUEUE_INFO0_VLD) |
+ le32_encode_bits(1, HAL_RX_REO_QUEUE_INFO0_ASSOCIATED_LINK_DESCRIPTOR_COUNTER) |
+ le32_encode_bits(ath12k_tid_to_ac(tid), HAL_RX_REO_QUEUE_INFO0_LINK_LIST_TIMER_IDX);
+
+ if (ba_window_size < 1)
+ ba_window_size = 1;
+
+ if (ba_window_size == 1 && tid != HAL_DESC_REO_NON_QOS_TID)
+ ba_window_size++;
+
+ if (ba_window_size == 1)
+ qdesc->info0 |= le32_encode_bits(1, HAL_RX_REO_QUEUE_INFO0_RTY);
+
+ qdesc->info0 |= le32_encode_bits(ba_window_size - 1,
+ HAL_RX_REO_QUEUE_INFO0_BA_WINDOW_SIZE);
+
+ switch (type) {
+ case HAL_PN_TYPE_NONE:
+ case HAL_PN_TYPE_WAPI_EVEN:
+ case HAL_PN_TYPE_WAPI_UNEVEN:
+ break;
+ case HAL_PN_TYPE_WPA:
+ qdesc->info0 |=
+ le32_encode_bits(1, HAL_RX_REO_QUEUE_INFO0_PN_CHECK_NEEDED) |
+ le32_encode_bits(HAL_RX_REO_QUEUE_PN_SIZE_48,
+ HAL_RX_REO_QUEUE_INFO0_PN_SIZE);
+ break;
+ }
+
+ qdesc->info0 |= le32_encode_bits(1,
+ HAL_RX_REO_QUEUE_INFO0_IGNORE_AMPDU_FLAG);
+
+ qdesc->info1 = le16_encode_bits(0, HAL_RX_REO_QUEUE_INFO1_SVLD);
+
+ if (start_seq <= 0xfff)
+ qdesc->info1 = le16_encode_bits(start_seq,
+ HAL_RX_REO_QUEUE_INFO1_SSN);
+
+ if (tid == HAL_DESC_REO_NON_QOS_TID)
+ return;
+
+ ext_desc = qdesc->ext_desc;
+ num_ext_desc = REO_QUEUE_EXT_DESC_MAX;
+
+ memset(ext_desc, 0, num_ext_desc * sizeof(*ext_desc));
+ for (i = 0; i < num_ext_desc; i++)
+ ath12k_wifi8_hal_reo_set_desc_hdr(&ext_desc[i].desc_hdr,
+ HAL_DESC_REO_OWNED,
+ HAL_DESC_REO_QUEUE_EXT_DESC,
+ reo_queue_desc_magic[i]);
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
index 430b0f07563f..94732f82f614 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
@@ -7,6 +7,9 @@
#ifndef ATH12K_HAL_RX_H
#define ATH12K_HAL_RX_H

+#include "hal_desc.h"
+#include "hal.h"
+
#define HAL_REO_CMD_FLG_NEED_STATUS BIT(0)
#define HAL_REO_CMD_FLG_STATS_CLEAR BIT(1)
#define HAL_REO_CMD_FLG_FLUSH_BLOCK_LATER BIT(2)
@@ -84,6 +87,14 @@
/* 8 buffers for max-size SG MPDU + 1 entry to confirm termination */
#define HAL_REO_SG_TERMINATION_MIN_ENTRIES 9

+#define REO_QUEUE_EXT_DESC_MAX 5
+#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_0 0xDDBEEF
+#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_1 0xADBEEF
+#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_2 0xBDBEEF
+#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_3 0xCDBEEF
+#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_4 0xEDBEEF
+#define REO_QUEUE_DESC_MAGIC_DEBUG_PATTERN_5 0xFDBEEF
+
struct ath12k_hal_rx_cmd_ring_param {
u32 mac_addr_31_0;
u32 mac_addr_47_32:16,
@@ -142,4 +153,8 @@ void ath12k_wifi8_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
void ath12k_wifi8_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_status *status);
+u32 ath12k_wifi8_hal_reo_qdesc_size(u32 ba_window_size, u8 tid);
+void ath12k_wifi8_hal_reo_qdesc_setup(struct hal_rx_reo_queue *qdesc,
+ int tid, u32 ba_window_size,
+ u32 start_seq, enum hal_pn_type type);
#endif

--
2.43.0