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
This commit is contained in:
Rakesh Pillai
2021-04-06 03:19:24 -07:00
committed by Madan Koyyalamudi
parent 20dddcb585
commit 5605d45923
7 changed files with 200 additions and 38 deletions

View File

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

View File

@@ -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)
{
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

View File

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

View File

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

View File

@@ -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
};

View File

@@ -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:

View File

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