diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 363f980fe9..659c22582f 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -1648,10 +1648,47 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) } #endif +/** + * dp_rx_srng_get_num_pending() - get number of pending entries + * @hal_soc: hal soc opaque pointer + * @hal_ring: opaque pointer to the HAL Rx Ring + * @num_entries: number of entries in the hal_ring. + * @near_full: pointer to a boolean. This is set if ring is near full. + * + * The function returns the number of entries in a destination ring which are + * yet to be reaped. The function also checks if the ring is near full. + * If more than half of the ring needs to be reaped, the ring is considered + * approaching full. + * The function useses hal_srng_dst_num_valid_locked to get the number of valid + * entries. It should not be called within a SRNG lock. HW pointer value is + * synced into cached_hp. + * + * Return: Number of pending entries if any + */ +static +uint32_t dp_rx_srng_get_num_pending(hal_soc_handle_t hal_soc, + hal_ring_handle_t hal_ring_hdl, + uint32_t num_entries, + bool *near_full) +{ + uint32_t num_pending = 0; + + num_pending = hal_srng_dst_num_valid_locked(hal_soc, + hal_ring_hdl, + true); + + if (num_entries && (num_pending >= num_entries >> 1)) + *near_full = true; + else + *near_full = false; + + return num_pending; +} + /** * dp_rx_process() - Brain of the Rx processing functionality * Called from the bottom half (tasklet/NET_RX_SOFTIRQ) - * @soc: core txrx main context + * @int_ctx: per interrupt context * @hal_ring: opaque pointer to the HAL Rx Ring, which will be serviced * @reo_ring_num: ring number (0, 1, 2 or 3) of the reo ring. * @quota: No. of units (packets) that can be serviced in one shot. @@ -1662,14 +1699,16 @@ void dp_rx_deliver_to_stack_no_peer(struct dp_soc *soc, qdf_nbuf_t nbuf) * Return: uint32_t: No. of elements processed */ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, - uint8_t reo_ring_num, uint32_t quota) + uint8_t reo_ring_num, uint32_t quota) { hal_ring_desc_t ring_desc; hal_soc_handle_t hal_soc; struct dp_rx_desc *rx_desc = NULL; qdf_nbuf_t nbuf, next; + bool near_full; union dp_rx_desc_list_elem_t *head[MAX_PDEV_CNT]; union dp_rx_desc_list_elem_t *tail[MAX_PDEV_CNT]; + uint32_t num_pending; uint32_t rx_bufs_used = 0, rx_buf_cookie; uint32_t l2_hdr_offset = 0; uint16_t msdu_len = 0; @@ -1703,6 +1742,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, bool is_prev_msdu_last = true; uint32_t num_entries_avail = 0; uint32_t rx_ol_pkt_cnt = 0; + uint32_t num_entries = 0; DP_HIST_INIT(); @@ -1713,6 +1753,7 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, hal_ring_handle_t hal_ring_hdl, scn = soc->hif_handle; hif_pm_runtime_mark_dp_rx_busy(scn); intr_id = int_ctx->dp_intr_id; + num_entries = hal_srng_get_num_entries(hal_soc, hal_ring_hdl); more_data: /* reset local variables here to be re-used in the function */ @@ -2196,12 +2237,23 @@ done: deliver_list_tail); if (dp_rx_enable_eol_data_check(soc) && rx_bufs_used) { - if (quota && - hal_srng_dst_peek_sync_locked(soc->hal_soc, - hal_ring_hdl)) { - DP_STATS_INC(soc, rx.hp_oos2, 1); - if (!hif_exec_should_yield(scn, intr_id)) - goto more_data; + if (quota) { + num_pending = + dp_rx_srng_get_num_pending(hal_soc, + hal_ring_hdl, + num_entries, + &near_full); + if (num_pending) { + DP_STATS_INC(soc, rx.hp_oos2, 1); + + if (!hif_exec_should_yield(scn, intr_id)) + goto more_data; + + if (qdf_unlikely(near_full)) { + DP_STATS_INC(soc, rx.near_full, 1); + goto more_data; + } + } } if (vdev && vdev->osif_gro_flush && rx_ol_pkt_cnt) { diff --git a/dp/wifi3.0/dp_stats.c b/dp/wifi3.0/dp_stats.c index 71d7f46918..4077be00d3 100644 --- a/dp/wifi3.0/dp_stats.c +++ b/dp/wifi3.0/dp_stats.c @@ -5068,6 +5068,8 @@ void dp_print_per_ring_stats(struct dp_soc *soc) total_packets = 0; DP_PRINT_STATS("Packets on ring %u:", ring); for (core = 0; core < num_possible_cpus(); core++) { + if (!soc->stats.rx.ring_packets[core][ring]) + continue; DP_PRINT_STATS("Packets arriving on core %u: %llu", core, soc->stats.rx.ring_packets[core][ring]); @@ -5154,11 +5156,14 @@ void dp_txrx_path_stats(struct dp_soc *soc) DP_PRINT_STATS("delivered %u msdus ( %llu bytes),", pdev->stats.rx.to_stack.num, pdev->stats.rx.to_stack.bytes); - for (i = 0; i < CDP_MAX_RX_RINGS; i++) + for (i = 0; i < CDP_MAX_RX_RINGS; i++) { + if (!pdev->stats.rx.rcvd_reo[i].num) + continue; DP_PRINT_STATS( "received on reo[%d] %u msdus( %llu bytes),", i, pdev->stats.rx.rcvd_reo[i].num, pdev->stats.rx.rcvd_reo[i].bytes); + } DP_PRINT_STATS("intra-bss packets %u msdus ( %llu bytes),", pdev->stats.rx.intra_bss.pkts.num, pdev->stats.rx.intra_bss.pkts.bytes); @@ -5187,6 +5192,7 @@ void dp_txrx_path_stats(struct dp_soc *soc) pdev->soc->stats.rx.err.pkt_delivered_no_peer); DP_PRINT_STATS("Reo Statistics"); + DP_PRINT_STATS("near_full: %u ", soc->stats.rx.near_full); DP_PRINT_STATS("rbm error: %u msdus", pdev->soc->stats.rx.err.invalid_rbm); DP_PRINT_STATS("hal ring access fail: %u msdus", @@ -5617,7 +5623,7 @@ void dp_print_soc_interrupt_stats(struct dp_soc *soc) DP_PRINT_STATS("INT: Total |txComps|reo[0] |reo[1] |reo[2] |reo[3] |mon |rx_err | wbm |reo_sta|rxdm2hst|hst2rxdm|"); for (i = 0; i < WLAN_CFG_INT_NUM_CONTEXTS; i++) { intr_stats = &soc->intr_ctx[i].intr_stats; - DP_PRINT_STATS("%3u[%d]: %7u %7u %7u %7u %7u %7u %7u %7u %7u %7u %8u %8u", + DP_PRINT_STATS("%3u[%3d]: %7u %7u %7u %7u %7u %7u %7u %7u %7u %7u %8u %8u", i, hif_get_int_ctx_irq_num(soc->hif_handle, i), intr_stats->num_masks, @@ -5676,6 +5682,8 @@ dp_print_soc_rx_stats(struct dp_soc *soc) DP_PRINT_STATS("RX frag err: %d", soc->stats.rx.rx_frag_err); DP_PRINT_STATS("RX HP out_of_sync: %d", soc->stats.rx.hp_oos2); + DP_PRINT_STATS("RX Ring Near Full: %d", soc->stats.rx.near_full); + DP_PRINT_STATS("RX Reap Loop Pkt Limit Hit: %d", soc->stats.rx.reap_loop_pkt_limit_hit); DP_PRINT_STATS("RX DESC invalid magic: %u", diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index cb32f058b3..312abc2046 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -693,6 +693,8 @@ struct dp_soc_stats { uint32_t reap_loop_pkt_limit_hit; /* Head pointer Out of sync at the end of dp_rx_process */ uint32_t hp_oos2; + /* Rx ring near full */ + uint32_t near_full; struct { /* Invalid RBM error count */ uint32_t invalid_rbm; diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 20d2fc0828..8b7b1581dc 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -789,9 +789,10 @@ void *hal_srng_dst_peek_sync_locked(hal_soc_handle_t hal_soc_hdl, * @sync_hw_ptr: Sync cached head pointer with HW * */ -static inline uint32_t hal_srng_dst_num_valid(void *hal_soc, - hal_ring_handle_t hal_ring_hdl, - int sync_hw_ptr) +static inline +uint32_t hal_srng_dst_num_valid(void *hal_soc, + hal_ring_handle_t hal_ring_hdl, + int sync_hw_ptr) { struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; uint32_t hp; @@ -810,6 +811,33 @@ static inline uint32_t hal_srng_dst_num_valid(void *hal_soc, return (srng->ring_size - tp + hp) / srng->entry_size; } +/** + * hal_srng_dst_num_valid_locked - Returns num valid entries to be processed + * + * @hal_soc: Opaque HAL SOC handle + * @hal_ring_hdl: Destination ring pointer + * @sync_hw_ptr: Sync cached head pointer with HW + * + * Returns number of valid entries to be processed by the host driver. The + * function takes up SRNG lock. + * + * Return: Number of valid destination entries + */ +static inline uint32_t +hal_srng_dst_num_valid_locked(hal_soc_handle_t hal_soc, + hal_ring_handle_t hal_ring_hdl, + int sync_hw_ptr) +{ + uint32_t num_valid; + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + + SRNG_LOCK(&srng->lock); + num_valid = hal_srng_dst_num_valid(hal_soc, hal_ring_hdl, sync_hw_ptr); + SRNG_UNLOCK(&srng->lock); + + return num_valid; +} + /** * hal_srng_src_reap_next - Reap next entry from a source ring and move reap * pointer. This can be used to release any buffers associated with completed @@ -1384,6 +1412,23 @@ hal_srng_get_tp_addr(void *hal_soc, hal_ring_handle_t hal_ring_hdl) } } +/** + * hal_srng_get_num_entries - Get total entries in the HAL Srng + * + * @hal_soc: Opaque HAL SOC handle + * @hal_ring_hdl: Ring pointer (Source or Destination ring) + * + * Return: total number of entries in hal ring + */ +static inline +uint32_t hal_srng_get_num_entries(hal_soc_handle_t hal_soc_hdl, + hal_ring_handle_t hal_ring_hdl) +{ + struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; + + return srng->num_entries; +} + /** * hal_get_srng_params - Retrieve SRNG parameters for a given ring from HAL *