[PATCH ath-next v3 02/13] wifi: ath12k: ng: add high-priority REO command ring

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


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 at 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, &central_ab->dev_flags) ||
+	    test_bit(ATH12K_FLAG_RECOVERY, &central_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(&central_dp->reo_cmd_lock);
+	list_add_tail(&dp_cmd->list, &central_dp->reo_cmd_list);
+	spin_unlock_bh(&central_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 = &central_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 = &central_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




More information about the ath12k mailing list