[PATCH ath-next v3 07/13] wifi: ath12k: ng: process REO status ring

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


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 at 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




More information about the ath12k mailing list