From 970948916a6c082119226eb1f03a72dafc15e025 Mon Sep 17 00:00:00 2001 From: Chaithanya Garrepalli Date: Thu, 23 Jul 2020 17:17:24 +0530 Subject: [PATCH] qcacmn: print backpressure stats in work queue context Avoid backpressure event prints in irq context and defer work queue context Change-Id: Ib68237d6a9930ead38f53aa89ec1d9e9a2f4147d --- dp/wifi3.0/dp_htt.c | 386 ++++++++++++++++++++++++++++++++++++++- dp/wifi3.0/dp_internal.h | 18 ++ dp/wifi3.0/dp_main.c | 9 + dp/wifi3.0/dp_types.h | 26 +++ 4 files changed, 431 insertions(+), 8 deletions(-) diff --git a/dp/wifi3.0/dp_htt.c b/dp/wifi3.0/dp_htt.c index a34ef374f6..483e85acc7 100644 --- a/dp/wifi3.0/dp_htt.c +++ b/dp/wifi3.0/dp_htt.c @@ -4271,7 +4271,6 @@ error: soc->htt_stats.num_stats = 0; qdf_spin_unlock_bh(&soc->htt_stats.lock); return; - } /* @@ -4443,16 +4442,278 @@ static bool time_allow_print(unsigned long *htt_ring_tt, u_int8_t ring_id) } static void dp_htt_alert_print(enum htt_t2h_msg_type msg_type, - u_int8_t pdev_id, u_int8_t ring_id, + struct dp_pdev *pdev, u_int8_t ring_id, u_int16_t hp_idx, u_int16_t tp_idx, u_int32_t bkp_time, char *ring_stype) { - dp_alert("msg_type: %d pdev_id: %d ring_type: %s ", - msg_type, pdev_id, ring_stype); + dp_alert("seq_num %u msg_type: %d pdev_id: %d ring_type: %s ", + pdev->bkp_stats.seq_num, msg_type, pdev->pdev_id, ring_stype); dp_alert("ring_id: %d hp_idx: %d tp_idx: %d bkpressure_time_ms: %d ", ring_id, hp_idx, tp_idx, bkp_time); } +/** + * dp_get_srng_ring_state_from_hal(): Get hal level ring stats + * @soc: DP_SOC handle + * @srng: DP_SRNG handle + * @ring_type: srng src/dst ring + * + * Return: void + */ +static QDF_STATUS +dp_get_srng_ring_state_from_hal(struct dp_soc *soc, + struct dp_pdev *pdev, + struct dp_srng *srng, + enum hal_ring_type ring_type, + struct dp_srng_ring_state *state) +{ + struct hal_soc *hal_soc; + + if (!soc || !srng || !srng->hal_srng || !state) + return QDF_STATUS_E_INVAL; + + hal_soc = (struct hal_soc *)soc->hal_soc; + + hal_get_sw_hptp(soc->hal_soc, srng->hal_srng, &state->sw_tail, + &state->sw_head); + + hal_get_hw_hptp(soc->hal_soc, srng->hal_srng, &state->hw_head, + &state->hw_tail, ring_type); + + state->ring_type = ring_type; + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_queue_srng_ring_stats(): Print pdev hal level ring stats + * @pdev: DP_pdev handle + * + * Return: void + */ +static void dp_queue_ring_stats(struct dp_pdev *pdev) +{ + uint32_t i; + int mac_id; + int lmac_id; + uint32_t j = 0; + struct dp_soc_srngs_state * soc_srngs_state = NULL; + QDF_STATUS status; + + soc_srngs_state = qdf_mem_malloc(sizeof(struct dp_soc_srngs_state)); + if (!soc_srngs_state) { + dp_htt_alert("Memory alloc failed for back pressure event"); + return; + } + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->reo_exception_ring, + REO_EXCEPTION, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->reo_reinject_ring, + REO_REINJECT, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->reo_cmd_ring, + REO_CMD, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->reo_status_ring, + REO_STATUS, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->rx_rel_ring, + WBM2SW_RELEASE, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->tcl_cmd_credit_ring, + TCL_CMD_CREDIT, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->tcl_status_ring, + TCL_STATUS, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->wbm_desc_rel_ring, + SW2WBM_RELEASE, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + for (i = 0; i < MAX_REO_DEST_RINGS; i++) { + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->reo_dest_ring[i], + REO_DST, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + } + + for (i = 0; i < pdev->soc->num_tcl_data_rings; i++) { + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->tcl_data_ring[i], + TCL_DATA, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + } + + for (i = 0; i < MAX_TCL_DATA_RINGS; i++) { + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->tx_comp_ring[i], + WBM2SW_RELEASE, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + } + + lmac_id = dp_get_lmac_id_for_pdev_id(pdev->soc, 0, pdev->pdev_id); + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->rx_refill_buf_ring + [lmac_id], + RXDMA_BUF, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->rx_refill_buf_ring2, + RXDMA_BUF, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + + for (i = 0; i < MAX_RX_MAC_RINGS; i++) { + dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->rx_mac_buf_ring[i], + RXDMA_BUF, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + } + + for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { + lmac_id = dp_get_lmac_id_for_pdev_id(pdev->soc, + mac_id, pdev->pdev_id); + + if (pdev->soc->wlan_cfg_ctx->rxdma1_enable) { + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->rxdma_mon_buf_ring[lmac_id], + RXDMA_MONITOR_BUF, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->rxdma_mon_dst_ring[lmac_id], + RXDMA_MONITOR_DST, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->rxdma_mon_desc_ring[lmac_id], + RXDMA_MONITOR_DESC, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + } + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->rxdma_mon_status_ring[lmac_id], + RXDMA_MONITOR_STATUS, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + } + + for (i = 0; i < NUM_RXDMA_RINGS_PER_PDEV; i++) { + lmac_id = dp_get_lmac_id_for_pdev_id(pdev->soc, + i, pdev->pdev_id); + + status = dp_get_srng_ring_state_from_hal + (pdev->soc, pdev, + &pdev->soc->rxdma_err_dst_ring + [lmac_id], + RXDMA_DST, + &soc_srngs_state->ring_state[j]); + + if (status == QDF_STATUS_SUCCESS) + qdf_assert_always(++j < DP_MAX_SRNGS); + } + soc_srngs_state->max_ring_id = j; + + qdf_spin_lock_bh(&pdev->bkp_stats.list_lock); + + soc_srngs_state->seq_num = pdev->bkp_stats.seq_num; + TAILQ_INSERT_TAIL(&pdev->bkp_stats.list, soc_srngs_state, + list_elem); + pdev->bkp_stats.seq_num++; + qdf_spin_unlock_bh(&pdev->bkp_stats.list_lock); + + qdf_queue_work(0, pdev->bkp_stats.work_queue, + &pdev->bkp_stats.work); +} + /* * dp_htt_bkp_event_alert() - htt backpressure event alert * @msg_word: htt packet context @@ -4499,22 +4760,22 @@ static void dp_htt_bkp_event_alert(u_int32_t *msg_word, struct htt_soc *soc) case HTT_SW_RING_TYPE_UMAC: if (!time_allow_print(radio_tt->umac_ttt, ring_id)) return; - dp_htt_alert_print(msg_type, pdev_id, ring_id, hp_idx, tp_idx, + dp_htt_alert_print(msg_type, pdev, ring_id, hp_idx, tp_idx, bkp_time, "HTT_SW_RING_TYPE_UMAC"); break; case HTT_SW_RING_TYPE_LMAC: if (!time_allow_print(radio_tt->lmac_ttt, ring_id)) return; - dp_htt_alert_print(msg_type, pdev_id, ring_id, hp_idx, tp_idx, + dp_htt_alert_print(msg_type, pdev, ring_id, hp_idx, tp_idx, bkp_time, "HTT_SW_RING_TYPE_LMAC"); break; default: - dp_htt_alert_print(msg_type, pdev_id, ring_id, hp_idx, tp_idx, + dp_htt_alert_print(msg_type, pdev, ring_id, hp_idx, tp_idx, bkp_time, "UNKNOWN"); break; } - dp_print_ring_stats(pdev); + dp_queue_ring_stats(pdev); dp_print_napi_stats(pdev->soc); } @@ -5845,3 +6106,112 @@ dp_htt_rx_fisa_config(struct dp_pdev *pdev, return status; } + +/** + * dp_bk_pressure_stats_handler(): worker function to print back pressure + * stats + * + * @context : argument to work function + */ +static void dp_bk_pressure_stats_handler(void *context) +{ + struct dp_pdev *pdev = (struct dp_pdev *)context; + struct dp_soc_srngs_state *soc_srngs_state, *soc_srngs_state_next; + const char *ring_name; + int i; + struct dp_srng_ring_state *ring_state; + + TAILQ_HEAD(, dp_soc_srngs_state) soc_srngs_state_list; + + TAILQ_INIT(&soc_srngs_state_list); + qdf_spin_lock_bh(&pdev->bkp_stats.list_lock); + TAILQ_CONCAT(&soc_srngs_state_list, &pdev->bkp_stats.list, + list_elem); + qdf_spin_unlock_bh(&pdev->bkp_stats.list_lock); + + TAILQ_FOREACH_SAFE(soc_srngs_state, &soc_srngs_state_list, + list_elem, soc_srngs_state_next) { + TAILQ_REMOVE(&soc_srngs_state_list, soc_srngs_state, + list_elem); + + DP_PRINT_STATS("### START BKP stats for seq_num %u ###", + soc_srngs_state->seq_num); + for (i = 0; i < soc_srngs_state->max_ring_id; i++) { + ring_state = &soc_srngs_state->ring_state[i]; + ring_name = dp_srng_get_str_from_hal_ring_type + (ring_state->ring_type); + DP_PRINT_STATS("%s: SW:Head pointer = %d Tail Pointer = %d\n", + ring_name, + ring_state->sw_head, + ring_state->sw_tail); + + DP_PRINT_STATS("%s: HW:Head pointer = %d Tail Pointer = %d\n", + ring_name, + ring_state->hw_head, + ring_state->hw_tail); + } + + DP_PRINT_STATS("### BKP stats for seq_num %u COMPLETE ###", + soc_srngs_state->seq_num); + qdf_mem_free(soc_srngs_state); + } +} + +/* + * dp_pdev_bkp_stats_detach() - detach resources for back pressure stats + * processing + * @pdev: Datapath PDEV handle + * + */ +void dp_pdev_bkp_stats_detach(struct dp_pdev *pdev) +{ + struct dp_soc_srngs_state *ring_state, *ring_state_next; + + if (!pdev->bkp_stats.work_queue) + return; + + qdf_flush_workqueue(0, pdev->bkp_stats.work_queue); + qdf_destroy_workqueue(0, pdev->bkp_stats.work_queue); + qdf_flush_work(&pdev->bkp_stats.work); + qdf_disable_work(&pdev->bkp_stats.work); + qdf_spin_lock_bh(&pdev->bkp_stats.list_lock); + TAILQ_FOREACH_SAFE(ring_state, &pdev->bkp_stats.list, + list_elem, ring_state_next) { + TAILQ_REMOVE(&pdev->bkp_stats.list, ring_state, + list_elem); + qdf_mem_free(ring_state); + } + qdf_spin_unlock_bh(&pdev->bkp_stats.list_lock); + qdf_spinlock_destroy(&pdev->bkp_stats.list_lock); +} + +/* + * dp_pdev_bkp_stats_attach() - attach resources for back pressure stats + * processing + * @pdev: Datapath PDEV handle + * + * Return: QDF_STATUS_SUCCESS: Success + * QDF_STATUS_E_NOMEM: Error + */ +QDF_STATUS dp_pdev_bkp_stats_attach(struct dp_pdev *pdev) +{ + TAILQ_INIT(&pdev->bkp_stats.list); + pdev->bkp_stats.seq_num = 0; + + qdf_create_work(0, &pdev->bkp_stats.work, + dp_bk_pressure_stats_handler, pdev); + + pdev->bkp_stats.work_queue = + qdf_alloc_unbound_workqueue("dp_bkp_work_queue"); + if (!pdev->bkp_stats.work_queue) + goto fail; + + qdf_spinlock_create(&pdev->bkp_stats.list_lock); + return QDF_STATUS_SUCCESS; + +fail: + dp_htt_alert("BKP stats attach failed"); + qdf_flush_work(&pdev->bkp_stats.work); + qdf_disable_work(&pdev->bkp_stats.work); + return QDF_STATUS_E_FAILURE; +} diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 59720bf24b..81dff10ddf 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -2734,4 +2734,22 @@ static inline QDF_STATUS dp_runtime_init(struct dp_soc *soc) } #endif +/* + * dp_pdev_bkp_stats_detach() - detach resources for back pressure stats + * processing + * @pdev: Datapath PDEV handle + * + */ +void dp_pdev_bkp_stats_detach(struct dp_pdev *pdev); + +/* + * dp_pdev_bkp_stats_attach() - attach resources for back pressure stats + * processing + * @pdev: Datapath PDEV handle + * + * Return: QDF_STATUS_SUCCESS: Success + * QDF_STATUS_E_NOMEM: Error + */ + +QDF_STATUS dp_pdev_bkp_stats_attach(struct dp_pdev *pdev); #endif /* #ifndef _DP_INTERNAL_H_ */ diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 71ec95ea72..a3dd1bcb50 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -4825,6 +4825,7 @@ static void dp_pdev_deinit(struct cdp_pdev *txrx_pdev, int force) dp_rx_pdev_buffers_free(pdev); dp_rx_pdev_mon_desc_pool_deinit(pdev); dp_rx_pdev_desc_pool_deinit(pdev); + dp_pdev_bkp_stats_detach(pdev); dp_htt_ppdu_stats_detach(pdev); dp_tx_ppdu_stats_detach(pdev); qdf_event_destroy(&pdev->fw_peer_stats_event); @@ -14614,6 +14615,12 @@ static QDF_STATUS dp_pdev_init(struct cdp_soc_t *txrx_soc, goto fail9; } + if (dp_pdev_bkp_stats_attach(pdev) != QDF_STATUS_SUCCESS) { + QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, + FL("dp_pdev_bkp_stats_attach failed")); + goto fail10; + } + /* initialize sw rx descriptors */ dp_rx_pdev_desc_pool_init(pdev); /* initialize sw monitor rx descriptors */ @@ -14632,6 +14639,8 @@ static QDF_STATUS dp_pdev_init(struct cdp_soc_t *txrx_soc, qdf_skb_total_mem_stats_read()); return QDF_STATUS_SUCCESS; +fail10: + dp_rx_fst_detach(soc, pdev); fail9: dp_ipa_uc_detach(soc, pdev); fail8: diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 35d5818399..2598b436a0 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -119,6 +119,8 @@ #define REO_CMD_EVENT_HIST_MAX 64 +#define DP_MAX_SRNGS 64 + /* 2G PHYB */ #define PHYB_2G_LMAC_ID 2 #define PHYB_2G_TARGET_PDEV_ID 2 @@ -2073,6 +2075,22 @@ struct pdev_htt_stats_dbgfs_cfg { }; #endif /* HTT_STATS_DEBUGFS_SUPPORT */ +struct dp_srng_ring_state { + enum hal_ring_type ring_type; + uint32_t sw_head; + uint32_t sw_tail; + uint32_t hw_head; + uint32_t hw_tail; + +}; + +struct dp_soc_srngs_state { + uint32_t seq_num; + uint32_t max_ring_id; + struct dp_srng_ring_state ring_state[DP_MAX_SRNGS]; + TAILQ_ENTRY(dp_soc_srngs_state) list_elem; +}; + /* PDEV level structure for data path */ struct dp_pdev { /** @@ -2463,6 +2481,14 @@ struct dp_pdev { #endif /* Flag to inidicate monitor rings are initialized */ uint8_t pdev_mon_init; + struct { + qdf_work_t work; + qdf_workqueue_t *work_queue; + uint32_t seq_num; + qdf_spinlock_t list_lock; + + TAILQ_HEAD(, dp_soc_srngs_state) list; + } bkp_stats; }; struct dp_peer;