Browse Source

qcacmn: Add near-full irq processing handler for RX ring

Add the handler to process the near-full condition
on the rx ring.

Change-Id: I426480386c4716702f8410ed87c70160decaa03f
CRs-Fixed: 2965081
Rakesh Pillai 4 years ago
parent
commit
5605d45923
7 changed files with 200 additions and 38 deletions
  1. 111 0
      dp/wifi3.0/be/dp_be.h
  2. 32 2
      dp/wifi3.0/be/dp_be_rx.c
  3. 0 33
      dp/wifi3.0/dp_rx.c
  4. 48 2
      dp/wifi3.0/dp_rx.h
  5. 2 0
      dp/wifi3.0/dp_types.h
  6. 4 1
      dp/wifi3.0/li/dp_li_rx.c
  7. 3 0
      hal/wifi3.0/hal_api.h

+ 111 - 0
dp/wifi3.0/be/dp_be.h

@@ -368,4 +368,115 @@ static inline void *dp_cc_desc_find(struct dp_soc *soc,
 
 	return (void *)(uintptr_t)(*(spt_page_va  + spt_va_id));
 }
+
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+/**
+ * enum dp_srng_near_full_levels - SRNG Near FULL levels
+ * @DP_SRNG_THRESH_SAFE: SRNG level safe for yielding the near full mode
+ *		of processing the entries in SRNG
+ * @DP_SRNG_THRESH_NEAR_FULL: SRNG level enters the near full mode
+ *		of processing the entries in SRNG
+ * @DP_SRNG_THRESH_CRITICAL: SRNG level enters the critical level of full
+ *		condition and drastic steps need to be taken for processing
+ *		the entries in SRNG
+ */
+enum dp_srng_near_full_levels {
+	DP_SRNG_THRESH_SAFE,
+	DP_SRNG_THRESH_NEAR_FULL,
+	DP_SRNG_THRESH_CRITICAL,
+};
+
+/**
+ * dp_srng_check_ring_near_full() - Check if SRNG is marked as near-full from
+ *				its corresponding near-full irq handler
+ * @soc: Datapath SoC handle
+ * @dp_srng: datapath handle for this SRNG
+ *
+ * Return: 1, if the srng was marked as near-full
+ *	   0, if the srng was not marked as near-full
+ */
+static inline int dp_srng_check_ring_near_full(struct dp_soc *soc,
+					       struct dp_srng *dp_srng)
+{
+	return qdf_atomic_read(&dp_srng->near_full);
+}
+
+/**
+ * dp_srng_get_near_full_level() - Check the num available entries in the
+ *			consumer srng and return the level of the srng
+ *			near full state.
+ * @soc: Datapath SoC Handle [To be validated by the caller]
+ * @hal_ring_hdl: SRNG handle
+ *
+ * Return: near-full level
+ */
+static inline int
+dp_srng_get_near_full_level(struct dp_soc *soc, struct dp_srng *dp_srng)
+{
+	uint32_t num_valid;
+
+	num_valid = hal_srng_dst_num_valid_nolock(soc->hal_soc,
+						  dp_srng->hal_srng,
+						  true);
+
+	if (num_valid > dp_srng->crit_thresh)
+		return DP_SRNG_THRESH_CRITICAL;
+	else if (num_valid < dp_srng->safe_thresh)
+		return DP_SRNG_THRESH_SAFE;
+	else
+		return DP_SRNG_THRESH_NEAR_FULL;
+}
+
+#define DP_SRNG_PER_LOOP_NF_REAP_MULTIPLIER	2
+
+/**
+ * dp_srng_test_and_update_nf_params() - Test the near full level and update
+ *			the reap_limit and flags to reflect the state.
+ * @soc: Datapath soc handle
+ * @srng: Datapath handle for the srng
+ * @max_reap_limit: [Output Param] Buffer to set the map_reap_limit as
+ *			per the near-full state
+ *
+ * Return: 1, if the srng is near full
+ *	   0, if the srng is not near full
+ */
+static inline int
+dp_srng_test_and_update_nf_params(struct dp_soc *soc,
+				  struct dp_srng *srng,
+				  int *max_reap_limit)
+{
+	int ring_near_full = 0, near_full_level;
+
+	if (dp_srng_check_ring_near_full(soc, srng)) {
+		near_full_level = dp_srng_get_near_full_level(soc, srng);
+		switch (near_full_level) {
+		case DP_SRNG_THRESH_CRITICAL:
+			/* Currently not doing anything special here */
+			/* fall through */
+		case DP_SRNG_THRESH_NEAR_FULL:
+			ring_near_full = 1;
+			*max_reap_limit *= DP_SRNG_PER_LOOP_NF_REAP_MULTIPLIER;
+			break;
+		case DP_SRNG_THRESH_SAFE:
+			qdf_atomic_set(&srng->near_full, 0);
+			ring_near_full = 0;
+			break;
+		default:
+			qdf_assert(0);
+			break;
+		}
+	}
+
+	return ring_near_full;
+}
+#else
+static inline int
+dp_srng_test_and_update_nf_params(struct dp_soc *soc,
+				  struct dp_srng *srng,
+				  int *max_reap_limit)
+{
+	return 0;
+}
+#endif
+
 #endif

