* [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support
@ 2026-11-04 1:10 Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 01/13] wifi: ath12k: ng: add REO command and status support Pradeep Kumar Chitrapu
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
Add the Wi-Fi 8 REO command handling needed by the QCN9625 datapath.
The series introduces the REO command and status descriptors, high
priority REO command ring support, common command context handling, REO
status processing, 1K queue statistics parsing, batched command sends,
REO queue descriptor helpers, qaddr cache clear support and RX TID REO
operation wiring.
The last patch fixes REO TID setup on Wi-Fi 8 global-peer-ID devices by
using the host-allocated dp_peer id instead of the invalid link peer id
when programming REO queue state.
The latest dependency postings found in local mail for this stack are:
Depends-on: [PATCH ath-next v4 00/12] wifi: ath12k: ng: refactor DP and HAL for multi-gen arch-ops
Message-ID: <20261103163435.2682252-1-praneesh.p@oss.qualcomm.com>
Depends-on: [PATCH ath-next v3 00/10] wifi: ath12k: ng: Add QCN9625 Wi-Fi 8 HAL register and descriptor definitions
Message-ID: <20261030120743.2687216-1-praneesh.p@oss.qualcomm.com>
Depends-on: [PATCH 0/4] wifi: ath12k: ng: Add SAM support for QCN9625
Message-ID: <20260921090656.1575082-1-aishwarya.r@oss.qualcomm.com>
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
Changes in v3:
- Update the cover letter dependency references to the latest versions
found in local mail: multi-gen arch-ops v4 and QCN9625 HAL/register
definitions v3.
- Clean up the global-peer-ID fix by keeping only the wiphy-locked
dp_peer accessor needed by the series.
- Make the dp_peer accessor typed and local to ath12k, and drop the
unused RCU accessor/export churn from the last patch.
- Link to v2: https://patch.msgid.link/20261021-reo-cmd-b4-posting-v2-0-e8e3f482bfc9@oss.qualcomm.com
Changes in v2:
- Use a lock-held helper for Wi-Fi 8 REO command queueing.
- Document all-or-nothing SRNG pointer rollback for batched REO commands.
- Use the shared Wi-Fi 8 REO queue-address LUT for qref updates.
- Link to v1: https://patch.msgid.link/20260923-reo-cmd-b4-posting-v1-0-74935135a2de@oss.qualcomm.com
To: Jeff Johnson <jjohnson@kernel.org>
To: Ripan Deuri <quic_rdeuri@quicinc.com>
To: Pavankumar Nandeshwar <quic_pnandesh@quicinc.com>
To: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
To: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Cc: linux-wireless@vger.kernel.org
Cc: ath12k@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
---
Pradeep Kumar Chitrapu (13):
wifi: ath12k: ng: add REO command and status support
wifi: ath12k: ng: add high-priority REO command ring
wifi: ath12k: ng: allocate REO command context before submission
wifi: ath12k: ng: refactor REO command framework for extensibility
wifi: ath12k: ng: log successful RX TID queue updates
wifi: ath12k: ng: parse 1K REO queue statistics
wifi: ath12k: ng: process REO status ring
wifi: ath12k: ng: add batched REO command sends
wifi: ath12k: ng: add REO queue descriptor helpers
wifi: ath12k: ng: add REO qaddr cache clear support
wifi: ath12k: ng: add RX TID REO helpers
wifi: ath12k: ng: wire RX TID REO operations
wifi: ath12k: ng: use global dp peer id for REO TID setup
drivers/net/wireless/ath/ath12k/core.h | 2 +
drivers/net/wireless/ath/ath12k/dp.c | 10 +-
drivers/net/wireless/ath/ath12k/dp.h | 15 +-
drivers/net/wireless/ath/ath12k/dp_cmn.h | 6 +
drivers/net/wireless/ath/ath12k/dp_peer.c | 14 +
drivers/net/wireless/ath/ath12k/dp_peer.h | 4 +-
drivers/net/wireless/ath/ath12k/dp_rx.c | 138 +++-
drivers/net/wireless/ath/ath12k/dp_rx.h | 20 +-
drivers/net/wireless/ath/ath12k/hal.h | 103 +++
drivers/net/wireless/ath/ath12k/mac.c | 15 +-
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 63 +-
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 4 +-
drivers/net/wireless/ath/ath12k/wifi7/hal.h | 94 +--
drivers/net/wireless/ath/ath12k/wifi8/dp.c | 28 +
drivers/net/wireless/ath/ath12k/wifi8/dp.h | 1 +
drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c | 16 +-
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c | 643 +++++++++++++++-
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h | 57 ++
drivers/net/wireless/ath/ath12k/wifi8/hal.c | 16 +-
drivers/net/wireless/ath/ath12k/wifi8/hal.h | 3 +
drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h | 377 +++++++++-
.../net/wireless/ath/ath12k/wifi8/hal_qcn9625.c | 1 +
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c | 813 +++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h | 103 ++-
drivers/net/wireless/ath/ath12k/wifi8/hal_tx.h | 9 +
drivers/net/wireless/ath/ath12k/wifi8/hw.c | 1 +
26 files changed, 2347 insertions(+), 209 deletions(-)
---
base-commit: a2fa01354eb39e673f3f09e6c1cec39f82f0f9ae
change-id: 20260923-reo-cmd-b4-posting-af227314a3b5
prerequisite-patch-id: 49882cc69530a316a86f617b0b8649c3e753fc39
prerequisite-patch-id: 6fe238c82896b9f8b39fa0f09e32fb72d82ea6e1
prerequisite-patch-id: f09a16b2b6b388cb3290a14d86f4fbe370929680
prerequisite-patch-id: f7fab6336752c5a6e2e45221157c05a2845b1057
Best regards,
--
Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 01/13] wifi: ath12k: ng: add REO command and status support
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 02/13] wifi: ath12k: ng: add high-priority REO command ring Pradeep Kumar Chitrapu
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
The Wi-Fi 8 datapath can initialize the REO command ring, but it lacks
the command encoders and status decoders needed by datapath clients to
inspect and update RX reorder queues.
Add descriptor definitions and HAL helpers for queue statistics, queue
and cache flush, cache unblock, timeout-list flush, descriptor-threshold
status, and RX queue update commands. Keep update selector bits separate
from their programmed values, use the corrected hardware field layout
for queue updates, and request queue writeback to DDR after updates.
Add the ASE cache invalidation command encoder as part of the same HAL
command support because later queue-address cache maintenance uses that
ring format on Wi-Fi 8.
Decode the corresponding status TLVs into one software status container.
This commit adds HAL primitives only; it does not submit commands or
service the REO status ring.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/hal.h | 1 +
drivers/net/wireless/ath/ath12k/wifi8/hal.c | 3 +-
drivers/net/wireless/ath/ath12k/wifi8/hal.h | 87 ++++
drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h | 269 +++++++++--
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c | 576 +++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h | 75 ++-
drivers/net/wireless/ath/ath12k/wifi8/hal_tx.h | 9 +
7 files changed, 977 insertions(+), 43 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index 3a8e26738270..f175b5361080 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1138,6 +1138,7 @@ struct ath12k_hal_reo_cmd {
u8 blocking_idx;
u16 ba_window_size;
u8 pn_size;
+ u8 pn_127_48_info;
};
enum hal_pn_type {
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal.c b/drivers/net/wireless/ath/ath12k/wifi8/hal.c
index 1aa62c669cb2..036c04cbbf16 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal.c
@@ -584,8 +584,7 @@ void ath12k_wifi8_hal_reo_init_cmd_ring(struct ath12k_base *ab,
for (i = 0; i < params.num_entries; i++) {
tlv = (struct hal_tlv_64_hdr *)entry;
desc = (struct hal_reo_get_queue_stats *)tlv->value;
- desc->cmd.info0 = le32_encode_bits(cmd_num++,
- HAL_REO_CMD_HDR_INFO0_CMD_NUMBER);
+ desc->cmd.reo_cmd_number = cpu_to_le16(cmd_num++);
entry += entry_size;
}
}
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal.h b/drivers/net/wireless/ath/ath12k/wifi8/hal.h
index 6fd99e52f1a9..d30ee1242122 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal.h
@@ -896,6 +896,93 @@ enum ath12k_hal_tx_pkt_ctrl_config {
HAL_TX_PACKET_CONTROL_CONFIG_MEC_NOTIFY_TX_EXCEPTION,
};
+struct hal_reo_status_queue_stats {
+ u16 ssn;
+ u16 curr_idx;
+ u32 pn[4];
+ u32 last_rx_queue_ts;
+ u32 last_rx_dequeue_ts;
+ u32 rx_bitmap[9];
+ u32 curr_mpdu_cnt;
+ u32 curr_msdu_cnt;
+ u16 fwd_due_to_bar_cnt;
+ u16 dup_cnt;
+ u32 frames_in_order_cnt;
+ u32 num_mpdu_processed_cnt;
+ u32 num_msdu_processed_cnt;
+ u32 total_num_processed_byte_cnt;
+ u32 late_rx_mpdu_cnt;
+ u32 reorder_hole_cnt;
+ u8 timeout_cnt;
+ u8 bar_rx_cnt;
+ u8 num_window_2k_jump_cnt;
+};
+
+struct hal_reo_status_flush_queue {
+ bool err_detected;
+};
+
+enum hal_reo_status_flush_cache_err_code {
+ HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_SUCCESS,
+ HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_IN_USE,
+ HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_NOT_FOUND,
+};
+
+struct hal_reo_status_flush_cache {
+ bool err_detected;
+ enum hal_reo_status_flush_cache_err_code err_code;
+ bool cache_controller_flush_status_hit;
+ u8 cache_controller_flush_status_desc_type;
+ u8 cache_controller_flush_status_client_id;
+ u8 cache_controller_flush_status_err;
+ u8 cache_controller_flush_status_cnt;
+};
+
+enum hal_reo_status_unblock_cache_type {
+ HAL_REO_STATUS_UNBLOCK_BLOCKING_RESOURCE,
+ HAL_REO_STATUS_UNBLOCK_ENTIRE_CACHE_USAGE,
+};
+
+struct hal_reo_status_unblock_cache {
+ bool err_detected;
+ enum hal_reo_status_unblock_cache_type unblock_type;
+};
+
+struct hal_reo_status_flush_timeout_list {
+ bool err_detected;
+ bool list_empty;
+ u16 release_desc_cnt;
+ u16 fwd_buf_cnt;
+};
+
+enum hal_reo_threshold_idx {
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER0,
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER1,
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER2,
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER_SUM,
+};
+
+struct hal_reo_status_desc_thresh_reached {
+ enum hal_reo_threshold_idx threshold_idx;
+ u32 link_desc_counter0;
+ u32 link_desc_counter1;
+ u32 link_desc_counter2;
+ u32 link_desc_counter_sum;
+};
+
+struct hal_reo_status {
+ struct hal_reo_status_header uniform_hdr;
+ u8 loop_cnt;
+ union {
+ struct hal_reo_status_queue_stats queue_stats;
+ struct hal_reo_status_flush_queue flush_queue;
+ struct hal_reo_status_flush_cache flush_cache;
+ struct hal_reo_status_unblock_cache unblock_cache;
+ struct hal_reo_status_flush_timeout_list timeout_list;
+ struct hal_reo_status_desc_thresh_reached desc_thresh_reached;
+ } u;
+};
+
void ath12k_wifi8_hal_init(struct ath12k_base *ab);
void ath12k_wifi8_hal_ce_dst_setup(struct ath12k_base *ab,
struct hal_srng *srng, int ring_num);
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h b/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h
index 05ce2dbd39e5..691c9866522f 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h
@@ -413,18 +413,18 @@ struct hal_reo_entrance_ring {
__le32 info4;
} __packed;
-#define HAL_REO_CMD_HDR_INFO0_CMD_NUMBER GENMASK(15, 0)
-#define HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED BIT(16)
+#define HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED BIT(0)
struct hal_reo_cmd_hdr {
- __le32 info0;
+ __le16 reo_cmd_number;
+ __le16 info0;
} __packed;
-#define HAL_REO_STATUS_HDR_INFO0_STATUS_NUM GENMASK(15, 0)
-#define HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS GENMASK(27, 26)
+#define HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS GENMASK(11, 10)
struct hal_reo_status_hdr {
- __le32 info0;
+ __le16 reo_status_number;
+ __le16 info0;
__le32 timestamp;
} __packed;
@@ -453,9 +453,9 @@ struct hal_reo_status_hdr {
struct hal_reo_get_queue_stats {
struct hal_reo_cmd_hdr cmd;
__le32 queue_addr_lo;
- __le32 info0;
- __le32 rsvd0[6];
- __le32 tlv64_pad;
+ __le16 info0;
+ __le16 rsvd0;
+ __le32 rsvd1[7];
} __packed;
/* hal_reo_get_queue_stats
@@ -494,17 +494,17 @@ struct hal_reo_get_queue_stats {
#define HAL_REO_GET_Q_STATS_STATUS_INFO1_PN_127_48_INFO GENMASK(1, 0)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO3_CURRENT_MPDU_COUNT GENMASK(6, 0)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO3_CURRENT_MSDU_COUNT GENMASK(31, 7)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO4_WINDOW_JUMP_2K GENMASK(3, 0)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO4_TIMEOUT_COUNT GENMASK(9, 4)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO4_FWD_DUE_TO_BAR_COUNT GENMASK(15, 10)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO5_FRAMES_IN_ORDER_COUNT GENMASK(23, 0)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO5_BAR_RECEIVED_COUNT GENMASK(31, 24)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO6_LATE_RCV_MPDU_COUNT GENMASK(11, 0)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO6_HOLE_COUNT GENMASK(27, 12)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO6_GET_Q_1K_SSTAT_FOLLOW BIT(28)
-#define HAL_REO_GET_Q_STATS_STATUS_INFO7_LOOPING_COUNT GENMASK(15, 12)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO2_CURRENT_MPDU_COUNT GENMASK(6, 0)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO2_CURRENT_MSDU_COUNT GENMASK(31, 7)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO3_WINDOW_JUMP_2K GENMASK(3, 0)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO3_TIMEOUT_COUNT GENMASK(9, 4)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO3_FWD_DUE_TO_BAR_COUNT GENMASK(15, 10)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO4_FRAMES_IN_ORDER_COUNT GENMASK(23, 0)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO4_BAR_RECEIVED_COUNT GENMASK(31, 24)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO5_LATE_RCV_MPDU_COUNT GENMASK(11, 0)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO5_HOLE_COUNT GENMASK(27, 12)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO5_GET_Q_1K_SSTAT_FOLLOW BIT(28)
+#define HAL_REO_GET_Q_STATS_STATUS_INFO6_LOOPING_COUNT GENMASK(15, 12)
struct hal_reo_get_queue_stats_status {
struct hal_reo_status_hdr hdr;
@@ -512,8 +512,7 @@ struct hal_reo_get_queue_stats_status {
__le32 pn_31_0;
__le16 pn_47_32;
__le16 info1;
- __le32 info2;
- __le32 rsvd0;
+ __le32 rsvd0[2];
__le32 last_rx_enqueue_timestamp;
__le32 last_rx_dequeue_timestamp;
__le32 rx_bitmap_31_0;
@@ -525,16 +524,205 @@ struct hal_reo_get_queue_stats_status {
__le32 rx_bitmap_223_192;
__le32 rx_bitmap_255_224;
__le32 rx_bitmap_287_256;
- __le32 info3;
- __le16 info4;
+ __le32 info2;
+ __le16 info3;
__le16 duplicate_count;
- __le32 info5;
+ __le32 info4;
__le32 mpdu_frames_processed_count;
__le32 msdu_frames_processed_count;
__le32 total_processed_byte_count;
- __le32 info6;
+ __le32 info5;
__le16 aging_drop_mpdu_count;
- __le16 info7;
+ __le16 info6;
+} __packed;
+
+/* REO command TLV tags */
+#define HAL_REO_GET_QUEUE_STATS 313
+#define HAL_REO_FLUSH_QUEUE 314
+#define HAL_REO_FLUSH_CACHE 315
+#define HAL_REO_UNBLOCK_CACHE 316
+#define HAL_REO_GET_QUEUE_STATS_STATUS 317
+#define HAL_REO_FLUSH_QUEUE_STATUS 318
+#define HAL_REO_FLUSH_CACHE_STATUS 319
+#define HAL_REO_UNBLOCK_CACHE_STATUS 320
+#define HAL_REO_FLUSH_TIMEOUT_LIST 337
+#define HAL_REO_FLUSH_TIMEOUT_LIST_STATUS 338
+#define HAL_REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS 339
+#define HAL_REO_UPDATE_RX_REO_QUEUE 371
+#define HAL_REO_UPDATE_RX_REO_QUEUE_STATUS 204
+
+#define HAL_REO_FLUSH_QUEUE_INFO0_DESC_ADDR_HI GENMASK(7, 0)
+struct hal_reo_flush_queue {
+ struct hal_reo_cmd_hdr cmd;
+ __le32 desc_addr_lo;
+ __le16 info0;
+ __le16 rsvd0;
+ __le32 rsvd1[7];
+} __packed;
+
+#define HAL_REO_FLUSH_CACHE_INFO0_CACHE_ADDR_HI GENMASK(7, 0)
+#define HAL_REO_FLUSH_CACHE_INFO0_FWD_ALL_MPDUS BIT(8)
+#define HAL_REO_FLUSH_CACHE_INFO0_BLOCK_RESRC_IDX GENMASK(11, 10)
+#define HAL_REO_FLUSH_CACHE_INFO0_FLUSH_WO_INVALIDATE BIT(12)
+#define HAL_REO_FLUSH_CACHE_INFO0_BLOCK_CACHE_USAGE BIT(13)
+#define HAL_REO_FLUSH_CACHE_INFO0_FLUSH_ALL BIT(14)
+#define HAL_REO_FLUSH_CACHE_INFO0_FLUSH_QUEUE_1K_DESC BIT(15)
+
+struct hal_reo_flush_cache {
+ struct hal_reo_cmd_hdr cmd;
+ __le32 cache_addr_lo;
+ __le16 info0;
+ __le16 rsvd0;
+ __le32 rsvd1[7];
+} __packed;
+
+enum hal_rx_reo_queue_pn_size {
+ HAL_RX_REO_QUEUE_PN_SIZE_24,
+ HAL_RX_REO_QUEUE_PN_SIZE_48,
+ HAL_RX_REO_QUEUE_PN_SIZE_128,
+};
+
+#define HAL_REO_UPD_RX_QUEUE_INFO0_QUEUE_ADDR_HI GENMASK(7, 0)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_RX_QUEUE_NUM BIT(8)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_VLD BIT(9)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_ASSOC_LNK_DESC_CNT BIT(10)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_DIS_DUP_DETECTION BIT(11)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SOFT_REORDER_EN BIT(12)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_AC BIT(13)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_BAR BIT(14)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_RETRY BIT(15)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_CHECK_2K_MODE BIT(16)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_OOR_MODE BIT(17)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_BA_WINDOW_SIZE BIT(18)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_CHECK BIT(19)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_EVEN_PN BIT(20)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_UNEVEN_PN BIT(21)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_HANDLE_ENABLE BIT(22)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_SIZE BIT(23)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_IGNORE_AMPDU_FLG BIT(24)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SVLD BIT(25)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SSN BIT(26)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SEQ_2K_ERR BIT(27)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_ERR BIT(28)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_VALID BIT(29)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN BIT(30)
+#define HAL_REO_UPD_RX_QUEUE_INFO0_CLR_STATS_COUNTERS BIT(31)
+
+#define HAL_REO_UPD_RX_QUEUE_INFO1_VLD BIT(0)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_ASSOC_LNK_DESC_COUNTER GENMASK(2, 1)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_DIS_DUP_DETECTION BIT(3)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_SOFT_REORDER_EN BIT(4)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_LINK_LIST_TIMER_ID GENMASK(8, 5)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_BAR BIT(9)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_RETRY BIT(10)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_CHECK_2K_MODE BIT(11)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_OOR_MODE BIT(12)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_PN_CHECK BIT(13)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_EVEN_PN BIT(14)
+#define HAL_REO_UPD_RX_QUEUE_INFO1_UNEVEN_PN BIT(15)
+
+#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_HANDLE_ENABLE BIT(0)
+#define HAL_REO_UPD_RX_QUEUE_INFO2_IGNORE_AMPDU_FLG BIT(1)
+#define HAL_REO_UPD_RX_QUEUE_INFO2_BA_WINDOW_SIZE GENMASK(11, 2)
+#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_SIZE GENMASK(13, 12)
+#define HAL_REO_UPD_RX_QUEUE_INFO2_SVLD BIT(14)
+#define HAL_REO_UPD_RX_QUEUE_INFO2_SSN GENMASK(26, 15)
+#define HAL_REO_UPD_RX_QUEUE_INFO2_SEQ_2K_ERR BIT(27)
+#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_ERR BIT(28)
+#define HAL_REO_UPD_RX_QUEUE_INFO2_PN_VALID BIT(29)
+#define HAL_REO_UPD_RX_QUEUE_INFO2_FLUSH_FROM_CACHE BIT(30)
+
+#define HAL_REO_UPD_RX_QUEUE_INFO3_PN_127_48_INFO GENMASK(1, 0)
+
+struct hal_reo_update_rx_queue {
+ struct hal_reo_cmd_hdr cmd;
+ __le32 queue_addr_lo;
+ __le32 info0;
+ __le16 receive_queue_number;
+ __le16 info1;
+ __le32 info2;
+ __le32 pn_31_0;
+ __le16 pn_47_32;
+ __le16 info3;
+ __le32 rsvd0[3];
+} __packed;
+
+#define HAL_REO_UNBLOCK_CACHE_INFO0_UNBLK_CACHE BIT(0)
+
+struct hal_reo_unblock_cache {
+ struct hal_reo_cmd_hdr cmd;
+ __le16 info0;
+ __le16 rsvd0;
+ __le32 rsvd1[8];
+} __packed;
+
+#define HAL_REO_STATUS_LOOP_CNT GENMASK(31, 28)
+
+#define HAL_REO_FLUSH_QUEUE_INFO0_ERR_DETECTED BIT(0)
+#define HAL_REO_FLUSH_QUEUE_INFO0_RSVD GENMASK(31, 1)
+#define HAL_REO_FLUSH_QUEUE_INFO1_RSVD GENMASK(27, 0)
+
+struct hal_reo_flush_queue_status {
+ struct hal_reo_status_hdr hdr;
+ __le32 info0;
+ __le32 rsvd0[21];
+ __le32 info1;
+} __packed;
+
+#define HAL_REO_FLUSH_CACHE_STATUS_INFO0_IS_ERR BIT(0)
+#define HAL_REO_FLUSH_CACHE_STATUS_INFO0_BLOCK_ERR_CODE GENMASK(2, 1)
+#define HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_STATUS_HIT BIT(8)
+#define HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_DESC_TYPE GENMASK(11, 9)
+#define HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_CLIENT_ID GENMASK(15, 12)
+#define HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_ERR GENMASK(17, 16)
+#define HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_COUNT GENMASK(25, 18)
+
+struct hal_reo_flush_cache_status {
+ struct hal_reo_status_hdr hdr;
+ __le32 info0;
+ __le32 rsvd0[21];
+ __le32 info1;
+} __packed;
+
+#define HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_IS_ERR BIT(0)
+#define HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_TYPE BIT(1)
+
+struct hal_reo_unblock_cache_status {
+ struct hal_reo_status_hdr hdr;
+ __le32 info0;
+ __le32 rsvd0[21];
+ __le32 info1;
+} __packed;
+
+#define HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_IS_ERR BIT(0)
+#define HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_LIST_EMPTY BIT(1)
+
+#define HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_REL_DESC_COUNT GENMASK(15, 0)
+#define HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_FWD_BUF_COUNT GENMASK(31, 16)
+
+struct hal_reo_flush_timeout_list_status {
+ struct hal_reo_status_hdr hdr;
+ __le32 info0;
+ __le32 info1;
+ __le32 rsvd0[20];
+ __le32 info2;
+} __packed;
+
+#define HAL_REO_DESC_THRESH_STATUS_INFO0_THRESH_INDEX GENMASK(1, 0)
+#define HAL_REO_DESC_THRESH_STATUS_INFO1_LINK_DESC_COUNTER0 GENMASK(23, 0)
+#define HAL_REO_DESC_THRESH_STATUS_INFO2_LINK_DESC_COUNTER1 GENMASK(23, 0)
+#define HAL_REO_DESC_THRESH_STATUS_INFO3_LINK_DESC_COUNTER2 GENMASK(23, 0)
+#define HAL_REO_DESC_THRESH_STATUS_INFO4_LINK_DESC_COUNTER_SUM GENMASK(25, 0)
+
+struct hal_reo_desc_thresh_reached_status {
+ struct hal_reo_status_hdr hdr;
+ __le32 info0;
+ __le32 info1;
+ __le32 info2;
+ __le32 info3;
+ __le32 info4;
+ __le32 rsvd0[17];
+ __le32 info5;
} __packed;
#define HAL_TCL_DATA_CMD_INFO0_BUF_OR_EXT_DESC_TYPE BIT(1)
@@ -683,6 +871,33 @@ struct hal_tqm_sync_cmd_status {
__le32 info20;
};
+#define HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_0 BIT(0)
+#define HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_1 BIT(1)
+#define HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_2 BIT(2)
+#define HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_3 BIT(3)
+#define HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_4 BIT(4)
+
+#define HAL_ASE_CMD_RING_INFO1_MAC_ADDR_31_0 GENMASK(31, 0)
+#define HAL_ASE_CMD_RING_INFO2_MAC_ADDR_47_32 GENMASK(15, 0)
+#define HAL_ASE_CMD_RING_INFO2_IS_MCAST BIT(16)
+#define HAL_ASE_CMD_RING_INFO2_IS_MEC BIT(17)
+#define HAL_ASE_CMD_RING_INFO2_AD1_MATCH BIT(18)
+#define HAL_ASE_CMD_RING_INFO2_LINK_ID GENMASK(21, 19)
+#define HAL_ASE_CMD_RING_INFO2_GSE_CTRL GENMASK(25, 22)
+#define HAL_ASE_CMD_RING_INFO2_SEARCH_INDEX_EN BIT(26)
+#define HAL_ASE_CMD_RING_INFO2_CACHE_SET_NUM GENMASK(31, 27)
+#define HAL_ASE_CMD_RING_CMD_METADATA_31_0 GENMASK(31, 0)
+#define HAL_ASE_CMD_RING_INFO3_SEARCH_INDEX GENMASK(19, 0)
+
+struct hal_ase_cmd {
+ __le32 info0;
+ __le32 info1;
+ __le32 info2;
+ __le32 cmd_meta_data_31_0;
+ __le32 rsvd[3];
+ __le32 info3;
+} __packed;
+
#define HAL_TCL_EXIT_BASE_INFO0_BUF_OR_EXT_DESC_TYPE BIT(0)
#define HAL_TCL_EXIT_BASE_INFO0_ENCAP_TYPE GENMASK(2, 1)
#define HAL_TCL_EXIT_BASE_INFO0_TID GENMASK(14, 11)
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
index c75fdd22139a..80c2f1202233 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
@@ -202,3 +202,579 @@ void ath12k_wifi8_hal_reo_hw_setup(struct ath12k_base *ab)
ath12k_hif_write32(ab, reo_base + HAL_REO1_RXDMA_ERROR_DESTINATION_MAPPING_AP_IX3,
val);
}
+
+int
+ath12k_wifi8_hal_invalidate_rx_cache_cmd_send(struct ath12k_base *ab,
+ struct hal_srng *srng,
+ struct ath12k_hal_rx_cmd_ring_param *param)
+{
+ struct hal_ase_cmd *ase_cmd;
+ int ret = 0;
+
+ spin_lock_bh(&srng->lock);
+
+ ath12k_hal_srng_access_begin(ab, srng);
+ ase_cmd = ath12k_hal_srng_src_get_next_entry(ab, srng);
+ if (!ase_cmd) {
+ ret = -ENOBUFS;
+ goto out;
+ }
+ memset(ase_cmd, 0x0, sizeof(*ase_cmd));
+
+ ase_cmd->info0 =
+ le32_encode_bits(!!(param->hw_link_bitmap & BIT(0)),
+ HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_0) |
+ le32_encode_bits(!!(param->hw_link_bitmap & BIT(1)),
+ HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_1) |
+ le32_encode_bits(!!(param->hw_link_bitmap & BIT(2)),
+ HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_2) |
+ le32_encode_bits(!!(param->hw_link_bitmap & BIT(3)),
+ HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_3) |
+ le32_encode_bits(!!(param->hw_link_bitmap & BIT(4)),
+ HAL_ASE_CMD_RING_INFO0_CMD_TO_CHIP_4);
+ ase_cmd->info1 = le32_encode_bits(param->mac_addr_31_0,
+ HAL_ASE_CMD_RING_INFO1_MAC_ADDR_31_0);
+ ase_cmd->info2 = le32_encode_bits(param->mac_addr_47_32,
+ HAL_ASE_CMD_RING_INFO2_MAC_ADDR_47_32) |
+ le32_encode_bits(param->is_mcast,
+ HAL_ASE_CMD_RING_INFO2_IS_MCAST) |
+ le32_encode_bits(param->is_mec,
+ HAL_ASE_CMD_RING_INFO2_IS_MEC) |
+ le32_encode_bits(param->ad1_match,
+ HAL_ASE_CMD_RING_INFO2_AD1_MATCH) |
+ le32_encode_bits(param->link_id,
+ HAL_ASE_CMD_RING_INFO2_LINK_ID) |
+ le32_encode_bits(param->cmd_num,
+ HAL_ASE_CMD_RING_INFO2_GSE_CTRL);
+ ase_cmd->cmd_meta_data_31_0 = cpu_to_le32(param->meta_data_0);
+out:
+ ath12k_hal_srng_access_end(ab, srng);
+ spin_unlock_bh(&srng->lock);
+
+ return ret;
+}
+
+static int ath12k_wifi8_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 = le64_encode_bits(HAL_REO_GET_QUEUE_STATS, HAL_TLV_HDR_TAG) |
+ le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
+
+ desc = (struct hal_reo_get_queue_stats *)tlv->value;
+ memset_startat(desc, 0, queue_addr_lo);
+
+ desc->cmd.info0 &= ~cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+ if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
+ desc->cmd.info0 |= cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+
+ desc->queue_addr_lo = cpu_to_le32(cmd->addr_lo);
+ desc->info0 = le16_encode_bits(cmd->addr_hi,
+ HAL_REO_GET_QUEUE_STATS_INFO0_QUEUE_ADDR_HI);
+ if (cmd->flag & HAL_REO_CMD_FLG_STATS_CLEAR)
+ desc->info0 |= cpu_to_le16(HAL_REO_GET_QUEUE_STATS_INFO0_CLEAR_STATS);
+
+ return le16_to_cpu(desc->cmd.reo_cmd_number);
+}
+
+static int ath12k_wifi8_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;
+ u8 avail_slot = ffz(hal->avail_blk_resource);
+
+ if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_BLOCK_LATER) {
+ if (avail_slot >= HAL_MAX_AVAIL_BLK_RES)
+ return -ENOSPC;
+
+ hal->current_blk_index = avail_slot;
+ }
+
+ tlv->tl = le64_encode_bits(HAL_REO_FLUSH_CACHE, HAL_TLV_HDR_TAG) |
+ le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
+
+ desc = (struct hal_reo_flush_cache *)tlv->value;
+ memset_startat(desc, 0, cache_addr_lo);
+
+ desc->cmd.info0 &= ~cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+ if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
+ desc->cmd.info0 |= cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+
+ desc->cache_addr_lo = cpu_to_le32(cmd->addr_lo);
+ desc->info0 = le16_encode_bits(cmd->addr_hi,
+ HAL_REO_FLUSH_CACHE_INFO0_CACHE_ADDR_HI);
+
+ if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS)
+ desc->info0 |= cpu_to_le16(HAL_REO_FLUSH_CACHE_INFO0_FWD_ALL_MPDUS);
+
+ if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_BLOCK_LATER) {
+ desc->info0 |= cpu_to_le16(HAL_REO_FLUSH_CACHE_INFO0_BLOCK_CACHE_USAGE);
+ desc->info0 |=
+ le16_encode_bits(avail_slot,
+ HAL_REO_FLUSH_CACHE_INFO0_BLOCK_RESRC_IDX);
+ }
+
+ if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_NO_INVAL)
+ desc->info0 |= cpu_to_le16(HAL_REO_FLUSH_CACHE_INFO0_FLUSH_WO_INVALIDATE);
+
+ if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_ALL)
+ desc->info0 |= cpu_to_le16(HAL_REO_FLUSH_CACHE_INFO0_FLUSH_ALL);
+
+ if (cmd->flag & HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC)
+ desc->info0 |= cpu_to_le16(HAL_REO_FLUSH_CACHE_INFO0_FLUSH_QUEUE_1K_DESC);
+
+ return le16_to_cpu(desc->cmd.reo_cmd_number);
+}
+
+static int
+ath12k_wifi8_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 = le64_encode_bits(HAL_REO_UPDATE_RX_REO_QUEUE, HAL_TLV_HDR_TAG) |
+ le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
+
+ desc = (struct hal_reo_update_rx_queue *)tlv->value;
+ memset_startat(desc, 0, queue_addr_lo);
+
+ desc->cmd.info0 &= ~cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+ if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
+ desc->cmd.info0 |= cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+
+ desc->queue_addr_lo = cpu_to_le32(cmd->addr_lo);
+ desc->info0 =
+ le32_encode_bits(cmd->addr_hi,
+ HAL_REO_UPD_RX_QUEUE_INFO0_QUEUE_ADDR_HI) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_RX_QUEUE_NUM),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_RX_QUEUE_NUM) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_VLD),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_VLD) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_ALDC),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_ASSOC_LNK_DESC_CNT) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_DIS_DUP_DETECTION),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_DIS_DUP_DETECTION) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_SOFT_REORDER_EN),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SOFT_REORDER_EN) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_AC),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_AC) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_BAR),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_BAR) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_RETRY),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_RETRY) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_CHECK_2K_MODE),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_CHECK_2K_MODE) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_OOR_MODE),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_OOR_MODE) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_BA_WINDOW_SIZE),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_BA_WINDOW_SIZE) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN_CHECK),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_CHECK) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_EVEN_PN),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_EVEN_PN) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_UNEVEN_PN),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_UNEVEN_PN) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN_HANDLE_ENABLE),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_HANDLE_ENABLE) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN_SIZE),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_SIZE) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_IGNORE_AMPDU_FLG),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_IGNORE_AMPDU_FLG) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_SVLD),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SVLD) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_SSN),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SSN) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_SEQ_2K_ERR),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_SEQ_2K_ERR) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN_ERR),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_ERR) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN_VALID),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN_VALID) |
+ le32_encode_bits(!!(cmd->upd0 & HAL_REO_CMD_UPD0_PN),
+ HAL_REO_UPD_RX_QUEUE_INFO0_UPD_PN);
+
+ if (cmd->flag & HAL_REO_CMD_FLG_STATS_CLEAR)
+ desc->info0 |= cpu_to_le32(HAL_REO_UPD_RX_QUEUE_INFO0_CLR_STATS_COUNTERS);
+
+ desc->receive_queue_number = cpu_to_le16(cmd->rx_queue_num);
+ desc->info1 =
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_VLD),
+ HAL_REO_UPD_RX_QUEUE_INFO1_VLD) |
+ le16_encode_bits(u32_get_bits(cmd->upd1, HAL_REO_CMD_UPD1_ALDC),
+ HAL_REO_UPD_RX_QUEUE_INFO1_ASSOC_LNK_DESC_COUNTER) |
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_DIS_DUP_DETECTION),
+ HAL_REO_UPD_RX_QUEUE_INFO1_DIS_DUP_DETECTION) |
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_SOFT_REORDER_EN),
+ HAL_REO_UPD_RX_QUEUE_INFO1_SOFT_REORDER_EN) |
+ le16_encode_bits(u32_get_bits(cmd->upd1, HAL_REO_CMD_UPD1_LL_TIMER_ID),
+ HAL_REO_UPD_RX_QUEUE_INFO1_LINK_LIST_TIMER_ID) |
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_BAR),
+ HAL_REO_UPD_RX_QUEUE_INFO1_BAR) |
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_CHECK_2K_MODE),
+ HAL_REO_UPD_RX_QUEUE_INFO1_CHECK_2K_MODE) |
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_RETRY),
+ HAL_REO_UPD_RX_QUEUE_INFO1_RETRY) |
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_OOR_MODE),
+ HAL_REO_UPD_RX_QUEUE_INFO1_OOR_MODE) |
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_PN_CHECK),
+ HAL_REO_UPD_RX_QUEUE_INFO1_PN_CHECK) |
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_EVEN_PN),
+ HAL_REO_UPD_RX_QUEUE_INFO1_EVEN_PN) |
+ le16_encode_bits(!!(cmd->upd1 & HAL_REO_CMD_UPD1_UNEVEN_PN),
+ HAL_REO_UPD_RX_QUEUE_INFO1_UNEVEN_PN);
+
+ if (cmd->pn_size == 24)
+ cmd->pn_size = HAL_RX_REO_QUEUE_PN_SIZE_24;
+ else if (cmd->pn_size == 48)
+ cmd->pn_size = HAL_RX_REO_QUEUE_PN_SIZE_48;
+ else if (cmd->pn_size == 128)
+ cmd->pn_size = HAL_RX_REO_QUEUE_PN_SIZE_128;
+
+ if (cmd->ba_window_size < 1)
+ cmd->ba_window_size = 1;
+
+ if (cmd->ba_window_size == 1)
+ cmd->ba_window_size++;
+
+ desc->info2 =
+ le32_encode_bits(!!(cmd->upd2 & HAL_REO_CMD_UPD2_PN_HANDLE_ENABLE),
+ HAL_REO_UPD_RX_QUEUE_INFO2_PN_HANDLE_ENABLE) |
+ le32_encode_bits(!!(cmd->upd2 & HAL_REO_CMD_UPD2_IGNORE_AMPDU_FLG),
+ HAL_REO_UPD_RX_QUEUE_INFO2_IGNORE_AMPDU_FLG) |
+ le32_encode_bits(cmd->ba_window_size - 1,
+ HAL_REO_UPD_RX_QUEUE_INFO2_BA_WINDOW_SIZE) |
+ le32_encode_bits(cmd->pn_size, HAL_REO_UPD_RX_QUEUE_INFO2_PN_SIZE) |
+ le32_encode_bits(!!(cmd->upd2 & HAL_REO_CMD_UPD2_SVLD),
+ HAL_REO_UPD_RX_QUEUE_INFO2_SVLD) |
+ le32_encode_bits(u32_get_bits(cmd->upd2, HAL_REO_CMD_UPD2_SSN),
+ HAL_REO_UPD_RX_QUEUE_INFO2_SSN) |
+ le32_encode_bits(!!(cmd->upd2 & HAL_REO_CMD_UPD2_SEQ_2K_ERR),
+ HAL_REO_UPD_RX_QUEUE_INFO2_SEQ_2K_ERR) |
+ le32_encode_bits(!!(cmd->upd2 & HAL_REO_CMD_UPD2_PN_ERR),
+ HAL_REO_UPD_RX_QUEUE_INFO2_PN_ERR) |
+ le32_encode_bits(!!(cmd->upd2 & HAL_REO_CMD_UPD2_PN_VALID),
+ HAL_REO_UPD_RX_QUEUE_INFO2_PN_VALID);
+
+ desc->info2 |= cpu_to_le32(HAL_REO_UPD_RX_QUEUE_INFO2_FLUSH_FROM_CACHE);
+
+ if (cmd->upd0 & HAL_REO_CMD_UPD0_PN) {
+ desc->pn_31_0 = cpu_to_le32(cmd->pn[0]);
+ desc->pn_47_32 = cpu_to_le16(cmd->pn[1]);
+ desc->info3 =
+ le16_encode_bits(cmd->pn_127_48_info,
+ HAL_REO_UPD_RX_QUEUE_INFO3_PN_127_48_INFO);
+ }
+
+ return le16_to_cpu(desc->cmd.reo_cmd_number);
+}
+
+static int ath12k_hal_reo_cmd_flush_queue(struct hal_tlv_64_hdr *tlv,
+ struct ath12k_hal_reo_cmd *cmd)
+{
+ struct hal_reo_flush_queue *desc = (struct hal_reo_flush_queue *)tlv->value;
+
+ tlv->tl = u32_encode_bits(HAL_REO_FLUSH_QUEUE, HAL_TLV_HDR_TAG) |
+ u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
+
+ memset_startat(desc, 0, desc_addr_lo);
+
+ desc->cmd.info0 &= ~cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+
+ if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
+ desc->cmd.info0 |= cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+
+ desc->desc_addr_lo = cpu_to_le32(cmd->addr_lo);
+ desc->info0 = le16_encode_bits(cmd->addr_hi,
+ HAL_REO_FLUSH_QUEUE_INFO0_DESC_ADDR_HI);
+
+ return le16_to_cpu(desc->cmd.reo_cmd_number);
+}
+
+static int ath12k_hal_reo_cmd_unblock_cache(struct hal_tlv_64_hdr *tlv,
+ struct ath12k_hal_reo_cmd *cmd)
+{
+ struct hal_reo_unblock_cache *desc =
+ (struct hal_reo_unblock_cache *)tlv->value;
+
+ tlv->tl = u32_encode_bits(HAL_REO_UNBLOCK_CACHE, HAL_TLV_HDR_TAG) |
+ u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
+
+ memset_startat(desc, 0, info0);
+
+ desc->cmd.info0 &= ~cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+
+ if (cmd->flag & HAL_REO_CMD_FLG_NEED_STATUS)
+ desc->cmd.info0 |= cpu_to_le16(HAL_REO_CMD_HDR_INFO0_STATUS_REQUIRED);
+
+ desc->info0 = cpu_to_le16(HAL_REO_UNBLOCK_CACHE_INFO0_UNBLK_CACHE);
+
+ return le16_to_cpu(desc->cmd.reo_cmd_number);
+}
+
+int ath12k_wifi8_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd)
+{
+ struct hal_tlv_64_hdr *reo_desc;
+ u32 saved_hp, saved_reap_hp;
+ int ret;
+
+ if (type == HAL_REO_CMD_FLUSH_TIMEOUT_LIST) {
+ ath12k_warn(ab, "Unsupported reo command %d\n", type);
+ return -EOPNOTSUPP;
+ }
+
+ if (type > HAL_REO_CMD_UPDATE_RX_QUEUE) {
+ ath12k_warn(ab, "Unknown reo command %d\n", type);
+ return -EINVAL;
+ }
+
+ spin_lock_bh(&srng->lock);
+
+ ath12k_hal_srng_access_begin(ab, srng);
+ saved_hp = srng->u.src_ring.hp;
+ saved_reap_hp = srng->u.src_ring.reap_hp;
+
+ reo_desc = ath12k_hal_srng_src_get_next_entry(ab, srng);
+ if (!reo_desc) {
+ ret = -ENOBUFS;
+ goto out;
+ }
+
+ switch (type) {
+ case HAL_REO_CMD_GET_QUEUE_STATS:
+ ret = ath12k_wifi8_hal_reo_cmd_queue_stats(reo_desc, cmd);
+ break;
+ case HAL_REO_CMD_FLUSH_CACHE:
+ ret = ath12k_wifi8_hal_reo_cmd_flush_cache(&ab->hal, reo_desc,
+ cmd);
+ break;
+ case HAL_REO_CMD_UPDATE_RX_QUEUE:
+ ret = ath12k_wifi8_hal_reo_cmd_update_rx_queue(reo_desc, cmd);
+ break;
+ case HAL_REO_CMD_FLUSH_QUEUE:
+ ret = ath12k_hal_reo_cmd_flush_queue(reo_desc, cmd);
+ break;
+ case HAL_REO_CMD_UNBLOCK_CACHE:
+ ret = ath12k_hal_reo_cmd_unblock_cache(reo_desc, cmd);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+out:
+ ath12k_hal_srng_access_end(ab, srng);
+ spin_unlock_bh(&srng->lock);
+
+ return ret;
+}
+
+static void ath12k_wifi8_hal_reo_status_hdr_parse(struct hal_reo_status_hdr *hdr,
+ struct hal_reo_status *status)
+{
+ status->uniform_hdr.cmd_num = le16_to_cpu(hdr->reo_status_number);
+ status->uniform_hdr.cmd_status =
+ le16_get_bits(hdr->info0, HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS);
+ status->uniform_hdr.timestamp = le32_to_cpu(hdr->timestamp);
+}
+
+void ath12k_wifi8_hal_reo_status_queue_stats(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status)
+{
+ struct hal_reo_get_queue_stats_status *desc =
+ (struct hal_reo_get_queue_stats_status *)tlv->value;
+
+ ath12k_wifi8_hal_reo_status_hdr_parse(&desc->hdr, status);
+
+ status->u.queue_stats.ssn =
+ le32_get_bits(desc->info0, HAL_REO_GET_Q_STATS_STATUS_INFO0_SSN);
+ status->u.queue_stats.curr_idx =
+ le32_get_bits(desc->info0, HAL_REO_GET_Q_STATS_STATUS_INFO0_CURRENT_INDEX);
+ status->u.queue_stats.pn[0] = le32_to_cpu(desc->pn_31_0);
+ status->u.queue_stats.pn[1] = le16_to_cpu(desc->pn_47_32);
+ status->u.queue_stats.last_rx_queue_ts =
+ le32_to_cpu(desc->last_rx_enqueue_timestamp);
+ status->u.queue_stats.last_rx_dequeue_ts =
+ le32_to_cpu(desc->last_rx_dequeue_timestamp);
+ status->u.queue_stats.rx_bitmap[0] = le32_to_cpu(desc->rx_bitmap_31_0);
+ status->u.queue_stats.rx_bitmap[1] = le32_to_cpu(desc->rx_bitmap_63_32);
+ status->u.queue_stats.rx_bitmap[2] = le32_to_cpu(desc->rx_bitmap_95_64);
+ status->u.queue_stats.rx_bitmap[3] = le32_to_cpu(desc->rx_bitmap_127_96);
+ status->u.queue_stats.rx_bitmap[4] = le32_to_cpu(desc->rx_bitmap_159_128);
+ status->u.queue_stats.rx_bitmap[5] = le32_to_cpu(desc->rx_bitmap_191_160);
+ status->u.queue_stats.rx_bitmap[6] = le32_to_cpu(desc->rx_bitmap_223_192);
+ status->u.queue_stats.rx_bitmap[7] = le32_to_cpu(desc->rx_bitmap_255_224);
+ status->u.queue_stats.rx_bitmap[8] = le32_to_cpu(desc->rx_bitmap_287_256);
+ status->u.queue_stats.curr_mpdu_cnt =
+ le32_get_bits(desc->info2, HAL_REO_GET_Q_STATS_STATUS_INFO2_CURRENT_MPDU_COUNT);
+ status->u.queue_stats.curr_msdu_cnt =
+ le32_get_bits(desc->info2, HAL_REO_GET_Q_STATS_STATUS_INFO2_CURRENT_MSDU_COUNT);
+ status->u.queue_stats.timeout_cnt =
+ le16_get_bits(desc->info3, HAL_REO_GET_Q_STATS_STATUS_INFO3_TIMEOUT_COUNT);
+ status->u.queue_stats.fwd_due_to_bar_cnt =
+ le16_get_bits(desc->info3, HAL_REO_GET_Q_STATS_STATUS_INFO3_FWD_DUE_TO_BAR_COUNT);
+ status->u.queue_stats.dup_cnt = le16_to_cpu(desc->duplicate_count);
+ status->u.queue_stats.frames_in_order_cnt =
+ le32_get_bits(desc->info4, HAL_REO_GET_Q_STATS_STATUS_INFO4_FRAMES_IN_ORDER_COUNT);
+ status->u.queue_stats.bar_rx_cnt =
+ le32_get_bits(desc->info4, HAL_REO_GET_Q_STATS_STATUS_INFO4_BAR_RECEIVED_COUNT);
+ status->u.queue_stats.num_mpdu_processed_cnt =
+ le32_to_cpu(desc->mpdu_frames_processed_count);
+ status->u.queue_stats.num_msdu_processed_cnt =
+ le32_to_cpu(desc->msdu_frames_processed_count);
+ status->u.queue_stats.total_num_processed_byte_cnt =
+ le32_to_cpu(desc->total_processed_byte_count);
+ status->u.queue_stats.late_rx_mpdu_cnt =
+ le32_get_bits(desc->info5, HAL_REO_GET_Q_STATS_STATUS_INFO5_LATE_RCV_MPDU_COUNT);
+ status->u.queue_stats.reorder_hole_cnt =
+ le32_get_bits(desc->info5, HAL_REO_GET_Q_STATS_STATUS_INFO5_HOLE_COUNT);
+ status->u.queue_stats.num_window_2k_jump_cnt =
+ le16_get_bits(desc->info3, HAL_REO_GET_Q_STATS_STATUS_INFO3_WINDOW_JUMP_2K);
+ status->loop_cnt =
+ le16_get_bits(desc->info6,
+ HAL_REO_GET_Q_STATS_STATUS_INFO6_LOOPING_COUNT);
+}
+
+void ath12k_wifi8_hal_reo_flush_queue_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status)
+{
+ struct hal_reo_flush_queue_status *desc =
+ (struct hal_reo_flush_queue_status *)tlv->value;
+
+ ath12k_wifi8_hal_reo_status_hdr_parse(&desc->hdr, status);
+ status->u.flush_queue.err_detected =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_QUEUE_INFO0_ERR_DETECTED);
+}
+
+void
+ath12k_wifi8_hal_reo_flush_cache_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status)
+{
+ struct ath12k_hal *hal = &ab->hal;
+ struct hal_reo_flush_cache_status *desc =
+ (struct hal_reo_flush_cache_status *)tlv->value;
+
+ ath12k_wifi8_hal_reo_status_hdr_parse(&desc->hdr, status);
+
+ status->u.flush_cache.err_detected =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_CACHE_STATUS_INFO0_IS_ERR);
+ status->u.flush_cache.err_code =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_CACHE_STATUS_INFO0_BLOCK_ERR_CODE);
+ 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 =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_STATUS_HIT);
+
+ status->u.flush_cache.cache_controller_flush_status_desc_type =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_DESC_TYPE);
+ status->u.flush_cache.cache_controller_flush_status_client_id =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_CLIENT_ID);
+ status->u.flush_cache.cache_controller_flush_status_err =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_ERR);
+ status->u.flush_cache.cache_controller_flush_status_cnt =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_CACHE_STATUS_INFO0_FLUSH_COUNT);
+}
+
+void ath12k_wifi8_hal_reo_unblk_cache_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status)
+{
+ struct ath12k_hal *hal = &ab->hal;
+ struct hal_reo_unblock_cache_status *desc =
+ (struct hal_reo_unblock_cache_status *)tlv->value;
+
+ ath12k_wifi8_hal_reo_status_hdr_parse(&desc->hdr, status);
+
+ status->u.unblock_cache.err_detected =
+ le32_get_bits(desc->info0,
+ HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_IS_ERR);
+ status->u.unblock_cache.unblock_type =
+ le32_get_bits(desc->info0,
+ HAL_REO_UNBLOCK_CACHE_STATUS_INFO0_TYPE);
+
+ if (!status->u.unblock_cache.err_detected &&
+ status->u.unblock_cache.unblock_type ==
+ HAL_REO_STATUS_UNBLOCK_BLOCKING_RESOURCE)
+ hal->avail_blk_resource &= ~BIT(hal->current_blk_index);
+}
+
+void
+ath12k_wifi8_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status)
+{
+ struct hal_reo_flush_timeout_list_status *desc =
+ (struct hal_reo_flush_timeout_list_status *)tlv->value;
+
+ ath12k_wifi8_hal_reo_status_hdr_parse(&desc->hdr, status);
+
+ status->u.timeout_list.err_detected =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_IS_ERR);
+ status->u.timeout_list.list_empty =
+ le32_get_bits(desc->info0,
+ HAL_REO_FLUSH_TIMEOUT_STATUS_INFO0_LIST_EMPTY);
+
+ status->u.timeout_list.release_desc_cnt =
+ le32_get_bits(desc->info1,
+ HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_REL_DESC_COUNT);
+ status->u.timeout_list.fwd_buf_cnt =
+ le32_get_bits(desc->info1,
+ HAL_REO_FLUSH_TIMEOUT_STATUS_INFO1_FWD_BUF_COUNT);
+}
+
+void
+ath12k_wifi8_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status)
+{
+ struct hal_reo_desc_thresh_reached_status *desc =
+ (struct hal_reo_desc_thresh_reached_status *)tlv->value;
+
+ ath12k_wifi8_hal_reo_status_hdr_parse(&desc->hdr, status);
+
+ status->u.desc_thresh_reached.threshold_idx =
+ le32_get_bits(desc->info0,
+ HAL_REO_DESC_THRESH_STATUS_INFO0_THRESH_INDEX);
+
+ status->u.desc_thresh_reached.link_desc_counter0 =
+ le32_get_bits(desc->info1,
+ HAL_REO_DESC_THRESH_STATUS_INFO1_LINK_DESC_COUNTER0);
+
+ status->u.desc_thresh_reached.link_desc_counter1 =
+ le32_get_bits(desc->info2,
+ HAL_REO_DESC_THRESH_STATUS_INFO2_LINK_DESC_COUNTER1);
+
+ status->u.desc_thresh_reached.link_desc_counter2 =
+ le32_get_bits(desc->info3,
+ HAL_REO_DESC_THRESH_STATUS_INFO3_LINK_DESC_COUNTER2);
+
+ status->u.desc_thresh_reached.link_desc_counter_sum =
+ le32_get_bits(desc->info4,
+ HAL_REO_DESC_THRESH_STATUS_INFO4_LINK_DESC_COUNTER_SUM);
+}
+
+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)
+{
+ struct hal_reo_status_hdr *desc =
+ (struct hal_reo_status_hdr *)tlv->value;
+
+ ath12k_wifi8_hal_reo_status_hdr_parse(desc, status);
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
index bb97652713a2..d61ca0823b5f 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
@@ -48,22 +48,24 @@
#define HAL_REO_CMD_UPD1_ALDC GENMASK(18, 17)
#define HAL_REO_CMD_UPD1_DIS_DUP_DETECTION BIT(19)
#define HAL_REO_CMD_UPD1_SOFT_REORDER_EN BIT(20)
-#define HAL_REO_CMD_UPD1_AC GENMASK(22, 21)
-#define HAL_REO_CMD_UPD1_BAR BIT(23)
-#define HAL_REO_CMD_UPD1_RETRY BIT(24)
-#define HAL_REO_CMD_UPD1_CHECK_2K_MODE BIT(25)
-#define HAL_REO_CMD_UPD1_OOR_MODE BIT(26)
-#define HAL_REO_CMD_UPD1_PN_CHECK BIT(27)
-#define HAL_REO_CMD_UPD1_EVEN_PN BIT(28)
-#define HAL_REO_CMD_UPD1_UNEVEN_PN BIT(29)
-#define HAL_REO_CMD_UPD1_PN_HANDLE_ENABLE BIT(30)
-#define HAL_REO_CMD_UPD1_IGNORE_AMPDU_FLG BIT(31)
+#define HAL_REO_CMD_UPD1_LL_TIMER_ID GENMASK(24, 21)
+#define HAL_REO_CMD_UPD1_BAR BIT(25)
+#define HAL_REO_CMD_UPD1_RETRY BIT(26)
+#define HAL_REO_CMD_UPD1_CHECK_2K_MODE BIT(27)
+#define HAL_REO_CMD_UPD1_OOR_MODE BIT(28)
+#define HAL_REO_CMD_UPD1_PN_CHECK BIT(29)
+#define HAL_REO_CMD_UPD1_EVEN_PN BIT(30)
+#define HAL_REO_CMD_UPD1_UNEVEN_PN BIT(31)
/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO2_* fields */
-#define HAL_REO_CMD_UPD2_SVLD BIT(10)
-#define HAL_REO_CMD_UPD2_SSN GENMASK(22, 11)
-#define HAL_REO_CMD_UPD2_SEQ_2K_ERR BIT(23)
-#define HAL_REO_CMD_UPD2_PN_ERR BIT(24)
+#define HAL_REO_CMD_UPD2_PN_HANDLE_ENABLE BIT(0)
+#define HAL_REO_CMD_UPD2_IGNORE_AMPDU_FLG BIT(1)
+#define HAL_REO_CMD_UPD2_SVLD BIT(14)
+#define HAL_REO_CMD_UPD2_SSN GENMASK(26, 15)
+#define HAL_REO_CMD_UPD2_SEQ_2K_ERR BIT(27)
+#define HAL_REO_CMD_UPD2_PN_ERR BIT(28)
+#define HAL_REO_CMD_UPD2_PN_VALID BIT(29)
+#define HAL_REO_CMD_UPD2_FLUSH_FROM_CACHE BIT(30)
#define HAL_RX_MPDU_ERR_FCS BIT(0)
#define HAL_RX_MPDU_ERR_DECRYPT BIT(1)
@@ -82,5 +84,50 @@
/* 8 buffers for max-size SG MPDU + 1 entry to confirm termination */
#define HAL_REO_SG_TERMINATION_MIN_ENTRIES 9
+struct ath12k_hal_rx_cmd_ring_param {
+ u32 mac_addr_31_0;
+ u32 mac_addr_47_32:16,
+ is_mcast:1,
+ is_mec:1,
+ ad1_match:1,
+ link_id:3,
+ reserved_0:10;
+ u32 meta_data_0;
+ u8 cmd_num:4,
+ reserved:4;
+ u8 hw_link_bitmap;
+};
+
+struct hal_tlv_64_hdr;
+struct hal_reo_status;
+
+int
+ath12k_wifi8_hal_invalidate_rx_cache_cmd_send(struct ath12k_base *ab,
+ struct hal_srng *srng,
+ struct ath12k_hal_rx_cmd_ring_param *param);
+int ath12k_wifi8_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd);
void ath12k_wifi8_hal_reo_hw_setup(struct ath12k_base *ab);
+void ath12k_wifi8_hal_reo_status_queue_stats(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status);
+void ath12k_wifi8_hal_reo_flush_queue_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status);
+void ath12k_wifi8_hal_reo_flush_cache_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status);
+void ath12k_wifi8_hal_reo_unblk_cache_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status);
+void ath12k_wifi8_hal_reo_flush_timeout_list_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status);
+void ath12k_wifi8_hal_reo_desc_thresh_reached_status(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status);
+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);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_tx.h b/drivers/net/wireless/ath/ath12k/wifi8/hal_tx.h
index ae4e32448027..594b5c544fb6 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_tx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_tx.h
@@ -112,4 +112,13 @@ int ath12k_wifi8_hal_tx_sam_cmd_send(struct ath12k_base *ab,
enum hal_tlv_tag_be type,
int id, bool clear_all);
+int
+ath12k_wifi8_hal_invalidate_tx_cache_cmd_send(struct ath12k_base *ab,
+ struct hal_srng *srng,
+ struct ath12k_hal_tx_cmd_ring_param *param);
+int ath12k_wifi8_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd);
+void ath12k_wifi8_hal_tx_set_dscp_tid_map(struct ath12k_base *ab, int id);
+
#endif /* ATH12K_HAL_TX_H */
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 02/13] wifi: ath12k: ng: add high-priority REO command ring
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 01/13] wifi: ath12k: ng: add REO command and status support Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 03/13] wifi: ath12k: ng: allocate REO command context before submission Pradeep Kumar Chitrapu
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
REO commands currently share one ring, so latency-sensitive queue
statistics and update requests can wait behind normal command traffic.
Wi-Fi 8 hardware provides a second REO command ring for priority traffic.
Represent it as ring index 1 of the existing HAL_REO_CMD type, allocate
and initialize it in the Wi-Fi 8 datapath, and expose a separate
high-priority send callback. Reserve a distinct command-number range so
completions from both command rings remain unambiguous.
The existing REO command ring and common send callback are unchanged.
Only Wi-Fi 8 installs the high-priority callback and allocates the
additional ring.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/dp_rx.h | 4 +
drivers/net/wireless/ath/ath12k/wifi8/dp.c | 2 +
drivers/net/wireless/ath/ath12k/wifi8/dp.h | 1 +
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c | 109 ++++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h | 13 +++
drivers/net/wireless/ath/ath12k/wifi8/hal.c | 13 ++-
drivers/net/wireless/ath/ath12k/wifi8/hal.h | 3 +
7 files changed, 142 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h
index d369d68620ed..3a369dfc8ea5 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.h
@@ -11,6 +11,8 @@
#define DP_MAX_NWIFI_HDR_LEN 30
+struct hal_reo_status;
+
struct ath12k_reoq_buf {
void *vaddr;
dma_addr_t paddr_aligned;
@@ -61,6 +63,8 @@ struct ath12k_dp_rx_reo_cmd {
int cmd_num;
void (*handler)(struct ath12k_dp *dp, void *ctx,
enum hal_reo_cmd_status status);
+ void (*status_handler)(struct ath12k_dp *dp, void *ctx,
+ struct hal_reo_status *status);
};
#define ATH12K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ)
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp.c b/drivers/net/wireless/ath/ath12k/wifi8/dp.c
index ff44b8be9534..dee73473cea9 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp.c
@@ -245,6 +245,8 @@ static int ath12k_wifi8_dp_umac_init(struct ath12k_dp *dp)
INIT_LIST_HEAD(&dp->reo_cmd_list);
INIT_LIST_HEAD(&dp->reo_cmd_cache_flush_list);
INIT_LIST_HEAD(&dp->reo_cmd_update_rx_queue_list);
+ spin_lock_init(&dp->reo_cmd_lock);
+ spin_lock_init(&dp->reo_rxq_flush_lock);
INIT_LIST_HEAD(&dp->tqm_cmd_list);
spin_lock_init(&dp->tqm_cmd_lock);
atomic_set(&dp->tqm_cmd_num, 0);
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp.h b/drivers/net/wireless/ath/ath12k/wifi8/dp.h
index 4b773dca0483..3d1ce8f31ee8 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp.h
@@ -42,6 +42,7 @@ struct ath12k_dp_wifi8 {
struct dp_srng tx_exception;
struct dp_srng tcl_cmd_ring;
struct dp_srng tcl_status_ring;
+ struct dp_srng reo_high_prio_cmd_ring;
struct dp_rxdma_ring wbm_refill_ring[DP_WBM_REFILL_RING_MAX];
struct dp_rxdma_ring wbm_idle_ring;
struct dp_srng tqm_cmd_ring;
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
index ca82f9ac0e44..0eea810f68fe 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
@@ -15,6 +15,8 @@
#include "hw.h"
#include "../hal.h"
+#define ATH12K_WIFI8_REO_CMD_HIGHPRI_START_NUM (DP_REO_CMD_RING_SIZE + 1)
+
/* Wi-Fi 8 uses cookie-conversion: the chip writes the SW descriptor VA
* directly into buf_addr_info[63:0] of the REO destination ring entry.
* info0 holds VA[31:0], info1[7:0] holds VA[39:32].
@@ -48,6 +50,99 @@ ath12k_wifi8_get_sw_desc(struct ath12k_dp *dp, const struct hal_reo_dest_ring *d
return ath12k_dp_get_rx_desc(dp, cookie);
}
+static int ath12k_wifi8_dp_reo_cmd_send_ring(struct ath12k_base *ab,
+ struct hal_srng *cmd_ring,
+ void *data, size_t len,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd,
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ struct hal_reo_status *status))
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp_rx_reo_cmd *dp_cmd;
+ int cmd_num;
+ struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
+ struct ath12k_base *central_ab = central_dp->ab;
+
+ if (test_bit(ATH12K_FLAG_CRASH_FLUSH, ¢ral_ab->dev_flags) ||
+ test_bit(ATH12K_FLAG_RECOVERY, ¢ral_ab->dev_flags))
+ return -ESHUTDOWN;
+
+ if (!cb) {
+ dp_cmd = NULL;
+ } else {
+ if (WARN_ON(len > sizeof(dp_cmd->data)))
+ return -EINVAL;
+
+ dp_cmd = kzalloc_obj(*dp_cmd, GFP_ATOMIC);
+ if (!dp_cmd)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&dp_cmd->list);
+ memcpy(&dp_cmd->data, data, len);
+ dp_cmd->status_handler = cb;
+ }
+
+ cmd_num = ath12k_wifi8_hal_reo_cmd_send(central_ab, cmd_ring, type, cmd);
+ if (cmd_num < 0) {
+ kfree(dp_cmd);
+ return cmd_num;
+ }
+
+ if (cmd_num == 0) {
+ kfree(dp_cmd);
+ return -EINVAL;
+ }
+
+ if (!dp_cmd)
+ return 0;
+
+ dp_cmd->cmd_num = cmd_num;
+
+ spin_lock_bh(¢ral_dp->reo_cmd_lock);
+ list_add_tail(&dp_cmd->list, ¢ral_dp->reo_cmd_list);
+ spin_unlock_bh(¢ral_dp->reo_cmd_lock);
+
+ return 0;
+}
+
+int ath12k_wifi8_dp_reo_cmd_send(struct ath12k_base *ab,
+ void *data, size_t len,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd,
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ struct hal_reo_status *status))
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
+ struct hal_srng *cmd_ring;
+
+ cmd_ring = ¢ral_dp->ab->hal.srng_list[central_dp->reo_cmd_ring.ring_id];
+
+ return ath12k_wifi8_dp_reo_cmd_send_ring(ab, cmd_ring, data, len,
+ type, cmd, cb);
+}
+
+int ath12k_wifi8_dp_reo_cmd_send_highprio(struct ath12k_base *ab,
+ void *data, size_t len,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd,
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ struct hal_reo_status *status))
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
+ struct ath12k_dp_wifi8 *dp_wifi8 = ath12k_get_dp_wifi8(central_dp);
+ struct hal_srng *cmd_ring;
+ u32 ring_id;
+
+ ring_id = dp_wifi8->reo_high_prio_cmd_ring.ring_id;
+ cmd_ring = ¢ral_dp->ab->hal.srng_list[ring_id];
+
+ return ath12k_wifi8_dp_reo_cmd_send_ring(ab, cmd_ring, data, len,
+ type, cmd, cb);
+}
+
/**
* ath12k_wifi8_rx_spd_buf_alloc - allocate per-ring SPD scratch-pad arrays
* @dp_hw_grp_wifi8: Wi-Fi 8 hardware-group private data
@@ -915,6 +1010,7 @@ int ath12k_wifi8_dp_rx_ring_setup(struct ath12k_base *ab)
{
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_dp_wifi8 *dp_wifi8 = ath12k_get_dp_wifi8(dp);
+ struct hal_srng *srng;
int i, ret;
ret = ath12k_dp_rx_pdev_reo_setup(ab);
@@ -949,6 +1045,17 @@ int ath12k_wifi8_dp_rx_ring_setup(struct ath12k_base *ab)
ath12k_wifi8_dp_wbm_idle_ring_buf_setup(ab, &dp_wifi8->wbm_idle_ring);
+ ret = ath12k_dp_srng_setup(ab, &dp_wifi8->reo_high_prio_cmd_ring,
+ HAL_REO_CMD, 1, 0, DP_REO_CMD_RING_SIZE);
+ if (ret) {
+ ath12k_warn(ab, "failed to set up reo_high_prio_cmd ring :%d\n", ret);
+ goto err_wbm_refill_cleanup;
+ }
+
+ srng = &ab->hal.srng_list[dp_wifi8->reo_high_prio_cmd_ring.ring_id];
+ ath12k_wifi8_hal_reo_init_cmd_ring_offset(ab, srng,
+ ATH12K_WIFI8_REO_CMD_HIGHPRI_START_NUM);
+
return 0;
err_wbm_refill_cleanup:
@@ -964,6 +1071,8 @@ int ath12k_wifi8_dp_rx_ring_free(struct ath12k_base *ab)
struct ath12k_dp_wifi8 *dp_wifi8 = ath12k_get_dp_wifi8(dp);
int i;
+ ath12k_dp_srng_cleanup(ab, &dp_wifi8->reo_high_prio_cmd_ring);
+
for (i = 0; i < DP_WBM_REFILL_RING_MAX; i++)
ath12k_dp_srng_cleanup(ab, &dp_wifi8->wbm_refill_ring[i].refill_buf_ring);
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
index 9ef1474b1a7e..a05ab2f4495c 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
@@ -11,6 +11,7 @@
#include "hal_desc.h"
struct ath12k_dp_hw_group_wifi8;
+struct hal_reo_status;
struct hal_rx_mpdu_desc_info {
union {
@@ -146,6 +147,18 @@ int ath12k_wifi8_dp_pdev_alloc(struct ath12k_base *ab);
void ath12k_wifi8_dp_pdev_free(struct ath12k_base *ab);
void ath12k_wifi8_dp_wbm_idle_ring_buf_setup(struct ath12k_base *ab,
struct dp_rxdma_ring *rx_ring);
+int ath12k_wifi8_dp_reo_cmd_send(struct ath12k_base *ab,
+ void *data, size_t len,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd,
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ struct hal_reo_status *status));
+int ath12k_wifi8_dp_reo_cmd_send_highprio(struct ath12k_base *ab,
+ void *data, size_t len,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd,
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ struct hal_reo_status *status));
int ath12k_wifi8_dp_rx_ring_setup(struct ath12k_base *ab);
int ath12k_wifi8_dp_rx_ring_free(struct ath12k_base *ab);
int ath12k_wifi8_dp_rxdma_ring_sel_config_qcn9625(struct ath12k_base *ab);
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal.c b/drivers/net/wireless/ath/ath12k/wifi8/hal.c
index 036c04cbbf16..af51ee3cd7e7 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal.c
@@ -565,13 +565,14 @@ void ath12k_wifi8_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc,
le32_encode_bits(cookie, BUFFER_ADDR_INFO1_SW_COOKIE);
}
-void ath12k_wifi8_hal_reo_init_cmd_ring(struct ath12k_base *ab,
- struct hal_srng *srng)
+void ath12k_wifi8_hal_reo_init_cmd_ring_offset(struct ath12k_base *ab,
+ struct hal_srng *srng,
+ u16 cmd_num)
{
struct hal_srng_params params;
struct hal_tlv_64_hdr *tlv;
struct hal_reo_get_queue_stats *desc;
- int i, cmd_num = 1;
+ int i;
int entry_size;
u8 *entry;
@@ -589,6 +590,12 @@ void ath12k_wifi8_hal_reo_init_cmd_ring(struct ath12k_base *ab,
}
}
+void ath12k_wifi8_hal_reo_init_cmd_ring(struct ath12k_base *ab,
+ struct hal_srng *srng)
+{
+ ath12k_wifi8_hal_reo_init_cmd_ring_offset(ab, srng, 1);
+}
+
#define HAL_RDI_MAPPING_MAX 32
int ath12k_wifi8_hal_get_rdi_source_cfg(struct ath12k_base *ab, int source)
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal.h b/drivers/net/wireless/ath/ath12k/wifi8/hal.h
index d30ee1242122..fc5df78be051 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal.h
@@ -1045,6 +1045,9 @@ void ath12k_wifi8_hal_set_link_desc_addr(struct hal_wbm_link_desc *desc,
u32 cookie, dma_addr_t paddr, u8 rbm);
void ath12k_wifi8_hal_reo_init_cmd_ring(struct ath12k_base *ab,
struct hal_srng *srng);
+void ath12k_wifi8_hal_reo_init_cmd_ring_offset(struct ath12k_base *ab,
+ struct hal_srng *srng,
+ u16 cmd_num);
int ath12k_wifi8_hal_get_rdi_source_cfg(struct ath12k_base *ab, int source);
void ath12k_wifi8_hal_hw_ase_init(struct ath12k_base *ab,
struct ath12k_hal_ast_param *ast_param);
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 03/13] wifi: ath12k: ng: allocate REO command context before submission
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 01/13] wifi: ath12k: ng: add REO command and status support Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 02/13] wifi: ath12k: ng: add high-priority REO command ring Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 04/13] wifi: ath12k: ng: refactor REO command framework for extensibility Pradeep Kumar Chitrapu
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
The Wi-Fi 7 REO send path submits a hardware command before allocating
the software entry used to match its completion. If the atomic
allocation then fails, the function returns -ENOMEM even though the
command is already in flight. The completion cannot be matched to a
callback, and callers may retry an operation whose first command was
accepted by hardware. This can skip RX TID cleanup or issue duplicate
queue operations under memory pressure.
Allocate and initialize the pending-command context before writing the
REO ring. Free it when hardware submission fails or returns an invalid
command number. Commands without callbacks continue to avoid the
allocation.
This changes only the Wi-Fi 7 command sender; the Wi-Fi 8 ring path
already allocates callback state before submission. Found during code
review.
Fixes: 52c555680bae ("wifi: ath12k: Move arch specific rx tid and related functions to wifi7 directory")
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 35 +++++++++++++++++----------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
index a41049e7b425..d3ed2134818a 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
@@ -148,30 +148,39 @@ int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab,
struct hal_srng *cmd_ring;
int cmd_num;
+ if (!cb) {
+ dp_cmd = NULL;
+ } else {
+ /* 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 = kzalloc_obj(*dp_cmd, GFP_ATOMIC);
+ if (!dp_cmd)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&dp_cmd->list);
+ memcpy(&dp_cmd->data, rx_tid, sizeof(*rx_tid));
+ }
+
cmd_ring = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id];
cmd_num = ath12k_wifi7_hal_reo_cmd_send(ab, cmd_ring, type, cmd);
/* cmd_num should start from 1, during failure return the error code */
- if (cmd_num < 0)
+ if (cmd_num < 0) {
+ kfree(dp_cmd);
return cmd_num;
+ }
/* reo cmd ring descriptors has cmd_num starting from 1 */
- if (cmd_num == 0)
+ if (cmd_num == 0) {
+ kfree(dp_cmd);
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 = kzalloc_obj(*dp_cmd, GFP_ATOMIC);
+ }
if (!dp_cmd)
- return -ENOMEM;
+ return 0;
- memcpy(&dp_cmd->data, rx_tid, sizeof(*rx_tid));
dp_cmd->cmd_num = cmd_num;
dp_cmd->handler = cb;
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 04/13] wifi: ath12k: ng: refactor REO command framework for extensibility
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (2 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 03/13] wifi: ath12k: ng: allocate REO command context before submission Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 05/13] wifi: ath12k: ng: log successful RX TID queue updates Pradeep Kumar Chitrapu
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
The REO command framework passes an RX TID context to completion
callbacks and exposes only a command-status enum. This prevents callbacks
from inspecting command-specific hardware responses and prevents other
context types from using the same pending-command path.
Pass the complete struct hal_reo_status to callbacks and consolidate the
status container shared by Wi-Fi 7 and Wi-Fi 8 into common hal.h. During
command-list teardown, synthesize a HAL_REO_CMD_DRAIN status so existing
callbacks retain ownership of their context cleanup.
Generalize the send API to accept an opaque pointer and length, and copy
the context into a fixed-size union in the pending command. Validate the
copy size and adapt existing Wi-Fi 7 callers and Wi-Fi 8 bookkeeping.
Command encoding, ring selection, and hardware programming are unchanged.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/dp.h | 11 ++--
drivers/net/wireless/ath/ath12k/dp_rx.c | 30 ++++++---
drivers/net/wireless/ath/ath12k/dp_rx.h | 12 ++--
drivers/net/wireless/ath/ath12k/hal.h | 87 +++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 25 ++++---
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 4 +-
drivers/net/wireless/ath/ath12k/wifi7/hal.h | 94 +++------------------------
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c | 6 +-
drivers/net/wireless/ath/ath12k/wifi8/hal.h | 87 -------------------------
9 files changed, 149 insertions(+), 207 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 6bd7ce41fc8d..9dba68f78808 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -27,6 +27,7 @@ struct ath12k_dp_vif;
struct ath12k_link_sta;
struct ath12k_dp_tx_msdu_info;
struct ath12k_dp_skb_ctrl;
+struct hal_reo_status;
#define DP_MON_PURGE_TIMEOUT_MS 100
#define DP_MON_SERVICE_BUDGET 128
@@ -437,11 +438,11 @@ struct ath12k_dp_arch_ops {
u32 (*tx_get_vdev_bank_config)(struct ath12k_base *ab,
struct ath12k_vif *ahvif);
int (*reo_cmd_send)(struct ath12k_base *ab,
- struct ath12k_dp_rx_tid_rxq *rx_tid,
+ void *data, size_t len,
enum hal_reo_cmd_type type,
struct ath12k_hal_reo_cmd *cmd,
void (*cb)(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status));
+ struct hal_reo_status *status));
void (*setup_pn_check_reo_cmd)(struct ath12k_hal_reo_cmd *cmd,
struct ath12k_dp_rx_tid *rx_tid,
u32 cipher, enum set_key_cmd key_cmd);
@@ -660,13 +661,13 @@ struct ath12k_dp {
};
static inline int ath12k_dp_arch_reo_cmd_send(struct ath12k_dp *dp,
- struct ath12k_dp_rx_tid_rxq *rx_tid,
+ void *data, size_t len,
enum hal_reo_cmd_type type,
struct ath12k_hal_reo_cmd *cmd,
void (*cb)(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status))
+ struct hal_reo_status *status))
{
- return dp->ops->reo_cmd_send(dp->ab, rx_tid, type, cmd, cb);
+ return dp->ops->reo_cmd_send(dp->ab, data, len, type, cmd, cb);
}
static inline
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index 1773d44a4cb4..47a7ec58446a 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -392,8 +392,11 @@ void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab)
spin_lock_bh(&dp->reo_cmd_lock);
list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) {
+ struct hal_reo_status drain_status = {};
+
list_del(&cmd->list);
- ath12k_dp_rx_tid_cleanup(ab, &cmd->data.qbuf);
+ drain_status.uniform_hdr.cmd_status = HAL_REO_CMD_DRAIN;
+ cmd->handler(dp, &cmd->u.data, &drain_status);
kfree(cmd);
}
spin_unlock_bh(&dp->reo_cmd_lock);
@@ -401,14 +404,20 @@ void ath12k_dp_rx_reo_cmd_list_cleanup(struct ath12k_base *ab)
EXPORT_SYMBOL(ath12k_dp_rx_reo_cmd_list_cleanup);
void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status)
+ struct hal_reo_status *status)
{
struct ath12k_dp_rx_tid_rxq *rx_tid = ctx;
+ enum hal_reo_cmd_status cmd_status;
+
+ if (!status || status->uniform_hdr.cmd_status == HAL_REO_CMD_DRAIN)
+ goto free_desc;
- if (status != HAL_REO_CMD_SUCCESS)
+ cmd_status = status->uniform_hdr.cmd_status;
+ if (cmd_status != HAL_REO_CMD_SUCCESS)
ath12k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n",
- rx_tid->tid, status);
+ rx_tid->tid, cmd_status);
+free_desc:
ath12k_dp_rx_tid_cleanup(dp->ab, &rx_tid->qbuf);
}
EXPORT_SYMBOL(ath12k_dp_reo_cmd_free);
@@ -444,18 +453,22 @@ void ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(struct ath12k_dp *dp)
EXPORT_SYMBOL(ath12k_dp_rx_process_reo_cmd_update_rx_queue_list);
void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status)
+ struct hal_reo_status *status)
{
struct ath12k_base *ab = dp->ab;
struct ath12k_dp_rx_tid_rxq *rx_tid = ctx;
struct ath12k_dp_rx_reo_cache_flush_elem *elem, *tmp;
+ enum hal_reo_cmd_status cmd_status;
- if (status == HAL_REO_CMD_DRAIN) {
+ if (!status || status->uniform_hdr.cmd_status == HAL_REO_CMD_DRAIN)
goto free_desc;
- } else if (status != HAL_REO_CMD_SUCCESS) {
+
+ cmd_status = status->uniform_hdr.cmd_status;
+
+ if (cmd_status != HAL_REO_CMD_SUCCESS) {
/* Shouldn't happen! Cleanup in case of other failure? */
ath12k_warn(ab, "failed to delete rx tid %d hw descriptor %d\n",
- rx_tid->tid, status);
+ rx_tid->tid, cmd_status);
return;
}
@@ -832,6 +845,7 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
ath12k_dp_arch_setup_pn_check_reo_cmd(dp, &cmd, rx_tid, key->cipher,
key_cmd);
ret = ath12k_dp_arch_reo_cmd_send(dp, &rx_tid_rxq,
+ sizeof(rx_tid_rxq),
HAL_REO_CMD_UPDATE_RX_QUEUE,
&cmd, NULL);
if (ret) {
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h
index 3a369dfc8ea5..f523ac48747f 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.h
@@ -59,12 +59,12 @@ struct dp_reo_update_rx_queue_elem {
struct ath12k_dp_rx_reo_cmd {
struct list_head list;
- struct ath12k_dp_rx_tid_rxq data;
+ union {
+ struct ath12k_dp_rx_tid_rxq data;
+ } u;
int cmd_num;
void (*handler)(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status);
- void (*status_handler)(struct ath12k_dp *dp, void *ctx,
- struct hal_reo_status *status);
+ struct hal_reo_status *status);
};
#define ATH12K_DP_RX_FRAGMENT_TIMEOUT_MS (2 * HZ)
@@ -284,9 +284,9 @@ bool ath12k_dp_rx_h_rate_common(struct ath12k_pdev_dp *dp_pdev,
struct sk_buff *ath12k_dp_rx_get_msdu_last_buf(struct sk_buff_head *msdu_list,
struct sk_buff *first);
void ath12k_dp_reo_cmd_free(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status);
+ struct hal_reo_status *status);
void ath12k_dp_rx_tid_del_func(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status);
+ struct hal_reo_status *status);
void ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(struct ath12k_dp *dp);
void ath12k_dp_init_rx_tid_rxq(struct ath12k_dp_rx_tid_rxq *rx_tid_rxq,
struct ath12k_dp_rx_tid *rx_tid,
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index f175b5361080..9c0d1dfac8d3 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1169,6 +1169,93 @@ struct hal_reo_status_header {
u32 timestamp;
};
+struct hal_reo_status_queue_stats {
+ u16 ssn;
+ u16 curr_idx;
+ u32 pn[4];
+ u32 last_rx_queue_ts;
+ u32 last_rx_dequeue_ts;
+ u32 rx_bitmap[9];
+ u32 curr_mpdu_cnt;
+ u32 curr_msdu_cnt;
+ u16 fwd_due_to_bar_cnt;
+ u16 dup_cnt;
+ u32 frames_in_order_cnt;
+ u32 num_mpdu_processed_cnt;
+ u32 num_msdu_processed_cnt;
+ u32 total_num_processed_byte_cnt;
+ u32 late_rx_mpdu_cnt;
+ u32 reorder_hole_cnt;
+ u8 timeout_cnt;
+ u8 bar_rx_cnt;
+ u8 num_window_2k_jump_cnt;
+};
+
+struct hal_reo_status_flush_queue {
+ bool err_detected;
+};
+
+enum hal_reo_status_flush_cache_err_code {
+ HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_SUCCESS,
+ HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_IN_USE,
+ HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_NOT_FOUND,
+};
+
+struct hal_reo_status_flush_cache {
+ bool err_detected;
+ enum hal_reo_status_flush_cache_err_code err_code;
+ bool cache_controller_flush_status_hit;
+ u8 cache_controller_flush_status_desc_type;
+ u8 cache_controller_flush_status_client_id;
+ u8 cache_controller_flush_status_err;
+ u8 cache_controller_flush_status_cnt;
+};
+
+enum hal_reo_status_unblock_cache_type {
+ HAL_REO_STATUS_UNBLOCK_BLOCKING_RESOURCE,
+ HAL_REO_STATUS_UNBLOCK_ENTIRE_CACHE_USAGE,
+};
+
+struct hal_reo_status_unblock_cache {
+ bool err_detected;
+ enum hal_reo_status_unblock_cache_type unblock_type;
+};
+
+struct hal_reo_status_flush_timeout_list {
+ bool err_detected;
+ bool list_empty;
+ u16 release_desc_cnt;
+ u16 fwd_buf_cnt;
+};
+
+enum hal_reo_threshold_idx {
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER0,
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER1,
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER2,
+ HAL_REO_THRESHOLD_IDX_DESC_COUNTER_SUM,
+};
+
+struct hal_reo_status_desc_thresh_reached {
+ enum hal_reo_threshold_idx threshold_idx;
+ u32 link_desc_counter0;
+ u32 link_desc_counter1;
+ u32 link_desc_counter2;
+ u32 link_desc_counter_sum;
+};
+
+struct hal_reo_status {
+ struct hal_reo_status_header uniform_hdr;
+ u8 loop_cnt;
+ union {
+ struct hal_reo_status_queue_stats queue_stats;
+ struct hal_reo_status_flush_queue flush_queue;
+ struct hal_reo_status_flush_cache flush_cache;
+ struct hal_reo_status_unblock_cache unblock_cache;
+ struct hal_reo_status_flush_timeout_list timeout_list;
+ struct hal_reo_status_desc_thresh_reached desc_thresh_reached;
+ } u;
+};
+
struct ath12k_hw_hal_params {
u8 rx_buf_rbm;
u32 wbm2sw_cc_enable;
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
index d3ed2134818a..379b33fc8029 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
@@ -137,11 +137,11 @@ int ath12k_wifi7_dp_rx_link_desc_return(struct ath12k_dp *dp,
}
int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab,
- struct ath12k_dp_rx_tid_rxq *rx_tid,
+ void *data, size_t len,
enum hal_reo_cmd_type type,
struct ath12k_hal_reo_cmd *cmd,
void (*cb)(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status))
+ struct hal_reo_status *status))
{
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_dp_rx_reo_cmd *dp_cmd;
@@ -151,6 +151,12 @@ int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab,
if (!cb) {
dp_cmd = NULL;
} else {
+ if (WARN_ON(len > sizeof(dp_cmd->u)))
+ return -EINVAL;
+
+ if (WARN_ON(len && !data))
+ return -EINVAL;
+
/* 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?
@@ -160,12 +166,13 @@ int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab,
return -ENOMEM;
INIT_LIST_HEAD(&dp_cmd->list);
- memcpy(&dp_cmd->data, rx_tid, sizeof(*rx_tid));
+ if (len)
+ memcpy(&dp_cmd->u, data, len);
+ dp_cmd->handler = cb;
}
cmd_ring = &ab->hal.srng_list[dp->reo_cmd_ring.ring_id];
cmd_num = ath12k_wifi7_hal_reo_cmd_send(ab, cmd_ring, type, cmd);
-
/* cmd_num should start from 1, during failure return the error code */
if (cmd_num < 0) {
kfree(dp_cmd);
@@ -182,7 +189,6 @@ int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab,
return 0;
dp_cmd->cmd_num = cmd_num;
- dp_cmd->handler = cb;
spin_lock_bh(&dp->reo_cmd_lock);
list_add_tail(&dp_cmd->list, &dp->reo_cmd_list);
@@ -216,7 +222,7 @@ int ath12k_wifi7_peer_rx_tid_reo_update(struct ath12k_dp *dp,
cmd.upd2 = u32_encode_bits(ssn, HAL_REO_CMD_UPD2_SSN);
}
- ret = ath12k_wifi7_dp_reo_cmd_send(ab, &rx_tid_rxq,
+ ret = ath12k_wifi7_dp_reo_cmd_send(ab, &rx_tid_rxq, sizeof(rx_tid_rxq),
HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd,
NULL);
if (ret) {
@@ -253,7 +259,7 @@ int ath12k_wifi7_dp_reo_cache_flush(struct ath12k_base *ab,
if (rx_tid->tid != HAL_DESC_REO_NON_QOS_TID)
cmd.flag |= HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC;
- ret = ath12k_wifi7_dp_reo_cmd_send(ab, rx_tid,
+ ret = ath12k_wifi7_dp_reo_cmd_send(ab, rx_tid, sizeof(*rx_tid),
HAL_REO_CMD_FLUSH_CACHE,
&cmd, ath12k_dp_reo_cmd_free);
return ret;
@@ -321,7 +327,7 @@ int ath12k_wifi7_dp_rx_tid_delete_handler(struct ath12k_base *ab,
/* Observed flush cache failure, to avoid that set vld bit during delete */
cmd.upd1 |= HAL_REO_CMD_UPD1_VLD;
- return ath12k_wifi7_dp_reo_cmd_send(ab, rx_tid,
+ return ath12k_wifi7_dp_reo_cmd_send(ab, rx_tid, sizeof(*rx_tid),
HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd,
ath12k_dp_rx_tid_del_func);
}
@@ -2302,8 +2308,7 @@ void ath12k_wifi7_dp_rx_process_reo_status(struct ath12k_dp *dp)
spin_unlock_bh(&dp->reo_cmd_lock);
if (found) {
- cmd->handler(dp, (void *)&cmd->data,
- reo_status.uniform_hdr.cmd_status);
+ cmd->handler(dp, &cmd->u.data, &reo_status);
kfree(cmd);
}
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h
index 9d9ffb6f835f..0cc5510ae824 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h
@@ -39,11 +39,11 @@ void ath12k_wifi7_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u1
void ath12k_wifi7_dp_rx_peer_tid_delete(struct ath12k_base *ab,
struct ath12k_dp_link_peer *peer, u8 tid);
int ath12k_wifi7_dp_reo_cmd_send(struct ath12k_base *ab,
- struct ath12k_dp_rx_tid_rxq *rx_tid,
+ void *data, size_t len,
enum hal_reo_cmd_type type,
struct ath12k_hal_reo_cmd *cmd,
void (*cb)(struct ath12k_dp *dp, void *ctx,
- enum hal_reo_cmd_status status));
+ struct hal_reo_status *status));
int ath12k_wifi7_dp_reo_cache_flush(struct ath12k_base *ab,
struct ath12k_dp_rx_tid_rxq *rx_tid);
int ath12k_wifi7_peer_rx_tid_reo_update(struct ath12k_dp *dp,
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal.h b/drivers/net/wireless/ath/ath12k/wifi7/hal.h
index 471b6ec3591c..065392c62263 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal.h
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal.h
@@ -446,92 +446,14 @@
#define HAL_REO_CMD_UPD2_SEQ_2K_ERR BIT(23)
#define HAL_REO_CMD_UPD2_PN_ERR BIT(24)
-struct hal_reo_status_queue_stats {
- u16 ssn;
- u16 curr_idx;
- u32 pn[4];
- u32 last_rx_queue_ts;
- u32 last_rx_dequeue_ts;
- u32 rx_bitmap[8]; /* Bitmap from 0-255 */
- u32 curr_mpdu_cnt;
- u32 curr_msdu_cnt;
- u16 fwd_due_to_bar_cnt;
- u16 dup_cnt;
- u32 frames_in_order_cnt;
- u32 num_mpdu_processed_cnt;
- u32 num_msdu_processed_cnt;
- u32 total_num_processed_byte_cnt;
- u32 late_rx_mpdu_cnt;
- u32 reorder_hole_cnt;
- u8 timeout_cnt;
- u8 bar_rx_cnt;
- u8 num_window_2k_jump_cnt;
-};
-
-struct hal_reo_status_flush_queue {
- bool err_detected;
-};
-
-enum hal_reo_status_flush_cache_err_code {
- HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_SUCCESS,
- HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_IN_USE,
- HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_NOT_FOUND,
-};
-
-struct hal_reo_status_flush_cache {
- bool err_detected;
- enum hal_reo_status_flush_cache_err_code err_code;
- bool cache_controller_flush_status_hit;
- u8 cache_controller_flush_status_desc_type;
- u8 cache_controller_flush_status_client_id;
- u8 cache_controller_flush_status_err;
- u8 cache_controller_flush_status_cnt;
-};
-
-enum hal_reo_status_unblock_cache_type {
- HAL_REO_STATUS_UNBLOCK_BLOCKING_RESOURCE,
- HAL_REO_STATUS_UNBLOCK_ENTIRE_CACHE_USAGE,
-};
-
-struct hal_reo_status_unblock_cache {
- bool err_detected;
- enum hal_reo_status_unblock_cache_type unblock_type;
-};
-
-struct hal_reo_status_flush_timeout_list {
- bool err_detected;
- bool list_empty;
- u16 release_desc_cnt;
- u16 fwd_buf_cnt;
-};
-
-enum hal_reo_threshold_idx {
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER0,
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER1,
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER2,
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER_SUM,
-};
-
-struct hal_reo_status_desc_thresh_reached {
- enum hal_reo_threshold_idx threshold_idx;
- u32 link_desc_counter0;
- u32 link_desc_counter1;
- u32 link_desc_counter2;
- u32 link_desc_counter_sum;
-};
-
-struct hal_reo_status {
- struct hal_reo_status_header uniform_hdr;
- u8 loop_cnt;
- union {
- struct hal_reo_status_queue_stats queue_stats;
- struct hal_reo_status_flush_queue flush_queue;
- struct hal_reo_status_flush_cache flush_cache;
- struct hal_reo_status_unblock_cache unblock_cache;
- struct hal_reo_status_flush_timeout_list timeout_list;
- struct hal_reo_status_desc_thresh_reached desc_thresh_reached;
- } u;
-};
+#define HAL_WIFI7_HASH_ROUTING_RING_TCL 0
+#define HAL_WIFI7_HASH_ROUTING_RING_SW1 1
+#define HAL_WIFI7_HASH_ROUTING_RING_SW2 2
+#define HAL_WIFI7_HASH_ROUTING_RING_SW3 3
+#define HAL_WIFI7_HASH_ROUTING_RING_SW4 4
+#define HAL_WIFI7_HASH_ROUTING_RING_REL 5
+#define HAL_WIFI7_HASH_ROUTING_RING_FW 6
+
int ath12k_wifi7_hal_init(struct ath12k_base *ab);
void ath12k_wifi7_hal_ce_dst_setup(struct ath12k_base *ab,
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
index 0eea810f68fe..b75e65091995 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
@@ -71,7 +71,7 @@ static int ath12k_wifi8_dp_reo_cmd_send_ring(struct ath12k_base *ab,
if (!cb) {
dp_cmd = NULL;
} else {
- if (WARN_ON(len > sizeof(dp_cmd->data)))
+ if (WARN_ON(len > sizeof(dp_cmd->u)))
return -EINVAL;
dp_cmd = kzalloc_obj(*dp_cmd, GFP_ATOMIC);
@@ -79,8 +79,8 @@ static int ath12k_wifi8_dp_reo_cmd_send_ring(struct ath12k_base *ab,
return -ENOMEM;
INIT_LIST_HEAD(&dp_cmd->list);
- memcpy(&dp_cmd->data, data, len);
- dp_cmd->status_handler = cb;
+ memcpy(&dp_cmd->u, data, len);
+ dp_cmd->handler = cb;
}
cmd_num = ath12k_wifi8_hal_reo_cmd_send(central_ab, cmd_ring, type, cmd);
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal.h b/drivers/net/wireless/ath/ath12k/wifi8/hal.h
index fc5df78be051..81bcfd6d0f43 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal.h
@@ -896,93 +896,6 @@ enum ath12k_hal_tx_pkt_ctrl_config {
HAL_TX_PACKET_CONTROL_CONFIG_MEC_NOTIFY_TX_EXCEPTION,
};
-struct hal_reo_status_queue_stats {
- u16 ssn;
- u16 curr_idx;
- u32 pn[4];
- u32 last_rx_queue_ts;
- u32 last_rx_dequeue_ts;
- u32 rx_bitmap[9];
- u32 curr_mpdu_cnt;
- u32 curr_msdu_cnt;
- u16 fwd_due_to_bar_cnt;
- u16 dup_cnt;
- u32 frames_in_order_cnt;
- u32 num_mpdu_processed_cnt;
- u32 num_msdu_processed_cnt;
- u32 total_num_processed_byte_cnt;
- u32 late_rx_mpdu_cnt;
- u32 reorder_hole_cnt;
- u8 timeout_cnt;
- u8 bar_rx_cnt;
- u8 num_window_2k_jump_cnt;
-};
-
-struct hal_reo_status_flush_queue {
- bool err_detected;
-};
-
-enum hal_reo_status_flush_cache_err_code {
- HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_SUCCESS,
- HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_IN_USE,
- HAL_REO_STATUS_FLUSH_CACHE_ERR_CODE_NOT_FOUND,
-};
-
-struct hal_reo_status_flush_cache {
- bool err_detected;
- enum hal_reo_status_flush_cache_err_code err_code;
- bool cache_controller_flush_status_hit;
- u8 cache_controller_flush_status_desc_type;
- u8 cache_controller_flush_status_client_id;
- u8 cache_controller_flush_status_err;
- u8 cache_controller_flush_status_cnt;
-};
-
-enum hal_reo_status_unblock_cache_type {
- HAL_REO_STATUS_UNBLOCK_BLOCKING_RESOURCE,
- HAL_REO_STATUS_UNBLOCK_ENTIRE_CACHE_USAGE,
-};
-
-struct hal_reo_status_unblock_cache {
- bool err_detected;
- enum hal_reo_status_unblock_cache_type unblock_type;
-};
-
-struct hal_reo_status_flush_timeout_list {
- bool err_detected;
- bool list_empty;
- u16 release_desc_cnt;
- u16 fwd_buf_cnt;
-};
-
-enum hal_reo_threshold_idx {
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER0,
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER1,
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER2,
- HAL_REO_THRESHOLD_IDX_DESC_COUNTER_SUM,
-};
-
-struct hal_reo_status_desc_thresh_reached {
- enum hal_reo_threshold_idx threshold_idx;
- u32 link_desc_counter0;
- u32 link_desc_counter1;
- u32 link_desc_counter2;
- u32 link_desc_counter_sum;
-};
-
-struct hal_reo_status {
- struct hal_reo_status_header uniform_hdr;
- u8 loop_cnt;
- union {
- struct hal_reo_status_queue_stats queue_stats;
- struct hal_reo_status_flush_queue flush_queue;
- struct hal_reo_status_flush_cache flush_cache;
- struct hal_reo_status_unblock_cache unblock_cache;
- struct hal_reo_status_flush_timeout_list timeout_list;
- struct hal_reo_status_desc_thresh_reached desc_thresh_reached;
- } u;
-};
-
void ath12k_wifi8_hal_init(struct ath12k_base *ab);
void ath12k_wifi8_hal_ce_dst_setup(struct ath12k_base *ab,
struct hal_srng *srng, int ring_num);
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 05/13] wifi: ath12k: ng: log successful RX TID queue updates
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (3 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 04/13] wifi: ath12k: ng: refactor REO command framework for extensibility Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 06/13] wifi: ath12k: ng: parse 1K REO queue statistics Pradeep Kumar Chitrapu
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
Log the peer, TID, link ID and BA window after a REO update RX
queue command succeeds. The message helps verify the programmed RX
reorder state when debugging aggregation setup.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
index 379b33fc8029..7d196e85f280 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
@@ -233,6 +233,11 @@ int ath12k_wifi7_peer_rx_tid_reo_update(struct ath12k_dp *dp,
rx_tid->ba_win_sz = ba_win_sz;
+ ath12k_dbg(ab, ATH12K_DBG_DP_RX,
+ "rx tid queue update successful for tid: %u, peer_id: %d, peer: %pM, link_id: %u ba_win_sz: %u\n",
+ rx_tid->tid, peer->peer_id, peer->addr, peer->link_id,
+ rx_tid->ba_win_sz);
+
return 0;
}
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 06/13] wifi: ath12k: ng: parse 1K REO queue statistics
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (4 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 05/13] wifi: ath12k: ng: log successful RX TID queue updates Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 07/13] wifi: ath12k: ng: process REO status ring Pradeep Kumar Chitrapu
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
A normal REO queue-statistics status contains the first 288 bits of the
reorder bitmap. For a receive queue with a larger BlockAck window, the
hardware sets a follow-up flag and returns bits 288 through 1023 in a
second status TLV.
Define the 1K queue-statistics status descriptor and decode its 23
additional bitmap words. Extend the common queue status with the PN
encoding, follow-up indication, and wider counters, and store the TLV tag
so a follow-on datapath patch can distinguish both responses for one
command number.
This commit only extends Wi-Fi 8 status representation and parsing. It
does not submit commands or change the Wi-Fi 7 descriptor path.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/hal.h | 15 +++++++++---
drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h | 10 ++++++++
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c | 30 ++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h | 3 +++
4 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index 9c0d1dfac8d3..6534e11a3378 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1173,6 +1173,9 @@ struct hal_reo_status_queue_stats {
u16 ssn;
u16 curr_idx;
u32 pn[4];
+ u8 pn_len;
+ u8 pn_127_48_info;
+ bool to_follow_1k;
u32 last_rx_queue_ts;
u32 last_rx_dequeue_ts;
u32 rx_bitmap[9];
@@ -1186,9 +1189,13 @@ struct hal_reo_status_queue_stats {
u32 total_num_processed_byte_cnt;
u32 late_rx_mpdu_cnt;
u32 reorder_hole_cnt;
- u8 timeout_cnt;
- u8 bar_rx_cnt;
- u8 num_window_2k_jump_cnt;
+ u32 timeout_cnt;
+ u32 bar_rx_cnt;
+ u32 num_window_2k_jump_cnt;
+};
+
+struct hal_reo_status_queue_1k_stats {
+ u32 rx_bitmap[23];
};
struct hal_reo_status_flush_queue {
@@ -1246,8 +1253,10 @@ struct hal_reo_status_desc_thresh_reached {
struct hal_reo_status {
struct hal_reo_status_header uniform_hdr;
u8 loop_cnt;
+ u16 tag;
union {
struct hal_reo_status_queue_stats queue_stats;
+ struct hal_reo_status_queue_1k_stats queue_1k_stats;
struct hal_reo_status_flush_queue flush_queue;
struct hal_reo_status_flush_cache flush_cache;
struct hal_reo_status_unblock_cache unblock_cache;
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h b/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h
index 691c9866522f..e2947dd112ce 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h
@@ -536,6 +536,15 @@ struct hal_reo_get_queue_stats_status {
__le16 info6;
} __packed;
+#define HAL_REO_GET_Q_1K_STATS_STATUS_INFO0_LOOPING_COUNT GENMASK(15, 12)
+
+struct hal_reo_get_queue_1k_stats_status {
+ struct hal_reo_status_hdr hdr;
+ __le32 rx_bitmap1023_288[23];
+ __le16 rsvd0;
+ __le16 info0;
+} __packed;
+
/* REO command TLV tags */
#define HAL_REO_GET_QUEUE_STATS 313
#define HAL_REO_FLUSH_QUEUE 314
@@ -549,6 +558,7 @@ struct hal_reo_get_queue_stats_status {
#define HAL_REO_FLUSH_TIMEOUT_LIST_STATUS 338
#define HAL_REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS 339
#define HAL_REO_UPDATE_RX_REO_QUEUE 371
+#define HAL_REO_GET_QUEUE_1K_STATS_STATUS 451
#define HAL_REO_UPDATE_RX_REO_QUEUE_STATUS 204
#define HAL_REO_FLUSH_QUEUE_INFO0_DESC_ADDR_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 80c2f1202233..d78c178cc70d 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
@@ -470,6 +470,29 @@ ath12k_wifi8_hal_reo_cmd_update_rx_queue(struct hal_tlv_64_hdr *tlv,
return le16_to_cpu(desc->cmd.reo_cmd_number);
}
+void ath12k_wifi8_hal_reo_status_queue_1k_stats(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status)
+{
+ struct hal_reo_get_queue_1k_stats_status *desc =
+ (struct hal_reo_get_queue_1k_stats_status *)tlv->value;
+ u32 *dst = status->u.queue_1k_stats.rx_bitmap;
+ int i;
+
+ status->uniform_hdr.cmd_num = le16_to_cpu(desc->hdr.reo_status_number);
+ status->uniform_hdr.cmd_status =
+ le16_get_bits(desc->hdr.info0,
+ HAL_REO_STATUS_HDR_INFO0_EXEC_STATUS);
+ status->uniform_hdr.timestamp = le32_to_cpu(desc->hdr.timestamp);
+
+ for (i = 0; i < ARRAY_SIZE(desc->rx_bitmap1023_288); i++)
+ dst[i] = le32_to_cpu(desc->rx_bitmap1023_288[i]);
+
+ status->loop_cnt =
+ le16_get_bits(desc->info0,
+ HAL_REO_GET_Q_1K_STATS_STATUS_INFO0_LOOPING_COUNT);
+}
+
static int ath12k_hal_reo_cmd_flush_queue(struct hal_tlv_64_hdr *tlv,
struct ath12k_hal_reo_cmd *cmd)
{
@@ -596,6 +619,13 @@ void ath12k_wifi8_hal_reo_status_queue_stats(struct ath12k_base *ab,
le32_get_bits(desc->info0, HAL_REO_GET_Q_STATS_STATUS_INFO0_CURRENT_INDEX);
status->u.queue_stats.pn[0] = le32_to_cpu(desc->pn_31_0);
status->u.queue_stats.pn[1] = le16_to_cpu(desc->pn_47_32);
+ status->u.queue_stats.pn_127_48_info =
+ le16_get_bits(desc->info1, HAL_REO_GET_Q_STATS_STATUS_INFO1_PN_127_48_INFO);
+ status->u.queue_stats.to_follow_1k =
+ le32_get_bits(desc->info5,
+ HAL_REO_GET_Q_STATS_STATUS_INFO5_GET_Q_1K_SSTAT_FOLLOW);
+ status->u.queue_stats.pn_len =
+ (status->u.queue_stats.pn_127_48_info == 0) ? 6 : 16;
status->u.queue_stats.last_rx_queue_ts =
le32_to_cpu(desc->last_rx_enqueue_timestamp);
status->u.queue_stats.last_rx_dequeue_ts =
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
index d61ca0823b5f..357839c7d9e3 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
@@ -112,6 +112,9 @@ void ath12k_wifi8_hal_reo_hw_setup(struct ath12k_base *ab);
void ath12k_wifi8_hal_reo_status_queue_stats(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_status *status);
+void ath12k_wifi8_hal_reo_status_queue_1k_stats(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *tlv,
+ struct hal_reo_status *status);
void ath12k_wifi8_hal_reo_flush_queue_status(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_status *status);
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 07/13] wifi: ath12k: ng: process REO status ring
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (5 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 06/13] wifi: ath12k: ng: parse 1K REO queue statistics Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 08/13] wifi: ath12k: ng: add batched REO command sends Pradeep Kumar Chitrapu
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
Wi-Fi 8 can submit REO commands with completion callbacks, but its NAPI
service path does not drain the REO status ring. Commands that request a
status therefore cannot deliver their decoded response to the pending
command context.
Service the REO status ring from the Wi-Fi 8 datapath, decode each
supported status TLV, match it to the pending command number, and pass the
complete status payload to the registered callback. Keep a queue-stats
command pending when a 1K bitmap page follows, then release its context
after processing the second page.
This commit only connects the generic command and status framework. It
does not add a command client or change Wi-Fi 7 status processing.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/wifi8/dp.c | 8 +++
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c | 93 +++++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h | 1 +
3 files changed, 102 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp.c b/drivers/net/wireless/ath/ath12k/wifi8/dp.c
index dee73473cea9..e89826f33206 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp.c
@@ -498,6 +498,14 @@ static int ath12k_wifi8_dp_service_srng(struct ath12k_dp *dp,
goto done;
}
+ if (dp->hw_params->ring_mask->reo_status[grp_id]) {
+ work_done = ath12k_wifi8_dp_rx_process_reo_status(dp, budget);
+ budget -= work_done;
+ tot_work_done += work_done;
+ if (budget <= 0)
+ goto done;
+ }
+
done:
return tot_work_done;
}
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
index b75e65091995..632ce30fe459 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
@@ -2210,3 +2210,96 @@ int ath12k_wifi8_dp_rx_process_err(struct ath12k_dp *dp,
return total_msdu_reaped;
}
+
+int ath12k_wifi8_dp_rx_process_reo_status(struct ath12k_dp *dp, int budget)
+{
+ struct ath12k_base *ab = dp->ab;
+ struct hal_tlv_64_hdr *hdr;
+ struct hal_srng *srng;
+ struct ath12k_dp_rx_reo_cmd *cmd, *tmp;
+ struct hal_reo_status reo_status;
+ int work_done = 0;
+ u16 tag;
+ bool found;
+ bool done;
+
+ srng = &ab->hal.srng_list[dp->reo_status_ring.ring_id];
+
+ spin_lock_bh(&srng->lock);
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ while (work_done < budget &&
+ (hdr = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
+ work_done++;
+ tag = le64_get_bits(hdr->tl, HAL_SRNG_TLV_HDR_TAG);
+ memset(&reo_status, 0, sizeof(reo_status));
+
+ reo_status.tag = tag;
+ switch (tag) {
+ case HAL_REO_GET_QUEUE_STATS_STATUS:
+ ath12k_wifi8_hal_reo_status_queue_stats(ab, hdr, &reo_status);
+ break;
+ case HAL_REO_GET_QUEUE_1K_STATS_STATUS:
+ ath12k_wifi8_hal_reo_status_queue_1k_stats(ab, hdr,
+ &reo_status);
+ break;
+ case HAL_REO_FLUSH_QUEUE_STATUS:
+ ath12k_wifi8_hal_reo_flush_queue_status(ab, hdr, &reo_status);
+ break;
+ case HAL_REO_FLUSH_CACHE_STATUS:
+ ath12k_wifi8_hal_reo_flush_cache_status(ab, hdr, &reo_status);
+ break;
+ case HAL_REO_UNBLOCK_CACHE_STATUS:
+ ath12k_wifi8_hal_reo_unblk_cache_status(ab, hdr, &reo_status);
+ break;
+ case HAL_REO_FLUSH_TIMEOUT_LIST_STATUS:
+ ath12k_wifi8_hal_reo_flush_timeout_list_status(ab, hdr,
+ &reo_status);
+ break;
+ case HAL_REO_DESCRIPTOR_THRESHOLD_REACHED_STATUS:
+ ath12k_wifi8_hal_reo_desc_thresh_reached_status(ab, hdr,
+ &reo_status);
+ break;
+ case HAL_REO_UPDATE_RX_REO_QUEUE_STATUS:
+ ath12k_wifi8_hal_reo_update_rx_reo_queue_status(ab, hdr,
+ &reo_status);
+ break;
+ default:
+ ath12k_warn(ab, "Unknown reo status type %d\n", tag);
+ continue;
+ }
+
+ found = false;
+ done = true;
+
+ spin_lock_bh(&dp->reo_cmd_lock);
+ list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) {
+ if (reo_status.uniform_hdr.cmd_num != cmd->cmd_num)
+ continue;
+
+ found = true;
+ if (tag == HAL_REO_GET_QUEUE_STATS_STATUS &&
+ reo_status.u.queue_stats.to_follow_1k)
+ done = false;
+
+ if (done)
+ list_del(&cmd->list);
+
+ break;
+ }
+ spin_unlock_bh(&dp->reo_cmd_lock);
+
+ if (found) {
+ if (cmd->handler)
+ cmd->handler(dp, &cmd->u, &reo_status);
+
+ if (done)
+ kfree(cmd);
+ }
+ }
+
+ ath12k_hal_srng_access_end(ab, srng);
+ spin_unlock_bh(&srng->lock);
+
+ return work_done;
+}
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
index a05ab2f4495c..10940dd92a62 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
@@ -191,4 +191,5 @@ void ath12k_hal_extract_rx_spd_data_qcn9625(struct hal_rx_spd *rx_info,
struct hal_rx_desc *rx_desc);
int ath12k_wifi8_dp_rx_process_err(struct ath12k_dp *dp,
struct napi_struct *napi, int budget);
+int ath12k_wifi8_dp_rx_process_reo_status(struct ath12k_dp *dp, int budget);
#endif /* ATH12K_DP_RX_WIFI8_H */
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 08/13] wifi: ath12k: ng: add batched REO command sends
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (6 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 07/13] wifi: ath12k: ng: process REO status ring Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 09/13] wifi: ath12k: ng: add REO queue descriptor helpers Pradeep Kumar Chitrapu
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
RX TID setup needs to send related REO operations together so hardware
sees a consistent queue state and the driver can keep one pending-command
view for the whole operation.
Add Wi-Fi 8 helpers to submit multiple REO commands to one command ring
while reusing the existing pending-command callback tracking. Share the
HAL descriptor formatter between the batch and single-command paths.
Reject batched flush-cache commands that request delayed blocking
because those commands mutate the shared REO block-resource state. If
descriptor formatting fails after reserving entries, restore the source
ring pointers before exposing stale descriptors to hardware; keep the
same rollback behavior for the single-command path.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/hal.h | 6 +
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c | 184 ++++++++++++++++++++++---
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h | 12 ++
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c | 138 +++++++++++++++----
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h | 9 ++
5 files changed, 297 insertions(+), 52 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index 6534e11a3378..b4da48af5a4b 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1141,6 +1141,12 @@ struct ath12k_hal_reo_cmd {
u8 pn_127_48_info;
};
+struct ath12k_reo_cmd_entry {
+ enum hal_reo_cmd_type type;
+ struct ath12k_hal_reo_cmd cmd;
+ int cmd_num;
+};
+
enum hal_pn_type {
HAL_PN_TYPE_NONE,
HAL_PN_TYPE_WPA,
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
index 632ce30fe459..14117430c43b 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
@@ -50,6 +50,73 @@ ath12k_wifi8_get_sw_desc(struct ath12k_dp *dp, const struct hal_reo_dest_ring *d
return ath12k_dp_get_rx_desc(dp, cookie);
}
+static inline bool ath12k_wifi8_dp_reo_cmd_shutdown(struct ath12k_base *ab)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
+ struct ath12k_base *central_ab = central_dp->ab;
+
+ return test_bit(ATH12K_FLAG_CRASH_FLUSH, ¢ral_ab->dev_flags) ||
+ test_bit(ATH12K_FLAG_RECOVERY, ¢ral_ab->dev_flags);
+}
+
+static int ath12k_wifi8_dp_reo_cmd_prepare(struct ath12k_dp_rx_reo_cmd **dp_cmd,
+ void *data, size_t len,
+ void (*cb)(struct ath12k_dp *dp,
+ void *ctx,
+ struct hal_reo_status *status))
+{
+ if (!cb) {
+ *dp_cmd = NULL;
+ return 0;
+ }
+
+ if (WARN_ON(len > sizeof((*dp_cmd)->u)))
+ return -EINVAL;
+
+ if (WARN_ON(len && !data))
+ return -EINVAL;
+
+ *dp_cmd = kzalloc_obj(struct ath12k_dp_rx_reo_cmd, GFP_ATOMIC);
+ if (!*dp_cmd)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&(*dp_cmd)->list);
+ if (len)
+ memcpy(&(*dp_cmd)->u, data, len);
+ (*dp_cmd)->handler = cb;
+
+ return 0;
+}
+
+static void ath12k_wifi8_dp_reo_cmd_queue_locked(struct ath12k_dp *dp,
+ struct ath12k_dp_rx_reo_cmd *dp_cmd,
+ int cmd_num)
+{
+ if (!dp_cmd)
+ return;
+
+ lockdep_assert_held(&dp->reo_cmd_lock);
+
+ dp_cmd->cmd_num = cmd_num;
+ list_add_tail(&dp_cmd->list, &dp->reo_cmd_list);
+}
+
+static int ath12k_wifi8_dp_reo_cmd_validate_batch(struct ath12k_reo_cmd_entry *cmds,
+ int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ if (!(cmds[i].cmd.flag & HAL_REO_CMD_FLG_FLUSH_BLOCK_LATER))
+ continue;
+
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static int ath12k_wifi8_dp_reo_cmd_send_ring(struct ath12k_base *ab,
struct hal_srng *cmd_ring,
void *data, size_t len,
@@ -63,25 +130,14 @@ static int ath12k_wifi8_dp_reo_cmd_send_ring(struct ath12k_base *ab,
int cmd_num;
struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
struct ath12k_base *central_ab = central_dp->ab;
+ int ret;
- if (test_bit(ATH12K_FLAG_CRASH_FLUSH, ¢ral_ab->dev_flags) ||
- test_bit(ATH12K_FLAG_RECOVERY, ¢ral_ab->dev_flags))
+ if (ath12k_wifi8_dp_reo_cmd_shutdown(ab))
return -ESHUTDOWN;
- if (!cb) {
- dp_cmd = NULL;
- } else {
- if (WARN_ON(len > sizeof(dp_cmd->u)))
- return -EINVAL;
-
- dp_cmd = kzalloc_obj(*dp_cmd, GFP_ATOMIC);
- if (!dp_cmd)
- return -ENOMEM;
-
- INIT_LIST_HEAD(&dp_cmd->list);
- memcpy(&dp_cmd->u, data, len);
- dp_cmd->handler = cb;
- }
+ ret = ath12k_wifi8_dp_reo_cmd_prepare(&dp_cmd, data, len, cb);
+ if (ret)
+ return ret;
cmd_num = ath12k_wifi8_hal_reo_cmd_send(central_ab, cmd_ring, type, cmd);
if (cmd_num < 0) {
@@ -97,15 +153,82 @@ static int ath12k_wifi8_dp_reo_cmd_send_ring(struct ath12k_base *ab,
if (!dp_cmd)
return 0;
- dp_cmd->cmd_num = cmd_num;
-
spin_lock_bh(¢ral_dp->reo_cmd_lock);
- list_add_tail(&dp_cmd->list, ¢ral_dp->reo_cmd_list);
+ ath12k_wifi8_dp_reo_cmd_queue_locked(central_dp, dp_cmd, cmd_num);
spin_unlock_bh(¢ral_dp->reo_cmd_lock);
return 0;
}
+static int
+ath12k_wifi8_dp_reo_cmd_send_ring_n(struct ath12k_base *ab,
+ struct hal_srng *cmd_ring,
+ struct ath12k_reo_cmd_entry *entries,
+ struct ath12k_reo_dp_cmd_desc *dp_descs,
+ int n)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
+ struct ath12k_base *central_ab = central_dp->ab;
+ struct ath12k_dp_rx_reo_cmd **dp_cmds;
+ int i, ret;
+
+ if (WARN_ON(n <= 0))
+ return -EINVAL;
+
+ if (WARN_ON(!entries || !dp_descs))
+ return -EINVAL;
+
+ if (ath12k_wifi8_dp_reo_cmd_shutdown(ab))
+ return -ESHUTDOWN;
+
+ ret = ath12k_wifi8_dp_reo_cmd_validate_batch(entries, n);
+ if (ret)
+ return ret;
+
+ dp_cmds = kcalloc(n, sizeof(*dp_cmds), GFP_ATOMIC);
+ if (!dp_cmds)
+ return -ENOMEM;
+
+ for (i = 0; i < n; i++) {
+ ret = ath12k_wifi8_dp_reo_cmd_prepare(&dp_cmds[i],
+ dp_descs[i].data,
+ dp_descs[i].len,
+ dp_descs[i].cb);
+ if (ret)
+ goto err_free;
+ }
+
+ spin_lock_bh(&cmd_ring->lock);
+ ath12k_hal_srng_access_begin(central_ab, cmd_ring);
+
+ ret = ath12k_wifi8_hal_reo_cmd_send_n_locked(central_ab, cmd_ring,
+ entries, n);
+ if (!ret) {
+ spin_lock_bh(¢ral_dp->reo_cmd_lock);
+ for (i = 0; i < n; i++)
+ ath12k_wifi8_dp_reo_cmd_queue_locked(central_dp, dp_cmds[i],
+ entries[i].cmd_num);
+ spin_unlock_bh(¢ral_dp->reo_cmd_lock);
+ }
+
+ ath12k_hal_srng_access_end(central_ab, cmd_ring);
+ spin_unlock_bh(&cmd_ring->lock);
+
+ if (ret)
+ goto err_free;
+
+ kfree(dp_cmds);
+ return 0;
+
+err_free:
+ for (i = 0; i < n; i++)
+ kfree(dp_cmds[i]);
+ kfree(dp_cmds);
+
+ return ret;
+}
+
int ath12k_wifi8_dp_reo_cmd_send(struct ath12k_base *ab,
void *data, size_t len,
enum hal_reo_cmd_type type,
@@ -116,8 +239,9 @@ int ath12k_wifi8_dp_reo_cmd_send(struct ath12k_base *ab,
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
struct hal_srng *cmd_ring;
+ u32 ring_id = central_dp->reo_cmd_ring.ring_id;
- cmd_ring = ¢ral_dp->ab->hal.srng_list[central_dp->reo_cmd_ring.ring_id];
+ cmd_ring = ¢ral_dp->ab->hal.srng_list[ring_id];
return ath12k_wifi8_dp_reo_cmd_send_ring(ab, cmd_ring, data, len,
type, cmd, cb);
@@ -134,15 +258,31 @@ int ath12k_wifi8_dp_reo_cmd_send_highprio(struct ath12k_base *ab,
struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
struct ath12k_dp_wifi8 *dp_wifi8 = ath12k_get_dp_wifi8(central_dp);
struct hal_srng *cmd_ring;
- u32 ring_id;
+ u32 ring_id = dp_wifi8->reo_high_prio_cmd_ring.ring_id;
- ring_id = dp_wifi8->reo_high_prio_cmd_ring.ring_id;
cmd_ring = ¢ral_dp->ab->hal.srng_list[ring_id];
return ath12k_wifi8_dp_reo_cmd_send_ring(ab, cmd_ring, data, len,
type, cmd, cb);
}
+int ath12k_wifi8_dp_reo_cmd_send_highprio_n(struct ath12k_base *ab,
+ struct ath12k_reo_cmd_entry *entries,
+ struct ath12k_reo_dp_cmd_desc *dp_descs,
+ int n)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
+ struct ath12k_dp_wifi8 *dp_wifi8 = ath12k_get_dp_wifi8(central_dp);
+ struct hal_srng *cmd_ring;
+ u32 ring_id = dp_wifi8->reo_high_prio_cmd_ring.ring_id;
+
+ cmd_ring = ¢ral_dp->ab->hal.srng_list[ring_id];
+
+ return ath12k_wifi8_dp_reo_cmd_send_ring_n(ab, cmd_ring, entries,
+ dp_descs, n);
+}
+
/**
* ath12k_wifi8_rx_spd_buf_alloc - allocate per-ring SPD scratch-pad arrays
* @dp_hw_grp_wifi8: Wi-Fi 8 hardware-group private data
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
index 10940dd92a62..2fb56776adb0 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
@@ -12,6 +12,7 @@
struct ath12k_dp_hw_group_wifi8;
struct hal_reo_status;
+struct ath12k_reo_cmd_entry;
struct hal_rx_mpdu_desc_info {
union {
@@ -159,6 +160,17 @@ int ath12k_wifi8_dp_reo_cmd_send_highprio(struct ath12k_base *ab,
struct ath12k_hal_reo_cmd *cmd,
void (*cb)(struct ath12k_dp *dp, void *ctx,
struct hal_reo_status *status));
+struct ath12k_reo_dp_cmd_desc {
+ void *data;
+ size_t len;
+ void (*cb)(struct ath12k_dp *dp, void *ctx,
+ struct hal_reo_status *status);
+};
+
+int ath12k_wifi8_dp_reo_cmd_send_highprio_n(struct ath12k_base *ab,
+ struct ath12k_reo_cmd_entry *entries,
+ struct ath12k_reo_dp_cmd_desc *dp_descs,
+ int n);
int ath12k_wifi8_dp_rx_ring_setup(struct ath12k_base *ab);
int ath12k_wifi8_dp_rx_ring_free(struct ath12k_base *ab);
int ath12k_wifi8_dp_rxdma_ring_sel_config_qcn9625(struct ath12k_base *ab);
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
index d78c178cc70d..12a37c395bb0 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
@@ -536,24 +536,116 @@ static int ath12k_hal_reo_cmd_unblock_cache(struct hal_tlv_64_hdr *tlv,
return le16_to_cpu(desc->cmd.reo_cmd_number);
}
-int ath12k_wifi8_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
- enum hal_reo_cmd_type type,
- struct ath12k_hal_reo_cmd *cmd)
+static int ath12k_wifi8_hal_reo_cmd_fill(struct ath12k_base *ab,
+ struct hal_tlv_64_hdr *reo_desc,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd)
{
- struct hal_tlv_64_hdr *reo_desc;
- u32 saved_hp, saved_reap_hp;
- int ret;
-
- if (type == HAL_REO_CMD_FLUSH_TIMEOUT_LIST) {
+ switch (type) {
+ case HAL_REO_CMD_GET_QUEUE_STATS:
+ return ath12k_wifi8_hal_reo_cmd_queue_stats(reo_desc, cmd);
+ case HAL_REO_CMD_FLUSH_CACHE:
+ return ath12k_wifi8_hal_reo_cmd_flush_cache(&ab->hal, reo_desc,
+ cmd);
+ case HAL_REO_CMD_UPDATE_RX_QUEUE:
+ return ath12k_wifi8_hal_reo_cmd_update_rx_queue(reo_desc, cmd);
+ case HAL_REO_CMD_FLUSH_QUEUE:
+ return ath12k_hal_reo_cmd_flush_queue(reo_desc, cmd);
+ case HAL_REO_CMD_UNBLOCK_CACHE:
+ return ath12k_hal_reo_cmd_unblock_cache(reo_desc, cmd);
+ case HAL_REO_CMD_FLUSH_TIMEOUT_LIST:
ath12k_warn(ab, "Unsupported reo command %d\n", type);
return -EOPNOTSUPP;
+ default:
+ ath12k_warn(ab, "Unknown reo command %d\n", type);
+ return -EINVAL;
}
+}
- if (type > HAL_REO_CMD_UPDATE_RX_QUEUE) {
- ath12k_warn(ab, "Unknown reo command %d\n", type);
+int ath12k_wifi8_hal_reo_cmd_send_n_locked(struct ath12k_base *ab,
+ struct hal_srng *srng,
+ struct ath12k_reo_cmd_entry *entries,
+ int n)
+{
+ struct hal_tlv_64_hdr *reo_desc;
+ u32 saved_hp, saved_reap_hp;
+ int i, ret;
+
+ if (WARN_ON(n <= 0))
+ return -EINVAL;
+
+ if (WARN_ON(!entries))
return -EINVAL;
+
+ lockdep_assert_held(&srng->lock);
+
+ saved_hp = srng->u.src_ring.hp;
+ saved_reap_hp = srng->u.src_ring.reap_hp;
+
+ for (i = 0; i < n; i++) {
+ reo_desc = ath12k_hal_srng_src_get_next_entry(ab, srng);
+ if (!reo_desc) {
+ ret = -ENOBUFS;
+ goto err_restore_hp;
+ }
+
+ ret = ath12k_wifi8_hal_reo_cmd_fill(ab, reo_desc,
+ entries[i].type,
+ &entries[i].cmd);
+ if (ret <= 0) {
+ if (!ret)
+ ret = -EINVAL;
+ goto err_restore_hp;
+ }
+
+ entries[i].cmd_num = ret;
}
+ return 0;
+
+err_restore_hp:
+ /* Keep batched command submission all-or-nothing. If any descriptor
+ * cannot be reserved or formatted, roll the source ring pointers back
+ * so partially prepared entries are not exposed to hardware.
+ */
+ srng->u.src_ring.hp = saved_hp;
+ srng->u.src_ring.reap_hp = saved_reap_hp;
+
+ return ret;
+}
+
+int ath12k_wifi8_hal_reo_cmd_send_n(struct ath12k_base *ab,
+ struct hal_srng *srng,
+ struct ath12k_reo_cmd_entry *entries,
+ int n)
+{
+ int ret;
+
+ if (WARN_ON(n <= 0))
+ return -EINVAL;
+
+ if (WARN_ON(!entries))
+ return -EINVAL;
+
+ spin_lock_bh(&srng->lock);
+ ath12k_hal_srng_access_begin(ab, srng);
+
+ ret = ath12k_wifi8_hal_reo_cmd_send_n_locked(ab, srng, entries, n);
+
+ ath12k_hal_srng_access_end(ab, srng);
+ spin_unlock_bh(&srng->lock);
+
+ return ret;
+}
+
+int ath12k_wifi8_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
+ enum hal_reo_cmd_type type,
+ struct ath12k_hal_reo_cmd *cmd)
+{
+ struct hal_tlv_64_hdr *reo_desc;
+ u32 saved_hp, saved_reap_hp;
+ int ret;
+
spin_lock_bh(&srng->lock);
ath12k_hal_srng_access_begin(ab, srng);
@@ -566,26 +658,12 @@ int ath12k_wifi8_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
goto out;
}
- switch (type) {
- case HAL_REO_CMD_GET_QUEUE_STATS:
- ret = ath12k_wifi8_hal_reo_cmd_queue_stats(reo_desc, cmd);
- break;
- case HAL_REO_CMD_FLUSH_CACHE:
- ret = ath12k_wifi8_hal_reo_cmd_flush_cache(&ab->hal, reo_desc,
- cmd);
- break;
- case HAL_REO_CMD_UPDATE_RX_QUEUE:
- ret = ath12k_wifi8_hal_reo_cmd_update_rx_queue(reo_desc, cmd);
- break;
- case HAL_REO_CMD_FLUSH_QUEUE:
- ret = ath12k_hal_reo_cmd_flush_queue(reo_desc, cmd);
- break;
- case HAL_REO_CMD_UNBLOCK_CACHE:
- ret = ath12k_hal_reo_cmd_unblock_cache(reo_desc, cmd);
- break;
- default:
- ret = -EINVAL;
- break;
+ ret = ath12k_wifi8_hal_reo_cmd_fill(ab, reo_desc, type, cmd);
+ if (ret <= 0) {
+ if (!ret)
+ ret = -EINVAL;
+ srng->u.src_ring.hp = saved_hp;
+ srng->u.src_ring.reap_hp = saved_reap_hp;
}
out:
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
index 357839c7d9e3..430b0f07563f 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
@@ -100,6 +100,7 @@ struct ath12k_hal_rx_cmd_ring_param {
struct hal_tlv_64_hdr;
struct hal_reo_status;
+struct ath12k_reo_cmd_entry;
int
ath12k_wifi8_hal_invalidate_rx_cache_cmd_send(struct ath12k_base *ab,
@@ -108,6 +109,14 @@ ath12k_wifi8_hal_invalidate_rx_cache_cmd_send(struct ath12k_base *ab,
int ath12k_wifi8_hal_reo_cmd_send(struct ath12k_base *ab, struct hal_srng *srng,
enum hal_reo_cmd_type type,
struct ath12k_hal_reo_cmd *cmd);
+int ath12k_wifi8_hal_reo_cmd_send_n_locked(struct ath12k_base *ab,
+ struct hal_srng *srng,
+ struct ath12k_reo_cmd_entry *entries,
+ int n);
+int ath12k_wifi8_hal_reo_cmd_send_n(struct ath12k_base *ab,
+ struct hal_srng *srng,
+ struct ath12k_reo_cmd_entry *entries,
+ int n);
void ath12k_wifi8_hal_reo_hw_setup(struct ath12k_base *ab);
void ath12k_wifi8_hal_reo_status_queue_stats(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 09/13] wifi: ath12k: ng: add REO queue descriptor helpers
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (7 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 08/13] wifi: ath12k: ng: add batched REO command sends Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 10/13] wifi: ath12k: ng: add REO qaddr cache clear support Pradeep Kumar Chitrapu
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
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@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
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 10/13] wifi: ath12k: ng: add REO qaddr cache clear support
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (8 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 09/13] wifi: ath12k: ng: add REO queue descriptor helpers Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 11/13] wifi: ath12k: ng: add RX TID REO helpers Pradeep Kumar Chitrapu
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
Wi-Fi 8 RX TID setup updates the shared queue-address table. Once REO
queue LUT support is enabled, those updates must invalidate the hardware
qaddr cache or later lookups can use stale queue descriptors.
Register the Wi-Fi 8 cache-clear callback before qref updates are made
reachable so station add cannot call an unset HAL operation.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
.../net/wireless/ath/ath12k/wifi8/hal_qcn9625.c | 1 +
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c | 23 ++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h | 1 +
3 files changed, 25 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_qcn9625.c b/drivers/net/wireless/ath/ath12k/wifi8/hal_qcn9625.c
index 6235668e23cd..bb2f114d97ab 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_qcn9625.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_qcn9625.c
@@ -421,6 +421,7 @@ const struct hal_ops hal_qcn9625_ops = {
.tx_configure_bank_register = ath12k_wifi8_hal_tx_configure_bank_register,
.tx_set_dscp_tid_map = ath12k_wifi8_hal_tx_set_dscp_tid_map,
.reo_hw_setup = ath12k_wifi8_hal_reo_hw_setup,
+ .reo_shared_qaddr_cache_clear = ath12k_wifi8_hal_reo_shared_qaddr_cache_clear,
.extract_rx_desc_data = ath12k_hal_extract_rx_desc_data_qcn9625,
.rx_desc_get_dot11_hdr = ath12k_hal_rx_desc_get_dot11_hdr_qcn9625,
.rx_h_is_decrypted = ath12k_hal_rx_h_is_decrypted_qcn9625,
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
index ad00c182c2bd..d636f6ab60ff 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c
@@ -907,6 +907,29 @@ void ath12k_wifi8_hal_reo_update_rx_reo_queue_status(struct ath12k_base *ab,
ath12k_wifi8_hal_reo_status_hdr_parse(desc, status);
}
+void ath12k_wifi8_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab)
+{
+ struct ath12k_hal *hal = &ab->hal;
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ u32 val;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ if (!ab->hw_params->reoq_lut_support)
+ return;
+
+ val = ath12k_hif_read32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
+ HAL_REO1_QDESC_ADDR(hal));
+
+ val |= u32_encode_bits(1, HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY);
+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
+ HAL_REO1_QDESC_ADDR(hal), val);
+
+ val &= ~HAL_REO_QDESC_ADDR_READ_CLEAR_QDESC_ARRAY;
+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG +
+ HAL_REO1_QDESC_ADDR(hal), val);
+}
+
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);
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
index 94732f82f614..26a24731cb06 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h
@@ -129,6 +129,7 @@ int ath12k_wifi8_hal_reo_cmd_send_n(struct ath12k_base *ab,
struct ath12k_reo_cmd_entry *entries,
int n);
void ath12k_wifi8_hal_reo_hw_setup(struct ath12k_base *ab);
+void ath12k_wifi8_hal_reo_shared_qaddr_cache_clear(struct ath12k_base *ab);
void ath12k_wifi8_hal_reo_status_queue_stats(struct ath12k_base *ab,
struct hal_tlv_64_hdr *tlv,
struct hal_reo_status *status);
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 11/13] wifi: ath12k: ng: add RX TID REO helpers
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (9 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 10/13] wifi: ath12k: ng: add REO qaddr cache clear support Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 12/13] wifi: ath12k: ng: wire RX TID REO operations Pradeep Kumar Chitrapu
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
The common RX TID path routes queue setup, update, flush and teardown
through architecture hooks. Wi-Fi 8 needs matching helpers before those
hooks can be enabled for QCN9625.
Add helpers for queue update, qref programming, PN configuration, flush
handling and fragment cleanup. Keep the helpers disconnected until the
final wiring patch so intermediate commits do not expose a partial RX TID
implementation.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c | 288 +++++++++++++++++++++++++-
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h | 31 +++
2 files changed, 315 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
index 14117430c43b..0b8a9d32e125 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
@@ -283,6 +283,287 @@ int ath12k_wifi8_dp_reo_cmd_send_highprio_n(struct ath12k_base *ab,
dp_descs, n);
}
+static struct ath12k_reo_queue_ref *
+ath12k_wifi8_peer_rx_tid_qref(struct ath12k_dp *dp, u16 peer_id, u16 tid)
+{
+ struct ath12k_reo_q_addr_lut *lut = &dp->reoq_lut;
+
+ if (!lut->vaddr)
+ return NULL;
+
+ peer_id &= ~ATH12K_PEER_ML_ID_VALID;
+
+ return (struct ath12k_reo_queue_ref *)lut->vaddr +
+ peer_id * (IEEE80211_NUM_TIDS + 1) + tid;
+}
+
+void ath12k_wifi8_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id,
+ u16 tid, dma_addr_t paddr)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
+ struct ath12k_base *central_ab = central_dp->ab;
+ struct ath12k_reo_queue_ref *qref;
+
+ if (!central_ab->hw_params->reoq_lut_support)
+ return;
+
+ if ((peer_id & ~ATH12K_PEER_ML_ID_VALID) > DP_MAX_PEER_ID) {
+ ath12k_warn(central_ab, "peer id %d exceeds reo qref table\n",
+ peer_id);
+ return;
+ }
+
+ qref = ath12k_wifi8_peer_rx_tid_qref(central_dp, peer_id, tid);
+ if (!qref) {
+ ath12k_warn(central_ab, "reo qref table is not setup\n");
+ return;
+ }
+
+ qref->info0 = u32_encode_bits(lower_32_bits(paddr),
+ BUFFER_ADDR_INFO0_ADDR);
+ qref->info1 = u32_encode_bits(upper_32_bits(paddr),
+ BUFFER_ADDR_INFO1_ADDR) |
+ u32_encode_bits(tid, DP_REO_QREF_NUM);
+
+ ath12k_hal_reo_shared_qaddr_cache_clear(central_ab);
+}
+
+void ath12k_wifi8_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id,
+ u16 tid)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ struct ath12k_dp *central_dp = ath12k_get_central_dp(dp);
+ struct ath12k_base *central_ab = central_dp->ab;
+ struct ath12k_reo_queue_ref *qref;
+
+ if (!central_ab->hw_params->reoq_lut_support)
+ return;
+
+ if ((peer_id & ~ATH12K_PEER_ML_ID_VALID) > DP_MAX_PEER_ID) {
+ ath12k_warn(central_ab, "peer id %d exceeds reo qref table\n",
+ peer_id);
+ return;
+ }
+
+ qref = ath12k_wifi8_peer_rx_tid_qref(central_dp, peer_id, tid);
+ if (!qref) {
+ ath12k_warn(central_ab, "reo qref table is not setup\n");
+ return;
+ }
+
+ qref->info0 = u32_encode_bits(0, BUFFER_ADDR_INFO0_ADDR);
+ qref->info1 = u32_encode_bits(0, BUFFER_ADDR_INFO1_ADDR) |
+ u32_encode_bits(tid, DP_REO_QREF_NUM);
+
+ ath12k_hal_reo_shared_qaddr_cache_clear(central_ab);
+}
+
+void ath12k_wifi8_dp_rx_peer_tid_delete(struct ath12k_base *ab,
+ struct ath12k_dp_link_peer *peer,
+ u8 tid)
+{
+ struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+
+ if (!(peer->rx_tid_active_bitmask & BIT(tid)))
+ return;
+
+ ath12k_dp_mark_tid_as_inactive(dp, peer->peer_id, tid);
+ ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(dp);
+}
+
+int ath12k_wifi8_peer_rx_tid_reo_update(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 ba_win_sz, u16 ssn,
+ bool update_ssn)
+{
+ struct ath12k_dp_rx_tid_rxq rx_tid_rxq;
+ struct ath12k_hal_reo_cmd cmd = {};
+ struct ath12k_base *ab = dp->ab;
+ int ret;
+
+ ath12k_dp_init_rx_tid_rxq(&rx_tid_rxq, rx_tid,
+ !!(peer->rx_tid_active_bitmask &
+ BIT(rx_tid->tid)));
+
+ cmd.addr_lo = lower_32_bits(rx_tid_rxq.qbuf.paddr_aligned);
+ cmd.addr_hi = upper_32_bits(rx_tid_rxq.qbuf.paddr_aligned);
+ cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
+ cmd.upd0 = HAL_REO_CMD_UPD0_BA_WINDOW_SIZE;
+ cmd.ba_window_size = ba_win_sz;
+
+ if (update_ssn) {
+ cmd.upd0 |= HAL_REO_CMD_UPD0_SSN;
+ cmd.upd2 = u32_encode_bits(ssn, HAL_REO_CMD_UPD2_SSN);
+ }
+
+ ret = ath12k_wifi8_dp_reo_cmd_send(ab, &rx_tid_rxq,
+ sizeof(rx_tid_rxq),
+ HAL_REO_CMD_UPDATE_RX_QUEUE,
+ &cmd, NULL);
+ if (ret) {
+ ath12k_warn(ab, "failed to update rx tid queue, tid %d (%d)\n",
+ rx_tid_rxq.tid, ret);
+ return ret;
+ }
+
+ rx_tid->ba_win_sz = ba_win_sz;
+
+ ath12k_dbg(ab, ATH12K_DBG_DP_RX,
+ "rx tid queue update successful for tid: %u, peer_id: %d, peer: %pM, link_id: %u ba_win_sz: %u\n",
+ rx_tid->tid, peer->peer_id, peer->addr, peer->link_id,
+ rx_tid->ba_win_sz);
+
+ return 0;
+}
+
+int ath12k_wifi8_dp_reo_cache_flush(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid)
+{
+ struct ath12k_hal_reo_cmd cmd = {};
+
+ cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
+ cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
+ cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS |
+ HAL_REO_CMD_FLG_FLUSH_FWD_ALL_MPDUS;
+
+ if (rx_tid->tid != HAL_DESC_REO_NON_QOS_TID)
+ cmd.flag |= HAL_REO_CMD_FLG_FLUSH_QUEUE_1K_DESC;
+
+ return ath12k_wifi8_dp_reo_cmd_send(ab, rx_tid, sizeof(*rx_tid),
+ HAL_REO_CMD_FLUSH_CACHE, &cmd,
+ ath12k_dp_reo_cmd_free);
+}
+
+int ath12k_wifi8_dp_rx_assign_reoq(struct ath12k_base *ab,
+ struct ath12k_dp_peer *dp_peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u16 ssn, enum hal_pn_type pn_type)
+{
+ u32 ba_win_sz = rx_tid->ba_win_sz;
+ struct ath12k_reoq_buf *buf;
+ void *vaddr, *vaddr_aligned;
+ dma_addr_t paddr_aligned;
+ u8 tid = rx_tid->tid;
+ u32 hw_desc_sz;
+ int ret;
+
+ buf = &dp_peer->reoq_bufs[tid];
+ if (!buf->vaddr) {
+ if (tid == HAL_DESC_REO_NON_QOS_TID)
+ hw_desc_sz = ath12k_wifi8_hal_reo_qdesc_size(ba_win_sz,
+ tid);
+ else
+ hw_desc_sz = ath12k_wifi8_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX,
+ tid);
+
+ vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1,
+ GFP_ATOMIC);
+ if (!vaddr)
+ return -ENOMEM;
+
+ vaddr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN);
+
+ ath12k_wifi8_hal_reo_qdesc_setup(vaddr_aligned, tid,
+ ba_win_sz, ssn, pn_type);
+
+ paddr_aligned = dma_map_single(ab->dev, vaddr_aligned,
+ hw_desc_sz,
+ DMA_BIDIRECTIONAL);
+ ret = dma_mapping_error(ab->dev, paddr_aligned);
+ if (ret) {
+ kfree(vaddr);
+ return ret;
+ }
+
+ buf->vaddr = vaddr;
+ buf->paddr_aligned = paddr_aligned;
+ buf->size = hw_desc_sz;
+ }
+
+ rx_tid->qbuf = *buf;
+
+ return 0;
+}
+
+int ath12k_wifi8_dp_rx_tid_delete_handler(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid)
+{
+ struct ath12k_hal_reo_cmd cmd = {};
+
+ cmd.flag = HAL_REO_CMD_FLG_NEED_STATUS;
+ cmd.addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
+ cmd.addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
+ /* Keep the queue descriptor valid until the delete completion path
+ * flushes it from the REO cache. Clearing VLD here can make the
+ * subsequent flush-cache command fail.
+ */
+ cmd.upd0 |= HAL_REO_CMD_UPD0_VLD;
+ cmd.upd1 |= HAL_REO_CMD_UPD1_VLD;
+
+ return ath12k_wifi8_dp_reo_cmd_send(ab, rx_tid, sizeof(*rx_tid),
+ HAL_REO_CMD_UPDATE_RX_QUEUE, &cmd,
+ ath12k_dp_rx_tid_del_func);
+}
+
+void ath12k_wifi8_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid,
+ bool rel_link_desc)
+{
+ enum hal_wbm_rel_bm_act act = HAL_WBM_REL_BM_ACT_PUT_IN_IDLE;
+ struct ath12k_buffer_addr *buf_addr_info;
+ struct ath12k_dp *dp = rx_tid->dp;
+
+ lockdep_assert_held(&dp->dp_lock);
+
+ if (rx_tid->dst_ring_desc) {
+ if (rel_link_desc) {
+ buf_addr_info = &rx_tid->dst_ring_desc->buf_addr_info;
+ ath12k_wifi8_dp_rx_link_desc_return(dp, buf_addr_info,
+ act);
+ }
+
+ kfree(rx_tid->dst_ring_desc);
+ rx_tid->dst_ring_desc = NULL;
+ }
+
+ rx_tid->cur_sn = 0;
+ rx_tid->last_frag_no = 0;
+ rx_tid->rx_frag_bitmap = 0;
+ __skb_queue_purge(&rx_tid->rx_frags);
+}
+
+void ath12k_wifi8_dp_setup_pn_check_reo_cmd(struct ath12k_hal_reo_cmd *cmd,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 cipher,
+ enum set_key_cmd key_cmd)
+{
+ cmd->flag = HAL_REO_CMD_FLG_NEED_STATUS;
+ cmd->upd0 = HAL_REO_CMD_UPD0_PN |
+ HAL_REO_CMD_UPD0_PN_SIZE |
+ HAL_REO_CMD_UPD0_PN_VALID |
+ HAL_REO_CMD_UPD0_PN_CHECK |
+ HAL_REO_CMD_UPD0_SVLD;
+
+ switch (cipher) {
+ case WLAN_CIPHER_SUITE_TKIP:
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_CCMP_256:
+ case WLAN_CIPHER_SUITE_GCMP:
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ if (key_cmd == SET_KEY) {
+ cmd->upd1 |= HAL_REO_CMD_UPD1_PN_CHECK;
+ cmd->pn_size = 48;
+ }
+ break;
+ default:
+ break;
+ }
+
+ cmd->addr_lo = lower_32_bits(rx_tid->qbuf.paddr_aligned);
+ cmd->addr_hi = upper_32_bits(rx_tid->qbuf.paddr_aligned);
+}
+
/**
* ath12k_wifi8_rx_spd_buf_alloc - allocate per-ring SPD scratch-pad arrays
* @dp_hw_grp_wifi8: Wi-Fi 8 hardware-group private data
@@ -1318,10 +1599,9 @@ ath12k_wifi8_hal_rx_msdu_link_info_get(struct hal_wifi8_rx_msdu_link *link,
* ath12k_wifi8_dp_rx_link_desc_return - return a link descriptor to the WBM
* idle pool.
*/
-static int
-ath12k_wifi8_dp_rx_link_desc_return(struct ath12k_dp *dp,
- struct ath12k_buffer_addr *buf_addr_info,
- enum hal_wbm_rel_bm_act action)
+int ath12k_wifi8_dp_rx_link_desc_return(struct ath12k_dp *dp,
+ struct ath12k_buffer_addr *buf_addr_info,
+ enum hal_wbm_rel_bm_act action)
{
struct ath12k_base *ab = dp->ab;
struct hal_wbm_release_ring *desc;
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
index 2fb56776adb0..c5ee01e703a5 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h
@@ -8,6 +8,7 @@
#define ATH12K_DP_RX_WIFI8_H
#include "../core.h"
+#include "../dp_rx.h"
#include "hal_desc.h"
struct ath12k_dp_hw_group_wifi8;
@@ -171,6 +172,36 @@ int ath12k_wifi8_dp_reo_cmd_send_highprio_n(struct ath12k_base *ab,
struct ath12k_reo_cmd_entry *entries,
struct ath12k_reo_dp_cmd_desc *dp_descs,
int n);
+void ath12k_wifi8_dp_setup_pn_check_reo_cmd(struct ath12k_hal_reo_cmd *cmd,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 cipher,
+ enum set_key_cmd key_cmd);
+int ath12k_wifi8_dp_rx_assign_reoq(struct ath12k_base *ab,
+ struct ath12k_dp_peer *dp_peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u16 ssn, enum hal_pn_type pn_type);
+int ath12k_wifi8_dp_rx_link_desc_return(struct ath12k_dp *dp,
+ struct ath12k_buffer_addr *buf_addr_info,
+ enum hal_wbm_rel_bm_act action);
+void ath12k_wifi8_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid,
+ bool rel_link_desc);
+void ath12k_wifi8_peer_rx_tid_qref_setup(struct ath12k_base *ab,
+ u16 peer_id, u16 tid,
+ dma_addr_t paddr);
+void ath12k_wifi8_dp_rx_peer_tid_delete(struct ath12k_base *ab,
+ struct ath12k_dp_link_peer *peer,
+ u8 tid);
+int ath12k_wifi8_dp_reo_cache_flush(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid);
+int ath12k_wifi8_peer_rx_tid_reo_update(struct ath12k_dp *dp,
+ struct ath12k_dp_link_peer *peer,
+ struct ath12k_dp_rx_tid *rx_tid,
+ u32 ba_win_sz, u16 ssn,
+ bool update_ssn);
+void ath12k_wifi8_peer_rx_tid_qref_reset(struct ath12k_base *ab,
+ u16 peer_id, u16 tid);
+int ath12k_wifi8_dp_rx_tid_delete_handler(struct ath12k_base *ab,
+ struct ath12k_dp_rx_tid_rxq *rx_tid);
int ath12k_wifi8_dp_rx_ring_setup(struct ath12k_base *ab);
int ath12k_wifi8_dp_rx_ring_free(struct ath12k_base *ab);
int ath12k_wifi8_dp_rxdma_ring_sel_config_qcn9625(struct ath12k_base *ab);
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 12/13] wifi: ath12k: ng: wire RX TID REO operations
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (10 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 11/13] wifi: ath12k: ng: add RX TID REO helpers Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 13/13] wifi: ath12k: ng: use global dp peer id for REO TID setup Pradeep Kumar Chitrapu
2026-11-04 2:26 ` [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Jeff Johnson
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
RX TID setup fails on Wi-Fi 8 while the architecture hooks are empty,
so common peer setup falls back to paths that cannot program QCN9625 REO
queue descriptors.
Install the Wi-Fi 8 RX TID hooks, initialize the REO command/list locks
used by those paths, and enable REO queue LUT support for QCN9625. Expose
the single Wi-Fi 8 REO LUT through the expected ML pointer so common qref
programming can use the same address table.
Tested-on: Compilation only, M=drivers/net/wireless/ath/ath12k
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/wifi8/dp.c | 18 ++++++++++++++++++
drivers/net/wireless/ath/ath12k/wifi8/hw.c | 1 +
2 files changed, 19 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp.c b/drivers/net/wireless/ath/ath12k/wifi8/dp.c
index e89826f33206..1e636e79fc32 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp.c
@@ -197,6 +197,9 @@ static int ath12k_wifi8_dp_reoq_lut_setup(struct ath12k_base *ab)
ath12k_hal_write_reoq_lut_addr(ab, dp->reoq_lut.paddr >> 8);
ath12k_hal_write_ml_reoq_lut_addr(ab, dp->reoq_lut.paddr >> 8);
+ dp->ml_reoq_lut.vaddr = dp->reoq_lut.vaddr;
+ dp->ml_reoq_lut.paddr = dp->reoq_lut.paddr;
+
ath12k_hal_reoq_lut_addr_read_enable(ab);
ath12k_hal_reoq_lut_set_max_peerid(ab);
@@ -215,6 +218,10 @@ static void ath12k_wifi8_dp_reoq_lut_cleanup(struct ath12k_base *ab)
dp->reoq_lut.vaddr_unaligned,
dp->reoq_lut.paddr_unaligned);
dp->reoq_lut.vaddr_unaligned = NULL;
+ dp->reoq_lut.vaddr = NULL;
+ dp->reoq_lut.paddr = 0;
+ dp->ml_reoq_lut.vaddr = NULL;
+ dp->ml_reoq_lut.paddr = 0;
}
}
@@ -519,6 +526,17 @@ static struct ath12k_dp_arch_ops ath12k_wifi8_dp_arch_ops = {
.dp_op_mlo_init = ath12k_wifi8_dp_op_mlo_init,
.dp_op_mlo_deinit = ath12k_wifi8_dp_op_mlo_deinit,
.service_srng = ath12k_wifi8_dp_service_srng,
+ .reo_cmd_send = ath12k_wifi8_dp_reo_cmd_send,
+ .setup_pn_check_reo_cmd = ath12k_wifi8_dp_setup_pn_check_reo_cmd,
+ .rx_peer_tid_delete = ath12k_wifi8_dp_rx_peer_tid_delete,
+ .reo_cache_flush = ath12k_wifi8_dp_reo_cache_flush,
+ .rx_link_desc_return = ath12k_wifi8_dp_rx_link_desc_return,
+ .rx_frags_cleanup = ath12k_wifi8_dp_rx_frags_cleanup,
+ .peer_rx_tid_reo_update = ath12k_wifi8_peer_rx_tid_reo_update,
+ .rx_assign_reoq = ath12k_wifi8_dp_rx_assign_reoq,
+ .peer_rx_tid_qref_setup = ath12k_wifi8_peer_rx_tid_qref_setup,
+ .peer_rx_tid_qref_reset = ath12k_wifi8_peer_rx_tid_qref_reset,
+ .rx_tid_delete_handler = ath12k_wifi8_dp_rx_tid_delete_handler,
.dp_peer_create = ath12k_wifi8_dp_peer_create,
.dp_peer_delete = ath12k_wifi8_dp_peer_delete,
.dp_link_peer_create = ath12k_wifi8_dp_link_peer_create,
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/hw.c b/drivers/net/wireless/ath/ath12k/wifi8/hw.c
index ed3ac770e754..a7da8b3a44cd 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/hw.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/hw.c
@@ -211,6 +211,7 @@ static const struct ath12k_hw_params ath12k_wifi8_hw_params[] = {
.current_cc_support = false,
.ring_mask = &ath12k_wifi8_hw_ring_mask_qcn9625,
+ .reoq_lut_support = true,
.num_tcl_banks = 128,
},
};
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH ath-next v3 13/13] wifi: ath12k: ng: use global dp peer id for REO TID setup
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (11 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 12/13] wifi: ath12k: ng: wire RX TID REO operations Pradeep Kumar Chitrapu
@ 2026-11-04 1:10 ` Pradeep Kumar Chitrapu
2026-11-04 2:26 ` [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Jeff Johnson
13 siblings, 0 replies; 15+ messages in thread
From: Pradeep Kumar Chitrapu @ 2026-11-04 1:10 UTC (permalink / raw)
To: Jeff Johnson, Ripan Deuri, Pavankumar Nandeshwar,
Vasanthakumar Thiagarajan, Baochen Qiang, ath12k-review
Cc: Pradeep Kumar Chitrapu, linux-wireless, ath12k, linux-kernel,
Jeff Johnson
Wi-Fi 8 link peers can keep the firmware peer id invalid while the REO
queue LUT is indexed by the host-allocated global dp_peer id.
If RX TID setup uses only the link peer id, station add can fail before
REOQ LUT programming. Thread the resolved dp_peer through peer setup and
RX TID setup, prefer the global dp_peer id on global-peer-id devices, and
keep the pending REO update cleanup keyed by the same id.
Cache the Wi-Fi 8 dp_peer on ath12k_sta with RCU accessors so later RX
TID operations can find the global peer directly, and clear it during peer
delete. Preserve the Wi-Fi 8 stale saved link descriptor guard too.
Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/core.h | 2 +
drivers/net/wireless/ath/ath12k/dp.c | 10 ++-
drivers/net/wireless/ath/ath12k/dp.h | 4 +-
drivers/net/wireless/ath/ath12k/dp_cmn.h | 6 ++
drivers/net/wireless/ath/ath12k/dp_peer.c | 14 +++
drivers/net/wireless/ath/ath12k/dp_peer.h | 4 +-
drivers/net/wireless/ath/ath12k/dp_rx.c | 108 +++++++++++++++++++-----
drivers/net/wireless/ath/ath12k/dp_rx.h | 8 +-
drivers/net/wireless/ath/ath12k/mac.c | 15 +++-
drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c | 16 +++-
drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c | 15 +++-
11 files changed, 169 insertions(+), 33 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 337cb4b1c386..1cd388f613f1 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -537,6 +537,8 @@ struct ath12k_sta {
u8 assoc_link_id;
u16 ml_peer_id;
u16 dp_peer_id;
+ /* Opaque RCU pointer to ath12k_dp_peer */
+ void __rcu *dp_peer;
bool is_mlo;
u16 free_logical_link_idx_map;
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index 4ab5daccd4f2..496eabe61119 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -44,7 +44,8 @@ void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr)
spin_unlock_bh(&dp->dp_lock);
}
-int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr)
+int ath12k_dp_peer_setup(struct ath12k *ar, struct ath12k_dp_peer *dp_peer,
+ int vdev_id, const u8 *addr)
{
struct ath12k_base *ab = ar->ab;
struct ath12k_dp_link_peer *peer;
@@ -52,6 +53,9 @@ int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr)
int ret = 0, tid;
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ if (!dp_peer)
+ return -ENOENT;
+
/* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */
reo_dest = ar->dp.mac_id + 1;
ret = ath12k_wmi_set_peer_param(ar, addr, vdev_id,
@@ -65,8 +69,8 @@ int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr)
}
for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) {
- ret = ath12k_dp_rx_peer_tid_setup(ar, addr, vdev_id, tid, 1, 0,
- HAL_PN_TYPE_NONE);
+ ret = ath12k_dp_rx_peer_tid_setup(ar, dp_peer, addr, vdev_id,
+ tid, 1, 0, HAL_PN_TYPE_NONE);
if (ret) {
ath12k_warn(ab, "failed to setup rxd tid queue for tid %d: %d\n",
tid, ret);
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 9dba68f78808..36e2704f309b 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -17,6 +17,7 @@
struct ath12k_base;
struct ath12k_hw;
struct ath12k_dp_link_peer;
+struct ath12k_dp_peer;
struct ath12k_dp;
struct ath12k_vif;
struct ath12k_link_vif;
@@ -969,7 +970,8 @@ static inline void ath12k_dp_arch_dp_link_vif_configure(struct ath12k_dp *dp,
void ath12k_dp_partner_cc_init(struct ath12k_base *ab);
int ath12k_dp_pdev_alloc(struct ath12k_base *ab);
void ath12k_dp_pdev_pre_alloc(struct ath12k *ar);
-int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr);
+int ath12k_dp_peer_setup(struct ath12k *ar, struct ath12k_dp_peer *dp_peer,
+ int vdev_id, const u8 *addr);
void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr);
void ath12k_dp_srng_cleanup(struct ath12k_base *ab, struct dp_srng *ring);
int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring,
diff --git a/drivers/net/wireless/ath/ath12k/dp_cmn.h b/drivers/net/wireless/ath/ath12k/dp_cmn.h
index 7075963251d2..79a3ad05900c 100644
--- a/drivers/net/wireless/ath/ath12k/dp_cmn.h
+++ b/drivers/net/wireless/ath/ath12k/dp_cmn.h
@@ -12,6 +12,9 @@
#define ATH12K_DP_REO_DST_RING_MAX MIN(NR_CPUS, 5)
struct ath12k_hw_group;
+struct ath12k_dp_peer;
+struct ath12k_sta;
+struct wiphy;
/*
* ML Peer IDs start from 8192, assuming max SLO clients count 1536,
@@ -145,4 +148,7 @@ ath12k_dp_link_peer_get_sta_rate_info_stats(struct ath12k_dp *dp, const u8 *addr
void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr);
u16 ath12k_dp_peer_get_peer_id(struct ath12k_dp_hw *dp_hw, u8 *addr);
u16 ath12k_dp_peer_get_sta_id(struct ath12k_dp_hw *dp_hw, u8 *addr);
+struct ath12k_dp_peer *
+ath12k_sta_get_dp_peer_wiphy_locked(struct wiphy *wiphy,
+ struct ath12k_sta *ahsta);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c
index 58b8b3ab5f4b..e4e2eb0719e8 100644
--- a/drivers/net/wireless/ath/ath12k/dp_peer.c
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.c
@@ -522,6 +522,11 @@ int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
* For WiFi7, peer_id is assigned by firmware via the HTT peer map
* event before this point.
*/
+ if (dp->global_peer_id_supported && dp_peer->is_mlo) {
+ peer->ml_id = dp_peer->peer_id;
+ peer->mlo = true;
+ }
+
if (peer->peer_id != ATH12K_MLO_PEER_ID_INVALID) {
peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
rcu_assign_pointer(dp_hw->dp_peers[peerid_index], dp_peer);
@@ -655,6 +660,15 @@ void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr)
memset(rx_stats, 0, sizeof(*rx_stats));
}
+struct ath12k_dp_peer *
+ath12k_sta_get_dp_peer_wiphy_locked(struct wiphy *wiphy,
+ struct ath12k_sta *ahsta)
+{
+ lockdep_assert_wiphy(wiphy);
+
+ return wiphy_dereference(wiphy, ahsta->dp_peer);
+}
+
/**
* ath12k_dp_peer_cleanup_all() - Clean up all datapath link peers for a radio.
* @ar: radio instance whose peers to clean up
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h
index 5ef14ed24113..19f6a47acbb1 100644
--- a/drivers/net/wireless/ath/ath12k/dp_peer.h
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.h
@@ -159,8 +159,8 @@ struct ath12k_dp_peer {
/* Info used in MMIC verification of * RX fragments */
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS];
- struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
- struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
+ struct ath12k_reoq_buf reoq_bufs[ATH12K_MAX_TIDS];
+ struct ath12k_dp_rx_tid rx_tid[ATH12K_MAX_TIDS];
struct ath12k_dp_peer_ext_ctx *peer_ext_ctx;
bool is_vdev_peer;
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index 47a7ec58446a..14755f653f38 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -13,6 +13,7 @@
#include "hw.h"
#include "dp_rx.h"
#include "dp_tx.h"
+#include "dp_cmn.h"
#include "peer.h"
#include "dp_mon.h"
#include "debugfs_htt_stats.h"
@@ -529,6 +530,50 @@ static int ath12k_dp_rx_tid_delete_handler(struct ath12k_base *ab,
return ath12k_dp_arch_rx_tid_delete_handler(dp, rx_tid);
}
+static bool ath12k_dp_rx_peer_id_valid(u16 peer_id)
+{
+ return peer_id != ATH12K_MLO_PEER_ID_INVALID;
+}
+
+static u16 ath12k_dp_rx_tid_peer_id(struct ath12k_dp *dp,
+ struct ath12k_dp_peer *dp_peer,
+ struct ath12k_dp_link_peer *peer)
+{
+ if (dp->global_peer_id_supported) {
+ if (dp_peer && ath12k_dp_rx_peer_id_valid(dp_peer->peer_id))
+ return dp_peer->peer_id;
+
+ if (peer->dp_peer &&
+ ath12k_dp_rx_peer_id_valid(peer->dp_peer->peer_id))
+ return peer->dp_peer->peer_id;
+
+ if (peer->mlo && ath12k_dp_rx_peer_id_valid(peer->ml_id))
+ return peer->ml_id;
+ }
+
+ if (peer->peer_id != ATH12K_MLO_PEER_ID_INVALID)
+ return peer->peer_id;
+
+ if (dp_peer && ath12k_dp_rx_peer_id_valid(dp_peer->peer_id))
+ return dp_peer->peer_id;
+
+ if (peer->dp_peer && ath12k_dp_rx_peer_id_valid(peer->dp_peer->peer_id))
+ return peer->dp_peer->peer_id;
+
+ return ATH12K_MLO_PEER_ID_INVALID;
+}
+
+static u16 ath12k_dp_rx_reo_peer_id(struct ath12k_dp *dp,
+ struct ath12k_dp_peer *dp_peer,
+ struct ath12k_dp_link_peer *peer)
+{
+ if (!dp->global_peer_id_supported && peer->mlo &&
+ peer->ml_id != ATH12K_MLO_PEER_ID_INVALID)
+ return peer->ml_id;
+
+ return ath12k_dp_rx_tid_peer_id(dp, dp_peer, peer);
+}
+
void ath12k_dp_mark_tid_as_inactive(struct ath12k_dp *dp, int peer_id, u8 tid)
{
struct dp_reo_update_rx_queue_elem *elem;
@@ -573,6 +618,7 @@ void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer
}
static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp,
+ struct ath12k_dp_peer *dp_peer,
struct ath12k_dp_link_peer *peer,
struct ath12k_dp_rx_tid *rx_tid)
{
@@ -587,9 +633,11 @@ static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp,
if (!elem)
return -ENOMEM;
- elem->peer_id = peer->peer_id;
- elem->is_ml_peer = peer->mlo;
- elem->ml_peer_id = peer->ml_id;
+ elem->peer_id = ath12k_dp_rx_tid_peer_id(dp, dp_peer, peer);
+ elem->is_ml_peer = !dp->global_peer_id_supported && peer->mlo &&
+ peer->ml_id != ATH12K_MLO_PEER_ID_INVALID;
+ elem->ml_peer_id = elem->is_ml_peer ? peer->ml_id :
+ ATH12K_MLO_PEER_ID_INVALID;
ath12k_dp_init_rx_tid_rxq(&elem->rx_tid, rx_tid,
(peer->rx_tid_active_bitmask & (1 << rx_tid->tid)));
@@ -601,8 +649,10 @@ static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp,
return 0;
}
-int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id,
- u8 tid, u32 ba_win_sz, u16 ssn,
+int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar,
+ struct ath12k_dp_peer *dp_peer,
+ const u8 *peer_mac, int vdev_id, u8 tid,
+ u32 ba_win_sz, u16 ssn,
enum hal_pn_type pn_type)
{
struct ath12k_base *ab = ar->ab;
@@ -610,17 +660,27 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
struct ath12k_dp_link_peer *peer;
struct ath12k_dp_rx_tid *rx_tid;
dma_addr_t paddr_aligned;
+ u16 reo_peer_id;
int ret;
spin_lock_bh(&dp->dp_lock);
peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac);
- if (!peer || !peer->dp_peer) {
+ if (!peer) {
spin_unlock_bh(&dp->dp_lock);
ath12k_warn(ab, "failed to find the peer to set up rx tid\n");
return -ENOENT;
}
+ if (!dp_peer)
+ dp_peer = peer->dp_peer;
+
+ if (!dp_peer) {
+ spin_unlock_bh(&dp->dp_lock);
+ ath12k_warn(ab, "failed to find dp peer to set up rx tid\n");
+ return -ENOENT;
+ }
+
if (ab->hw_params->dp_primary_link_only &&
!peer->primary_link) {
spin_unlock_bh(&dp->dp_lock);
@@ -634,14 +694,22 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
return -EINVAL;
}
- if (peer->peer_id > DP_MAX_PEER_ID || tid > IEEE80211_NUM_TIDS) {
- ath12k_warn(ab, "peer id of peer %d or tid %d doesn't allow reoq setup\n",
- peer->peer_id, tid);
+ reo_peer_id = ath12k_dp_rx_reo_peer_id(dp, dp_peer, peer);
+
+ if ((reo_peer_id & ~ATH12K_PEER_ML_ID_VALID) > DP_MAX_PEER_ID ||
+ tid > IEEE80211_NUM_TIDS) {
+ ath12k_warn(ab,
+ "reo peer id %d or tid %d doesn't allow reoq setup global %d dp_peer_id %u link_dp_peer_id %u link_peer_id %u ml_id %u mlo %d primary %d\n",
+ reo_peer_id, tid, dp->global_peer_id_supported,
+ dp_peer ? dp_peer->peer_id : ATH12K_MLO_PEER_ID_INVALID,
+ peer->dp_peer ? peer->dp_peer->peer_id :
+ ATH12K_MLO_PEER_ID_INVALID,
+ peer->peer_id, peer->ml_id, peer->mlo, peer->primary_link);
spin_unlock_bh(&dp->dp_lock);
return -EINVAL;
}
- rx_tid = &peer->dp_peer->rx_tid[tid];
+ rx_tid = &dp_peer->rx_tid[tid];
/* Update the tid queue if it is already setup */
if (peer->rx_tid_active_bitmask & (1 << tid)) {
ret = ath12k_dp_arch_peer_rx_tid_reo_update(dp, peer, rx_tid,
@@ -672,7 +740,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
rx_tid->ba_win_sz = ba_win_sz;
- ret = ath12k_dp_arch_rx_assign_reoq(dp, peer->dp_peer, rx_tid, ssn, pn_type);
+ ret = ath12k_dp_arch_rx_assign_reoq(dp, dp_peer, rx_tid, ssn, pn_type);
if (ret) {
spin_unlock_bh(&dp->dp_lock);
ath12k_warn(ab, "failed to assign reoq buf for rx tid %u\n", tid);
@@ -686,7 +754,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
* allocating during tid delete is that, if any alloc fail in update_rxq_list
* we may not be able to delete the tid vaddr/paddr and may lead to leak
*/
- ret = ath12k_dp_prepare_reo_update_elem(dp, peer, rx_tid);
+ ret = ath12k_dp_prepare_reo_update_elem(dp, dp_peer, peer, rx_tid);
if (ret) {
ath12k_warn(ab, "failed to alloc update_rxq_list for rx tid %u\n", tid);
ath12k_dp_rx_tid_cleanup(ab, &rx_tid->qbuf);
@@ -699,12 +767,8 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
/* Update the REO queue LUT at the corresponding peer id
* and tid with qaddr.
*/
- if (peer->mlo)
- ath12k_dp_arch_peer_rx_tid_qref_setup(dp, peer->ml_id, tid,
- paddr_aligned);
- else
- ath12k_dp_arch_peer_rx_tid_qref_setup(dp, peer->peer_id, tid,
- paddr_aligned);
+ ath12k_dp_arch_peer_rx_tid_qref_setup(dp, reo_peer_id, tid,
+ paddr_aligned);
spin_unlock_bh(&dp->dp_lock);
} else {
@@ -724,6 +788,7 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
struct ath12k_base *ab = ar->ab;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
struct ath12k_link_sta *arsta;
+ struct ath12k_dp_peer *dp_peer;
int vdev_id;
int ret;
@@ -736,7 +801,12 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
vdev_id = arsta->arvif->vdev_id;
- ret = ath12k_dp_rx_peer_tid_setup(ar, arsta->addr, vdev_id,
+ dp_peer = ath12k_sta_get_dp_peer_wiphy_locked(ath12k_ar_to_hw(ar)->wiphy,
+ ahsta);
+ if (!dp_peer)
+ return -ENOENT;
+
+ ret = ath12k_dp_rx_peer_tid_setup(ar, dp_peer, arsta->addr, vdev_id,
params->tid, params->buf_size,
params->ssn, arsta->ahsta->pn_type);
if (ret)
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h
index f523ac48747f..a76b79549924 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.h
@@ -10,8 +10,10 @@
#include "debug.h"
#define DP_MAX_NWIFI_HDR_LEN 30
+#define ATH12K_MAX_TIDS (IEEE80211_NUM_TIDS + 1)
struct hal_reo_status;
+struct ath12k_dp_peer;
struct ath12k_reoq_buf {
void *vaddr;
@@ -232,8 +234,10 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer *peer);
void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar,
struct ath12k_dp_link_peer *peer, u8 tid);
-int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id,
- u8 tid, u32 ba_win_sz, u16 ssn,
+int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar,
+ struct ath12k_dp_peer *dp_peer,
+ const u8 *peer_mac, int vdev_id, u8 tid,
+ u32 ba_win_sz, u16 ssn,
enum hal_pn_type pn_type);
int ath12k_dp_rxdma_ring_buf_setup(struct ath12k_base *ab,
struct dp_rxdma_ring *rx_ring);
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 77343469ccca..37c17a97d5aa 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -7177,6 +7177,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
struct ath12k_wmi_peer_create_arg peer_param = {};
int ret;
struct ath12k_link_sta *temp_arsta;
+ struct ath12k_dp_peer *dp_peer;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -7235,7 +7236,19 @@ static int ath12k_mac_station_add(struct ath12k *ar,
}
}
- ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, arsta->addr);
+ dp_peer = ath12k_sta_get_dp_peer_wiphy_locked(ath12k_ar_to_hw(ar)->wiphy,
+ arsta->ahsta);
+ if (!dp_peer || dp_peer->peer_id == ATH12K_MLO_PEER_ID_INVALID) {
+ spin_lock_bh(&ar->ah->dp_hw.peer_lock);
+ dp_peer = ath12k_dp_peer_find_by_addr_and_sta(&ar->ah->dp_hw,
+ sta->addr, sta);
+ if (!dp_peer)
+ dp_peer = ath12k_dp_peer_find_by_addr_and_sta(&ar->ah->dp_hw,
+ arsta->addr,
+ sta);
+ spin_unlock_bh(&ar->ah->dp_hw.peer_lock);
+ }
+ ret = ath12k_dp_peer_setup(ar, dp_peer, arvif->vdev_id, arsta->addr);
if (ret) {
ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n",
arsta->addr, arvif->vdev_id, ret);
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c b/drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c
index a89086ca15c1..2006a862feb2 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c
@@ -319,7 +319,8 @@ int ath12k_wifi8_dp_peer_create(struct ath12k_hw *ah, u8 *addr,
struct ath12k_dp_hw *dp_hw = &ah->dp_hw;
struct ath12k_sta *ahsta = NULL;
- ahsta = ath12k_sta_to_ahsta(params->sta);
+ if (params->sta)
+ ahsta = ath12k_sta_to_ahsta(params->sta);
spin_lock_bh(&dp_hw->peer_lock);
dp_peer = ath12k_dp_peer_find_by_addr(dp_hw, addr);
@@ -375,7 +376,10 @@ int ath12k_wifi8_dp_peer_create(struct ath12k_hw *ah, u8 *addr,
dp_peer->hw_link_id = params->hw_link_id;
} else {
dp_peer->assoc_hw_link_id = params->hw_link_id;
- ahsta->dp_peer_id = dp_peer->peer_id;
+ if (ahsta) {
+ ahsta->dp_peer_id = dp_peer->peer_id;
+ rcu_assign_pointer(ahsta->dp_peer, dp_peer);
+ }
}
dp_peer->is_sta_bss_peer = params->is_sta_bss_peer;
@@ -410,15 +414,19 @@ void ath12k_wifi8_dp_peer_delete(struct ath12k_dp *dp, struct ath12k_hw *ah, u8
struct ath12k_base *central_ab = NULL;
struct ath12k_dp_wifi8 *dp_wifi8 = NULL;
struct hal_srng *srng = NULL;
+ struct ath12k_sta *ahsta;
int i, ret;
dp_hw_grp_wifi8 = ath12k_get_dp_hw_group_wifi8(dp->dp_hw_grp);
spin_lock_bh(&dp_hw->peer_lock);
- if (sta)
+ if (sta) {
+ ahsta = ath12k_sta_to_ahsta(sta);
+ rcu_assign_pointer(ahsta->dp_peer, NULL);
dp_peer = ath12k_dp_peer_find_by_addr_and_sta(dp_hw, addr, sta);
- else
+ } else {
dp_peer = ath12k_dp_peer_find_by_addr(dp_hw, addr);
+ }
if (!dp_peer) {
spin_unlock_bh(&dp_hw->peer_lock);
diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
index 0b8a9d32e125..c74f070c0d88 100644
--- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c
@@ -364,11 +364,18 @@ void ath12k_wifi8_dp_rx_peer_tid_delete(struct ath12k_base *ab,
u8 tid)
{
struct ath12k_dp *dp = ath12k_ab_to_dp(ab);
+ u16 peer_id = peer->peer_id;
if (!(peer->rx_tid_active_bitmask & BIT(tid)))
return;
- ath12k_dp_mark_tid_as_inactive(dp, peer->peer_id, tid);
+ if (peer_id == ATH12K_MLO_PEER_ID_INVALID && peer->dp_peer)
+ peer_id = peer->dp_peer->peer_id;
+
+ if (peer_id == ATH12K_MLO_PEER_ID_INVALID)
+ return;
+
+ ath12k_dp_mark_tid_as_inactive(dp, peer_id, tid);
ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(dp);
}
@@ -517,6 +524,11 @@ void ath12k_wifi8_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid,
lockdep_assert_held(&dp->dp_lock);
if (rx_tid->dst_ring_desc) {
+ if ((unsigned long)rx_tid->dst_ring_desc < PAGE_SIZE) {
+ rx_tid->dst_ring_desc = NULL;
+ goto clear;
+ }
+
if (rel_link_desc) {
buf_addr_info = &rx_tid->dst_ring_desc->buf_addr_info;
ath12k_wifi8_dp_rx_link_desc_return(dp, buf_addr_info,
@@ -527,6 +539,7 @@ void ath12k_wifi8_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid,
rx_tid->dst_ring_desc = NULL;
}
+clear:
rx_tid->cur_sn = 0;
rx_tid->last_frag_no = 0;
rx_tid->rx_frag_bitmap = 0;
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
` (12 preceding siblings ...)
2026-11-04 1:10 ` [PATCH ath-next v3 13/13] wifi: ath12k: ng: use global dp peer id for REO TID setup Pradeep Kumar Chitrapu
@ 2026-11-04 2:26 ` Jeff Johnson
13 siblings, 0 replies; 15+ messages in thread
From: Jeff Johnson @ 2026-11-04 2:26 UTC (permalink / raw)
To: Pradeep Kumar Chitrapu, Jeff Johnson, Ripan Deuri,
Pavankumar Nandeshwar, Vasanthakumar Thiagarajan, Baochen Qiang,
ath12k-review
Cc: linux-wireless, ath12k, linux-kernel
On 11/3/2026 5:10 PM, Pradeep Kumar Chitrapu wrote:
> Add the Wi-Fi 8 REO command handling needed by the QCN9625 datapath.
> The series introduces the REO command and status descriptors, high
> priority REO command ring support, common command context handling, REO
> status processing, 1K queue statistics parsing, batched command sends,
> REO queue descriptor helpers, qaddr cache clear support and RX TID REO
> operation wiring.
>
> The last patch fixes REO TID setup on Wi-Fi 8 global-peer-ID devices by
> using the host-allocated dp_peer id instead of the invalid link peer id
> when programming REO queue state.
>
> The latest dependency postings found in local mail for this stack are:
>
> Depends-on: [PATCH ath-next v4 00/12] wifi: ath12k: ng: refactor DP and HAL for multi-gen arch-ops
> Message-ID: <20261103163435.2682252-1-praneesh.p@oss.qualcomm.com>
> Depends-on: [PATCH ath-next v3 00/10] wifi: ath12k: ng: Add QCN9625 Wi-Fi 8 HAL register and descriptor definitions
> Message-ID: <20261030120743.2687216-1-praneesh.p@oss.qualcomm.com>
> Depends-on: [PATCH 0/4] wifi: ath12k: ng: Add SAM support for QCN9625
> Message-ID: <20260921090656.1575082-1-aishwarya.r@oss.qualcomm.com>
>
> Signed-off-by: Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
> ---
> Changes in v3:
> - Update the cover letter dependency references to the latest versions
> found in local mail: multi-gen arch-ops v4 and QCN9625 HAL/register
> definitions v3.
> - Clean up the global-peer-ID fix by keeping only the wiphy-locked
> dp_peer accessor needed by the series.
> - Make the dp_peer accessor typed and local to ath12k, and drop the
> unused RCU accessor/export churn from the last patch.
> - Link to v2: https://patch.msgid.link/20261021-reo-cmd-b4-posting-v2-0-e8e3f482bfc9@oss.qualcomm.com
>
> Changes in v2:
> - Use a lock-held helper for Wi-Fi 8 REO command queueing.
> - Document all-or-nothing SRNG pointer rollback for batched REO commands.
> - Use the shared Wi-Fi 8 REO queue-address LUT for qref updates.
> - Link to v1: https://patch.msgid.link/20260923-reo-cmd-b4-posting-v1-0-74935135a2de@oss.qualcomm.com
>
> To: Jeff Johnson <jjohnson@kernel.org>
> To: Ripan Deuri <quic_rdeuri@quicinc.com>
> To: Pavankumar Nandeshwar <quic_pnandesh@quicinc.com>
> To: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
> To: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
> Cc: linux-wireless@vger.kernel.org
> Cc: ath12k@lists.infradead.org
> Cc: linux-kernel@vger.kernel.org
> Cc: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
>
> ---
> Pradeep Kumar Chitrapu (13):
> wifi: ath12k: ng: add REO command and status support
> wifi: ath12k: ng: add high-priority REO command ring
> wifi: ath12k: ng: allocate REO command context before submission
> wifi: ath12k: ng: refactor REO command framework for extensibility
> wifi: ath12k: ng: log successful RX TID queue updates
> wifi: ath12k: ng: parse 1K REO queue statistics
> wifi: ath12k: ng: process REO status ring
> wifi: ath12k: ng: add batched REO command sends
> wifi: ath12k: ng: add REO queue descriptor helpers
> wifi: ath12k: ng: add REO qaddr cache clear support
> wifi: ath12k: ng: add RX TID REO helpers
> wifi: ath12k: ng: wire RX TID REO operations
> wifi: ath12k: ng: use global dp peer id for REO TID setup
>
> drivers/net/wireless/ath/ath12k/core.h | 2 +
> drivers/net/wireless/ath/ath12k/dp.c | 10 +-
> drivers/net/wireless/ath/ath12k/dp.h | 15 +-
> drivers/net/wireless/ath/ath12k/dp_cmn.h | 6 +
> drivers/net/wireless/ath/ath12k/dp_peer.c | 14 +
> drivers/net/wireless/ath/ath12k/dp_peer.h | 4 +-
> drivers/net/wireless/ath/ath12k/dp_rx.c | 138 +++-
> drivers/net/wireless/ath/ath12k/dp_rx.h | 20 +-
> drivers/net/wireless/ath/ath12k/hal.h | 103 +++
> drivers/net/wireless/ath/ath12k/mac.c | 15 +-
> drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 63 +-
> drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 4 +-
> drivers/net/wireless/ath/ath12k/wifi7/hal.h | 94 +--
> drivers/net/wireless/ath/ath12k/wifi8/dp.c | 28 +
> drivers/net/wireless/ath/ath12k/wifi8/dp.h | 1 +
> drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c | 16 +-
> drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c | 643 +++++++++++++++-
> drivers/net/wireless/ath/ath12k/wifi8/dp_rx.h | 57 ++
> drivers/net/wireless/ath/ath12k/wifi8/hal.c | 16 +-
> drivers/net/wireless/ath/ath12k/wifi8/hal.h | 3 +
> drivers/net/wireless/ath/ath12k/wifi8/hal_desc.h | 377 +++++++++-
> .../net/wireless/ath/ath12k/wifi8/hal_qcn9625.c | 1 +
> drivers/net/wireless/ath/ath12k/wifi8/hal_rx.c | 813 +++++++++++++++++++++
> drivers/net/wireless/ath/ath12k/wifi8/hal_rx.h | 103 ++-
> drivers/net/wireless/ath/ath12k/wifi8/hal_tx.h | 9 +
> drivers/net/wireless/ath/ath12k/wifi8/hw.c | 1 +
> 26 files changed, 2347 insertions(+), 209 deletions(-)
> ---
> base-commit: a2fa01354eb39e673f3f09e6c1cec39f82f0f9ae
> change-id: 20260923-reo-cmd-b4-posting-af227314a3b5
> prerequisite-patch-id: 49882cc69530a316a86f617b0b8649c3e753fc39
> prerequisite-patch-id: 6fe238c82896b9f8b39fa0f09e32fb72d82ea6e1
> prerequisite-patch-id: f09a16b2b6b388cb3290a14d86f4fbe370929680
> prerequisite-patch-id: f7fab6336752c5a6e2e45221157c05a2845b1057
>
> Best regards,
> --
> Pradeep Kumar Chitrapu <pradeep.chitrapu@oss.qualcomm.com>
All,
This was only supposed to go to the Qualcomm internal list since this is work
in progress. Please ignore.
/jeff
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-11-04 2:26 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04 1:10 [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 01/13] wifi: ath12k: ng: add REO command and status support Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 02/13] wifi: ath12k: ng: add high-priority REO command ring Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 03/13] wifi: ath12k: ng: allocate REO command context before submission Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 04/13] wifi: ath12k: ng: refactor REO command framework for extensibility Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 05/13] wifi: ath12k: ng: log successful RX TID queue updates Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 06/13] wifi: ath12k: ng: parse 1K REO queue statistics Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 07/13] wifi: ath12k: ng: process REO status ring Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 08/13] wifi: ath12k: ng: add batched REO command sends Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 09/13] wifi: ath12k: ng: add REO queue descriptor helpers Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 10/13] wifi: ath12k: ng: add REO qaddr cache clear support Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 11/13] wifi: ath12k: ng: add RX TID REO helpers Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 12/13] wifi: ath12k: ng: wire RX TID REO operations Pradeep Kumar Chitrapu
2026-11-04 1:10 ` [PATCH ath-next v3 13/13] wifi: ath12k: ng: use global dp peer id for REO TID setup Pradeep Kumar Chitrapu
2026-11-04 2:26 ` [PATCH ath-next v3 00/13] wifi: ath12k: ng: add Wi-Fi 8 REO command support Jeff Johnson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®