[PATCH ath-next v3 02/13] wifi: ath12k: ng: add high-priority REO command ring
From: Pradeep Kumar Chitrapu
Date: Tue Nov 03 2026 - 20:12:25 EST
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@xxxxxxxxxxxxxxxx>
---
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