From 5605d4592320bb9959623c2ef14775bb3203215f Mon Sep 17 00:00:00 2001 From: Rakesh Pillai Date: Tue, 6 Apr 2021 03:19:24 -0700 Subject: [PATCH] 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 --- dp/wifi3.0/be/dp_be.h | 111 +++++++++++++++++++++++++++++++++++++++ dp/wifi3.0/be/dp_be_rx.c | 34 +++++++++++- dp/wifi3.0/dp_rx.c | 33 ------------ dp/wifi3.0/dp_rx.h | 50 +++++++++++++++++- dp/wifi3.0/dp_types.h | 2 + dp/wifi3.0/li/dp_li_rx.c | 5 +- hal/wifi3.0/hal_api.h | 3 ++ 7 files changed, 200 insertions(+), 38 deletions(-) diff --git a/dp/wifi3.0/be/dp_be.h b/dp/wifi3.0/be/dp_be.h index 90c834b2ab..29518b4272 100644 --- a/dp/wifi3.0/be/dp_be.h +++ b/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 diff --git a/dp/wifi3.0/be/dp_be_rx.c b/dp/wifi3.0/be/dp_be_rx.c index 5a8caef766..53143704ec 100644 --- a/dp/wifi3.0/be/dp_be_rx.c +++ b/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 diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 2bf3bd2fd4..66ba55da3e 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/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 diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index bcf2b7943e..56f3798756 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/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 diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 83717902d1..39fb0257d8 100644 --- a/dp/wifi3.0/dp_types.h +++ b/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 }; diff --git a/dp/wifi3.0/li/dp_li_rx.c b/dp/wifi3.0/li/dp_li_rx.c index b5858e67a1..fcf19a96e3 100644 --- a/dp/wifi3.0/li/dp_li_rx.c +++ b/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: diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index b6157631ab..8726a847bd 100644 --- a/hal/wifi3.0/hal_api.h +++ b/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