+ 32 - 2
dp/wifi3.0/be/dp_be_rx.c

@@ -100,6 +100,8 @@ uint32_t dp_rx_process_be(struct dp_intr *int_ctx,
 	qdf_nbuf_t ebuf_head;
 	qdf_nbuf_t ebuf_tail;
 	uint8_t pkt_capture_offload = 0;
+	struct dp_srng *rx_ring = &soc->reo_dest_ring[reo_ring_num];
+	int max_reap_limit, ring_near_full;
 
 	DP_HIST_INIT();
 
@@ -123,6 +125,8 @@ more_data:
 	num_rx_bufs_reaped = 0;
 	ebuf_head = NULL;
 	ebuf_tail = NULL;
+	ring_near_full = 0;
+	max_reap_limit = dp_rx_get_loop_pkt_limit(soc);
 
 	qdf_mem_zero(rx_bufs_reaped, sizeof(rx_bufs_reaped));
 	qdf_mem_zero(&mpdu_desc_info, sizeof(mpdu_desc_info));
@@ -130,6 +134,9 @@ more_data:
 	qdf_mem_zero(head, sizeof(head));
 	qdf_mem_zero(tail, sizeof(tail));
 
+	ring_near_full = dp_srng_test_and_update_nf_params(soc, rx_ring,
+							   &max_reap_limit);
+
 	if (qdf_unlikely(dp_rx_srng_access_start(int_ctx, soc, hal_ring_hdl))) {
 		/*
 		 * Need API to convert from hal_ring pointer to
@@ -376,7 +383,8 @@ more_data:
 		 * then allow break.
 		 */
 		if (is_prev_msdu_last &&
-		    dp_rx_reap_loop_pkt_limit_hit(soc, num_rx_bufs_reaped))
+		    dp_rx_reap_loop_pkt_limit_hit(soc, num_rx_bufs_reaped,
+						  max_reap_limit))
 			break;
 	}
 done:
@@ -722,6 +730,17 @@ done:
 	if (qdf_likely(peer))
 		dp_peer_unref_delete(peer, DP_MOD_ID_RX);
 
+	/*
+	 * If we are processing in near-full condition, there are 3 scenario
+	 * 1) Ring entries has reached critical state
+	 * 2) Ring entries are still near high threshold
+	 * 3) Ring entries are below the safe level
+	 *
+	 * One more loop will move the state to normal processing and yield
+	 */
+	if (ring_near_full)
+		goto more_data;
+
 	if (dp_rx_enable_eol_data_check(soc) && rx_bufs_used) {
 		if (quota) {
 			num_pending =
@@ -987,6 +1006,17 @@ uint32_t dp_rx_nf_process(struct dp_intr *int_ctx,
 			  uint8_t reo_ring_num,
 			  uint32_t quota)
 {
-	return 0;
+	struct dp_soc *soc = int_ctx->soc;
+	struct dp_srng *rx_ring = &soc->reo_dest_ring[reo_ring_num];
+	uint32_t work_done = 0;
+
+	if (dp_srng_get_near_full_level(soc, rx_ring) <
+			DP_SRNG_THRESH_NEAR_FULL)
+		return 0;
+
+	qdf_atomic_set(&rx_ring->near_full, 1);
+	work_done++;
+
+	return work_done;
 }
 #endif

+ 0 - 33
dp/wifi3.0/dp_rx.c

@@ -1886,39 +1886,6 @@ static inline void
 dp_rx_desc_nbuf_len_sanity_check(struct dp_soc *soc, uint32_t pkt_len) { }
 #endif
 
-#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
-bool dp_rx_reap_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped)
-{
-	bool limit_hit = false;
-	struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx;
-
-	limit_hit =
-		(num_reaped >= cfg->rx_reap_loop_pkt_limit) ? true : false;
-
-	if (limit_hit)
-		DP_STATS_INC(soc, rx.reap_loop_pkt_limit_hit, 1)
-
-	return limit_hit;
-}
-
-bool dp_rx_enable_eol_data_check(struct dp_soc *soc)
-{
-	return soc->wlan_cfg_ctx->rx_enable_eol_data_check;
-}
-
-#else
-bool dp_rx_reap_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped)
-{
-	return false;
-}
-
-bool dp_rx_enable_eol_data_check(struct dp_soc *soc)
-{
-	return false;
-}
-
-#endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */
-
 #ifdef DP_RX_PKT_NO_PEER_DELIVER
 /**
  * dp_rx_deliver_to_stack_no_peer() - try deliver rx data even if

+ 48 - 2
dp/wifi3.0/dp_rx.h

@@ -1949,8 +1949,54 @@ void dp_rx_cksum_offload(struct dp_pdev *pdev,
 
 #endif /* QCA_HOST_MODE_WIFI_DISABLED */
 
