diff --git a/dp/inc/cdp_txrx_cmn_struct.h b/dp/inc/cdp_txrx_cmn_struct.h index 9f1011e911..aba54657aa 100644 --- a/dp/inc/cdp_txrx_cmn_struct.h +++ b/dp/inc/cdp_txrx_cmn_struct.h @@ -65,6 +65,7 @@ #define CDP_NAPI_STATS 9 #define CDP_WLAN_RX_BUF_DEBUG_STATS 10 #define CDP_RX_RING_STATS 11 +#define CDP_DP_NAPI_STATS 12 #define CDP_SCHEDULER_STATS 21 #define CDP_TX_QUEUE_STATS 22 #define CDP_BUNDLE_STATS 23 diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 09cef0d1e8..08e7f5ed9b 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -3893,6 +3893,15 @@ static int dp_txrx_stats(struct cdp_vdev *vdev, enum cdp_stats stats) return 0; } +/* + * dp_print_napi_stats(): NAPI stats + * @soc - soc handle + */ +static void dp_print_napi_stats(struct dp_soc *soc) +{ + hif_print_napi_stats(soc->hif_handle); +} + /* * dp_print_per_ring_stats(): Packet count per ring * @soc - soc handle @@ -4087,6 +4096,10 @@ static QDF_STATUS dp_txrx_dump_stats(void *psoc, uint16_t value) cdp_dump_flow_pool_info((struct cdp_soc_t *)soc); break; + case CDP_DP_NAPI_STATS: + dp_print_napi_stats(soc); + break; + case CDP_TXRX_DESC_STATS: /* TODO: NOT IMPLEMENTED */ break; diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 56485ed7b7..92916fabcc 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -895,6 +895,7 @@ void hif_update_pipe_callback(struct hif_opaque_softc *osc, u_int8_t pipeid, struct hif_msg_callbacks *callbacks); +void hif_print_napi_stats(struct hif_opaque_softc *hif_ctx); #ifdef __cplusplus } #endif diff --git a/hif/src/hif_exec.c b/hif/src/hif_exec.c index 7afe21ca4c..944133da16 100644 --- a/hif/src/hif_exec.c +++ b/hif/src/hif_exec.c @@ -20,6 +20,41 @@ #include #include +/** + * hif_print_napi_stats() - print NAPI stats + * @hif_ctx: hif context + * + * return: void + */ +void hif_print_napi_stats(struct hif_opaque_softc *hif_ctx) +{ + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_ctx); + struct hif_exec_context *hif_ext_group; + struct qca_napi_stat *napi_stats; + int i, j; + + QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_FATAL, + "NAPI[#ctx]CPU[#] |schedules |polls |completes |workdone\n"); + + for (i = 0; i < hif_state->hif_num_extgroup; i++) { + if (hif_state->hif_ext_group[i]) { + hif_ext_group = hif_state->hif_ext_group[i]; + for (j = 0; j < num_possible_cpus(); j++) { + napi_stats = &(hif_ext_group->stats[j]); + if (napi_stats->napi_schedules != 0) + QDF_TRACE(QDF_MODULE_ID_HIF, + QDF_TRACE_LEVEL_FATAL, + "NAPI[%2d]CPU[%d]: " + "%7d %7d %7d %7d \n", + i, j, + napi_stats->napi_schedules, + napi_stats->napi_polls, + napi_stats->napi_completes, + napi_stats->napi_workdone); + } + } + } +} static void hif_exec_tasklet_schedule(struct hif_exec_context *ctx) { @@ -65,6 +100,7 @@ static int hif_exec_poll(struct napi_struct *napi, int budget) struct hif_exec_context *hif_ext_group = &exec_ctx->exec_ctx; struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif); int work_done; + int cpu = smp_processor_id(); work_done = hif_ext_group->handler(hif_ext_group->context, budget); @@ -75,12 +111,16 @@ static int hif_exec_poll(struct napi_struct *napi, int budget) napi_complete(napi); qdf_atomic_dec(&scn->active_grp_tasklet_cnt); hif_ext_group->irq_enable(hif_ext_group); + hif_ext_group->stats[cpu].napi_completes++; } else { /* if the ext_group supports time based yield, claim full work * done anyways */ work_done = budget; } + hif_ext_group->stats[cpu].napi_polls++; + hif_ext_group->stats[cpu].napi_workdone += work_done; + return work_done; } @@ -91,6 +131,7 @@ static int hif_exec_poll(struct napi_struct *napi, int budget) static void hif_exec_napi_schedule(struct hif_exec_context *ctx) { struct hif_napi_exec_context *n_ctx = hif_exec_get_napi(ctx); + ctx->stats[smp_processor_id()].napi_schedules++; napi_schedule(&n_ctx->napi); }