Przeglądaj źródła

qcacmn: Replenish last entry in monitor status ring

In current monitor status ring implementation,
on pdev_attach, (srng->num_entires – 1) entries
(to keep one entry slot between hp and tp)
are replenished and last entry is not replenished to HW.

With qcn9000 monitor mode HW enhancements, status and destination ring
can be made lock-stepped.
for qcn9000 lock step is achieved by making monitor status ring
follow the monitor destination reap for a PPDU

However in existing flow during attach monitor status replenish logic
do not fill last entry but is filled up during first subsequent reap.
for first ppdu, i.e. after reaping destination ring,
when status ring is reaped, as first entry (hp = srng->num_entires – 1)
in status ring is NULL, so lock-stepping is not achieved.

To address this issue for qcn9000 as well as HK:
	a. Replenish last entry in monitor status ring during attach
	b. Modify src srng peek API to peek it from hp+1 entry
	c. Introduce new HAL API get cur desc and move next
	d. Remove WAR to skip status ring entries if DMA is not done

Change-Id: I60b8e7c075253d37e6b849a9b24f473c5afce82c
CRs-Fixed: 2626049
Amir Patel 5 lat temu
rodzic
commit
e919b20a34
2 zmienionych plików z 57 dodań i 11 usunięć
  1. 21 7
      dp/wifi3.0/dp_rx_mon_status.c
  2. 36 4
      hal/wifi3.0/hal_api.h

+ 21 - 7
dp/wifi3.0/dp_rx_mon_status.c

@@ -1681,7 +1681,7 @@ dp_rx_mon_status_srng_process(struct dp_soc *soc, uint32_t mac_id,
 	 * BUFFER_ADDR_INFO STRUCT
 	 */
 	while (qdf_likely((rxdma_mon_status_ring_entry =
-		hal_srng_src_peek(hal_soc, mon_status_srng))
+		hal_srng_src_peek_n_get_next(hal_soc, mon_status_srng))
 			&& quota--)) {
 		uint32_t rx_buf_cookie;
 		qdf_nbuf_t status_nbuf;
@@ -1722,9 +1722,22 @@ dp_rx_mon_status_srng_process(struct dp_soc *soc, uint32_t mac_id,
 				dp_info_rl("tlv tag status error hp:%u, tp:%u",
 					   hp, tp);
 				pdev->rx_mon_stats.tlv_tag_status_err++;
-				/* WAR for missing status: Skip status entry */
-				hal_srng_src_get_next(hal_soc, mon_status_srng);
-				continue;
+
+				/* RxDMA status done bit might not be set even
+				 * though tp is moved by HW.
+				 * So Hold on to current entry on
+				 * monitor status ring
+				 */
+
+				/* If done status is missing, hold onto status
+				 * ring until status is done for this status
+				 * ring buffer.
+				 * Keep HP in mon_status_ring unchanged,
+				 * and break from here.
+				 * Check status for same buffer for next time
+				 * dp_rx_mon_status_srng_process
+				 */
+				break;
 			}
 			qdf_nbuf_set_pktlen(status_nbuf, RX_DATA_BUFFER_SIZE);
 
@@ -1965,7 +1978,7 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc,
 		num_req_buffers = num_entries_avail;
 	}
 
-	while (count < num_req_buffers) {
+	while (count <= num_req_buffers) {
 		rx_netbuf = dp_rx_nbuf_prepare(dp_soc, dp_pdev);
 
 		/*
@@ -1984,8 +1997,9 @@ QDF_STATUS dp_rx_mon_status_buffers_replenish(struct dp_soc *dp_soc,
 		paddr = qdf_nbuf_get_frag_paddr(rx_netbuf, 0);
 
 		next = (*desc_list)->next;
-		rxdma_ring_entry = hal_srng_src_get_next(dp_soc->hal_soc,
-							 rxdma_srng);
+		rxdma_ring_entry = hal_srng_src_get_cur_hp_n_move_next(
+						dp_soc->hal_soc,
+						rxdma_srng);
 
 		if (qdf_unlikely(!rxdma_ring_entry)) {
 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,

+ 36 - 4
hal/wifi3.0/hal_api.h

@@ -1389,7 +1389,8 @@ void *hal_srng_src_get_next(void *hal_soc,
 }
 
 /**
- * hal_srng_src_peek - Get next entry from a ring without moving head pointer.
+ * hal_srng_src_peek_n_get_next - Get next entry from a ring without
+ * moving head pointer.
  * hal_srng_src_get_next should be called subsequently to move the head pointer
  *
  * @hal_soc: Opaque HAL SOC handle
@@ -1398,8 +1399,8 @@ void *hal_srng_src_get_next(void *hal_soc,
  * Return: Opaque pointer for next ring entry; NULL on failire
  */
 static inline
-void *hal_srng_src_peek(hal_soc_handle_t hal_soc_hdl,
-			hal_ring_handle_t hal_ring_hdl)
+void *hal_srng_src_peek_n_get_next(hal_soc_handle_t hal_soc_hdl,
+				   hal_ring_handle_t hal_ring_hdl)
 {
 	struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl;
 	uint32_t *desc;
@@ -1412,13 +1413,44 @@ void *hal_srng_src_peek(hal_soc_handle_t hal_soc_hdl,
 	 */
 	if (((srng->u.src_ring.hp + srng->entry_size) %
 		srng->ring_size) != srng->u.src_ring.cached_tp) {
-		desc = &(srng->ring_base_vaddr[srng->u.src_ring.hp]);
+		desc = &(srng->ring_base_vaddr[(srng->u.src_ring.hp +
+						srng->entry_size) %
+						srng->ring_size]);
 		return (void *)desc;
 	}
 
 	return NULL;
 }
 
+/**
+ * hal_srng_src_get_cur_hp_n_move_next () - API returns current hp
+ * and move hp to next in src ring
+ *
+ * Usage: This API should only be used at init time replenish.
+ *
+ * @hal_soc_hdl: HAL soc handle
+ * @hal_ring_hdl: Source ring pointer
+ *
+ */
+static inline void *
+hal_srng_src_get_cur_hp_n_move_next(hal_soc_handle_t hal_soc_hdl,
+				    hal_ring_handle_t hal_ring_hdl)
+{
+	struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl;
+	uint32_t *cur_desc = NULL;
+	uint32_t next_hp;
+
+	cur_desc = &srng->ring_base_vaddr[(srng->u.src_ring.hp)];
+
+	next_hp = (srng->u.src_ring.hp + srng->entry_size) %
+		srng->ring_size;
+
+	if (next_hp != srng->u.src_ring.cached_tp)
+		srng->u.src_ring.hp = next_hp;
+
+	return (void *)cur_desc;
+}
+
 /**
  * hal_srng_src_num_avail - Returns number of available entries in src ring
  *