-bool dp_rx_reap_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped);
-bool dp_rx_enable_eol_data_check(struct dp_soc *soc);
+#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
+static inline
+bool dp_rx_reap_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped,
+				   int max_reap_limit)
+{
+	bool limit_hit = false;
+
+	limit_hit =
+		(num_reaped >= max_reap_limit) ? true : false;
+
+	if (limit_hit)
+		DP_STATS_INC(soc, rx.reap_loop_pkt_limit_hit, 1)
+
+	return limit_hit;
+}
+
+static inline
+bool dp_rx_enable_eol_data_check(struct dp_soc *soc)
+{
+	return soc->wlan_cfg_ctx->rx_enable_eol_data_check;
+}
+
+static inline int dp_rx_get_loop_pkt_limit(struct dp_soc *soc)
+{
+	struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx;
+
+	return cfg->rx_reap_loop_pkt_limit;
+}
+#else
+static inline
+bool dp_rx_reap_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped,
+				   int max_reap_limit)
+{
+	return false;
+}
+
+static inline
+bool dp_rx_enable_eol_data_check(struct dp_soc *soc)
+{
+	return false;
+}
+
+static inline int dp_rx_get_loop_pkt_limit(struct dp_soc *soc)
+{
+	return 0;
+}
+#endif /* WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT */
+
 void dp_rx_update_stats(struct dp_soc *soc, qdf_nbuf_t nbuf);
 
 #ifdef QCA_SUPPORT_WDS_EXTENDED

+ 2 - 0
dp/wifi3.0/dp_types.h

@@ -671,6 +671,7 @@ struct dp_txrx_pool_stats {
  * @is_mem_prealloc: Is this srng memeory pre-allocated
  * @crit_thresh: Critical threshold for near-full processing of this srng
  * @safe_thresh: Safe threshold for near-full processing of this srng
+ * @near_full: Flag to indicate srng is near-full
  */
 struct dp_srng {
 	hal_ring_handle_t hal_srng;
@@ -688,6 +689,7 @@ struct dp_srng {
 #ifdef WLAN_FEATURE_NEAR_FULL_IRQ
 	uint16_t crit_thresh;
 	uint16_t safe_thresh;
+	qdf_atomic_t near_full;
 #endif
 };
 

+ 4 - 1
dp/wifi3.0/li/dp_li_rx.c

@@ -114,6 +114,7 @@ uint32_t dp_rx_process_li(struct dp_intr *int_ctx,
 	qdf_nbuf_t ebuf_head;
 	qdf_nbuf_t ebuf_tail;
 	uint8_t pkt_capture_offload = 0;
+	int max_reap_limit;
 
 	DP_HIST_INIT();
 
@@ -137,6 +138,7 @@ more_data:
 	num_rx_bufs_reaped = 0;
 	ebuf_head = NULL;
 	ebuf_tail = NULL;
+	max_reap_limit = dp_rx_get_loop_pkt_limit(soc);
 
 	qdf_mem_zero(rx_bufs_reaped, sizeof(rx_bufs_reaped));
 	qdf_mem_zero(&mpdu_desc_info, sizeof(mpdu_desc_info));
@@ -383,7 +385,8 @@ more_data:
 		 * then allow break.
 		 */
 		if (is_prev_msdu_last &&
-		    dp_rx_reap_loop_pkt_limit_hit(soc, num_rx_bufs_reaped))
+		    dp_rx_reap_loop_pkt_limit_hit(soc, num_rx_bufs_reaped,
+						  max_reap_limit))
 			break;
 	}
 done:

+ 3 - 0
hal/wifi3.0/hal_api.h

@@ -1606,6 +1606,9 @@ void *hal_srng_dst_peek_sync_locked(hal_soc_handle_t hal_soc_hdl,
 	return ring_desc_ptr;
 }
 
+#define hal_srng_dst_num_valid_nolock(hal_soc, hal_ring_hdl, sync_hw_ptr) \
+		hal_srng_dst_num_valid(hal_soc, hal_ring_hdl, sync_hw_ptr)
+
 /**
  * hal_srng_dst_num_valid - Returns number of valid entries (to be processed
  * by SW) in destination ring