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:

committed by
Madan Koyyalamudi

parent
20dddcb585
commit
5605d45923
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
};
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user