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

Pradeep Kumar Chitrapu pradeep.chitrapu at oss.qualcomm.com
Tue Nov 3 17:10:52 PST 2026


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 at oss.qualcomm.com>
---
 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




More information about the ath12k mailing list