diff --git a/dp/wifi3.0/dp_internal.h b/dp/wifi3.0/dp_internal.h index 39e5dada55..1df035e5bf 100644 --- a/dp/wifi3.0/dp_internal.h +++ b/dp/wifi3.0/dp_internal.h @@ -827,11 +827,13 @@ extern void dp_reo_cmdlist_destroy(struct dp_soc *soc); /** * dp_reo_status_ring_handler - Handler for REO Status ring + * @int_ctx: pointer to DP interrupt context * @soc: DP Soc handle * * Returns: Number of descriptors reaped */ -uint32_t dp_reo_status_ring_handler(struct dp_soc *soc); +uint32_t dp_reo_status_ring_handler(struct dp_intr *int_ctx, + struct dp_soc *soc); void dp_aggregate_vdev_stats(struct dp_vdev *vdev, struct cdp_vdev_stats *vdev_stats); void dp_rx_tid_stats_cb(struct dp_soc *soc, void *cb_ctxt, @@ -1195,6 +1197,48 @@ static inline void dp_peer_unref_del_find_by_id(struct dp_peer *peer) } #endif +#ifdef WLAN_FEATURE_DP_EVENT_HISTORY +/** + * dp_srng_access_start() - Wrapper function to log access start of a hal ring + * @int_ctx: pointer to DP interrupt context + * @soc: DP Soc handle + * @hal_ring: opaque pointer to the HAL Rx Error Ring, which will be serviced + * + * Return: 0 on success; error on failure + */ +int dp_srng_access_start(struct dp_intr *int_ctx, struct dp_soc *dp_soc, + void *hal_ring); + +/** + * dp_srng_access_end() - Wrapper function to log access end of a hal ring + * @int_ctx: pointer to DP interrupt context + * @soc: DP Soc handle + * @hal_ring: opaque pointer to the HAL Rx Error Ring, which will be serviced + * + * Return: void + */ +void dp_srng_access_end(struct dp_intr *int_ctx, struct dp_soc *dp_soc, + void *hal_ring); + +#else + +static inline int dp_srng_access_start(struct dp_intr *int_ctx, + struct dp_soc *dp_soc, void *hal_ring) +{ + void *hal_soc = dp_soc->hal_soc; + + return hal_srng_access_start(hal_soc, hal_ring); +} + +static inline void dp_srng_access_end(struct dp_intr *int_ctx, + struct dp_soc *dp_soc, void *hal_ring) +{ + void *hal_soc = dp_soc->hal_soc; + + return hal_srng_access_end(hal_soc, hal_ring); +} +#endif /* WLAN_FEATURE_DP_EVENT_HISTORY */ + #ifdef CONFIG_WIN /** * dp_pdev_print_delay_stats(): Print pdev level delay stats diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 95feb710f9..2f4c86b23a 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -74,6 +74,21 @@ extern int con_mode_monitor; #endif #endif +#ifdef WLAN_FEATURE_DP_EVENT_HISTORY +/* + * If WLAN_CFG_INT_NUM_CONTEXTS is changed, HIF_NUM_INT_CONTEXTS + * also should be updated accordingly + */ +QDF_COMPILE_TIME_ASSERT(num_intr_grps, + HIF_NUM_INT_CONTEXTS == WLAN_CFG_INT_NUM_CONTEXTS); + +/* + * HIF_EVENT_HIST_MAX should always be power of 2 + */ +QDF_COMPILE_TIME_ASSERT(hif_event_history_size, + (HIF_EVENT_HIST_MAX & (HIF_EVENT_HIST_MAX - 1)) == 0); +#endif /* WLAN_FEATURE_DP_EVENT_HISTORY */ + #ifdef WLAN_RX_PKT_CAPTURE_ENH #include "dp_rx_mon_feature.h" #else @@ -1360,6 +1375,40 @@ static void dp_srng_cleanup(struct dp_soc *soc, struct dp_srng *srng, /* TODO: Need this interface from HIF */ void *hif_get_hal_handle(void *hif_handle); +#ifdef WLAN_FEATURE_DP_EVENT_HISTORY +int dp_srng_access_start(struct dp_intr *int_ctx, struct dp_soc *dp_soc, + void *hal_ring) +{ + void *hal_soc = dp_soc->hal_soc; + uint32_t hp, tp; + uint8_t ring_id; + + hal_get_sw_hptp(hal_soc, hal_ring, &tp, &hp); + ring_id = hal_srng_ring_id_get(hal_ring); + + hif_record_event(dp_soc->hif_handle, int_ctx->dp_intr_id, + ring_id, hp, tp, HIF_EVENT_SRNG_ACCESS_START); + + return hal_srng_access_start(hal_soc, hal_ring); +} + +void dp_srng_access_end(struct dp_intr *int_ctx, struct dp_soc *dp_soc, + void *hal_ring) +{ + void *hal_soc = dp_soc->hal_soc; + uint32_t hp, tp; + uint8_t ring_id; + + hal_get_sw_hptp(hal_soc, hal_ring, &tp, &hp); + ring_id = hal_srng_ring_id_get(hal_ring); + + hif_record_event(dp_soc->hif_handle, int_ctx->dp_intr_id, + ring_id, hp, tp, HIF_EVENT_SRNG_ACCESS_END); + + return hal_srng_access_end(hal_soc, hal_ring); +} +#endif /* WLAN_FEATURE_DP_EVENT_HISTORY */ + /* * dp_service_srngs() - Top level interrupt handler for DP Ring interrupts * @dp_ctx: DP SOC handle @@ -1418,9 +1467,9 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) /* Process REO Exception ring interrupt */ if (rx_err_mask) { - work_done = dp_rx_err_process(soc, - soc->reo_exception_ring.hal_srng, - remaining_quota); + work_done = dp_rx_err_process(int_ctx, soc, + soc->reo_exception_ring.hal_srng, + remaining_quota); if (work_done) { intr_stats->num_rx_err_ring_masks++; @@ -1437,8 +1486,9 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) /* Process Rx WBM release ring interrupt */ if (rx_wbm_rel_mask) { - work_done = dp_rx_wbm_err_process(soc, - soc->rx_rel_ring.hal_srng, remaining_quota); + work_done = dp_rx_wbm_err_process(int_ctx, soc, + soc->rx_rel_ring.hal_srng, + remaining_quota); if (work_done) { intr_stats->num_rx_wbm_rel_ring_masks++; @@ -1476,7 +1526,7 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) } if (reo_status_mask) { - if (dp_reo_status_ring_handler(soc)) + if (dp_reo_status_ring_handler(int_ctx, soc)) int_ctx->intr_stats.num_reo_status_ring_masks++; } @@ -1501,7 +1551,7 @@ static uint32_t dp_service_srngs(void *dp_ctx, uint32_t dp_budget) if (int_ctx->rxdma2host_ring_mask & (1 << mac_for_pdev)) { - work_done = dp_rxdma_err_process(soc, + work_done = dp_rxdma_err_process(int_ctx, soc, mac_for_pdev, remaining_quota); if (work_done) diff --git a/dp/wifi3.0/dp_reo.c b/dp/wifi3.0/dp_reo.c index 0225eb19d7..cc047969f0 100644 --- a/dp/wifi3.0/dp_reo.c +++ b/dp/wifi3.0/dp_reo.c @@ -85,7 +85,7 @@ QDF_STATUS dp_reo_send_cmd(struct dp_soc *soc, enum hal_reo_cmd_type type, return QDF_STATUS_SUCCESS; } -uint32_t dp_reo_status_ring_handler(struct dp_soc *soc) +uint32_t dp_reo_status_ring_handler(struct dp_intr *int_ctx, struct dp_soc *soc) { uint32_t *reo_desc; struct dp_reo_cmd_info *reo_cmd = NULL; @@ -93,8 +93,7 @@ uint32_t dp_reo_status_ring_handler(struct dp_soc *soc) int num; int processed_count = 0; - if (hal_srng_access_start(soc->hal_soc, - soc->reo_status_ring.hal_srng)) { + if (dp_srng_access_start(int_ctx, soc, soc->reo_status_ring.hal_srng)) { return processed_count; } reo_desc = hal_srng_dst_get_next(soc->hal_soc, @@ -174,7 +173,7 @@ next: soc->reo_status_ring.hal_srng); } /* while */ - hal_srng_access_end(soc->hal_soc, soc->reo_status_ring.hal_srng); + dp_srng_access_end(int_ctx, soc, soc->reo_status_ring.hal_srng); return processed_count; } diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index b1b12ffac3..17a7bb80f3 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -1600,7 +1600,7 @@ more_data: qdf_mem_zero(head, sizeof(head)); qdf_mem_zero(tail, sizeof(tail)); - if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring))) { + if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring))) { /* * Need API to convert from hal_ring pointer to @@ -1609,7 +1609,6 @@ more_data: DP_STATS_INC(soc, rx.err.hal_ring_access_fail, 1); QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, FL("HAL RING Access Failed -- %pK"), hal_ring); - hal_srng_access_end(hal_soc, hal_ring); goto done; } @@ -1765,7 +1764,7 @@ more_data: break; } done: - hal_srng_access_end(hal_soc, hal_ring); + dp_srng_access_end(int_ctx, soc, hal_ring); if (nbuf_tail) QDF_NBUF_CB_RX_FLUSH_IND(nbuf_tail) = 1; diff --git a/dp/wifi3.0/dp_rx.h b/dp/wifi3.0/dp_rx.h index d694f8dad1..e5c00fb4c0 100644 --- a/dp/wifi3.0/dp_rx.h +++ b/dp/wifi3.0/dp_rx.h @@ -463,10 +463,36 @@ uint32_t dp_rx_process(struct dp_intr *int_ctx, void *hal_ring, uint8_t reo_ring_num, uint32_t quota); -uint32_t dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota); +/** + * dp_rx_err_process() - Processes error frames routed to REO error ring + * @int_ctx: pointer to DP interrupt context + * @soc: core txrx main context + * @hal_ring: opaque pointer to the HAL Rx Error Ring, which will be serviced + * @quota: No. of units (packets) that can be serviced in one shot. + * + * This function implements error processing and top level demultiplexer + * for all the frames routed to REO error ring. + * + * Return: uint32_t: No. of elements processed + */ +uint32_t dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, + void *hal_ring, uint32_t quota); +/** + * dp_rx_wbm_err_process() - Processes error frames routed to WBM release ring + * @int_ctx: pointer to DP interrupt context + * @soc: core txrx main context + * @hal_ring: opaque pointer to the HAL Rx Error Ring, which will be serviced + * @quota: No. of units (packets) that can be serviced in one shot. + * + * This function implements error processing and top level demultiplexer + * for all the frames routed to WBM2HOST sw release ring. + * + * Return: uint32_t: No. of elements processed + */ uint32_t -dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota); +dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, + void *hal_ring, uint32_t quota); /** * dp_rx_sg_create() - create a frag_list for MSDUs which are spread across @@ -1107,9 +1133,18 @@ QDF_STATUS dp_rx_link_desc_return_by_addr(struct dp_soc *soc, void *link_desc_addr, uint8_t bm_action); +/** + * dp_rxdma_err_process() - RxDMA error processing functionality + * @soc: core txrx main contex + * @mac_id: mac id which is one of 3 mac_ids + * @hal_ring: opaque pointer to the HAL Rx Ring, which will be serviced + * @quota: No. of units (packets) that can be serviced in one shot. + * + * Return: num of buffers processed + */ uint32_t -dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id, - uint32_t quota); +dp_rxdma_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, + uint32_t mac_id, uint32_t quota); void dp_rx_fill_mesh_stats(struct dp_vdev *vdev, qdf_nbuf_t nbuf, uint8_t *rx_tlv_hdr, struct dp_peer *peer); diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index e2e7e355b1..142382824d 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -1078,20 +1078,9 @@ fail: return; } -/** - * dp_rx_err_process() - Processes error frames routed to REO error ring - * - * @soc: core txrx main context - * @hal_ring: opaque pointer to the HAL Rx Error Ring, which will be serviced - * @quota: No. of units (packets) that can be serviced in one shot. - * - * This function implements error processing and top level demultiplexer - * for all the frames routed to REO error ring. - * - * Return: uint32_t: No. of elements processed - */ uint32_t -dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) +dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, + void *hal_ring, uint32_t quota) { void *hal_soc; void *ring_desc; @@ -1120,7 +1109,7 @@ dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) /* Debug -- Remove later */ qdf_assert(hal_soc); - if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring))) { + if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring))) { /* TODO */ /* @@ -1248,7 +1237,7 @@ dp_rx_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) } done: - hal_srng_access_end(hal_soc, hal_ring); + dp_srng_access_end(int_ctx, soc, hal_ring); if (soc->rx.flags.defrag_timeout_check) { uint32_t now_ms = @@ -1276,20 +1265,9 @@ done: return rx_bufs_used; /* Assume no scale factor for now */ } -/** - * dp_rx_wbm_err_process() - Processes error frames routed to WBM release ring - * - * @soc: core txrx main context - * @hal_ring: opaque pointer to the HAL Rx Error Ring, which will be serviced - * @quota: No. of units (packets) that can be serviced in one shot. - * - * This function implements error processing and top level demultiplexer - * for all the frames routed to WBM2HOST sw release ring. - * - * Return: uint32_t: No. of elements processed - */ uint32_t -dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) +dp_rx_wbm_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, + void *hal_ring, uint32_t quota) { void *hal_soc; void *ring_desc; @@ -1320,7 +1298,7 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) /* Debug -- Remove later */ qdf_assert(hal_soc); - if (qdf_unlikely(hal_srng_access_start(hal_soc, hal_ring))) { + if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_ring))) { /* TODO */ /* @@ -1407,7 +1385,7 @@ dp_rx_wbm_err_process(struct dp_soc *soc, void *hal_ring, uint32_t quota) rx_desc); } done: - hal_srng_access_end(hal_soc, hal_ring); + dp_srng_access_end(int_ctx, soc, hal_ring); for (mac_id = 0; mac_id < MAX_PDEV_CNT; mac_id++) { if (rx_bufs_reaped[mac_id]) { @@ -1708,18 +1686,9 @@ dp_rx_err_mpdu_pop(struct dp_soc *soc, uint32_t mac_id, return rx_bufs_used; } -/** -* dp_rxdma_err_process() - RxDMA error processing functionality -* -* @soc: core txrx main contex -* @mac_id: mac id which is one of 3 mac_ids -* @hal_ring: opaque pointer to the HAL Rx Ring, which will be serviced -* @quota: No. of units (packets) that can be serviced in one shot. - -* Return: num of buffers processed -*/ uint32_t -dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) +dp_rxdma_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, + uint32_t mac_id, uint32_t quota) { struct dp_pdev *pdev = dp_get_pdev_for_mac_id(soc, mac_id); int mac_for_pdev = dp_get_mac_id_for_mac(soc, mac_id); @@ -1750,7 +1719,7 @@ dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) qdf_assert(hal_soc); - if (qdf_unlikely(hal_srng_access_start(hal_soc, err_dst_srng))) { + if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, err_dst_srng))) { QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, "%s %d : HAL Monitor Destination Ring Init \ Failed -- %pK", @@ -1766,7 +1735,7 @@ dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id, uint32_t quota) &head, &tail); } - hal_srng_access_end(hal_soc, err_dst_srng); + dp_srng_access_end(int_ctx, soc, err_dst_srng); if (rx_bufs_used) { dp_rxdma_srng = &pdev->rx_refill_buf_ring; diff --git a/dp/wifi3.0/dp_rx_mon.h b/dp/wifi3.0/dp_rx_mon.h index 759d324dc2..975b241887 100644 --- a/dp/wifi3.0/dp_rx_mon.h +++ b/dp/wifi3.0/dp_rx_mon.h @@ -83,8 +83,17 @@ QDF_STATUS dp_rx_mon_deliver(struct dp_soc *soc, uint32_t mac_id, */ QDF_STATUS dp_rx_mon_deliver_non_std(struct dp_soc *soc, uint32_t mac_id); -uint32_t dp_rxdma_err_process(struct dp_soc *soc, uint32_t mac_id, - uint32_t quota); +/** + * dp_rxdma_err_process() - RxDMA error processing functionality + * @soc: core txrx main contex + * @mac_id: mac id which is one of 3 mac_ids + * @hal_ring: opaque pointer to the HAL Rx Ring, which will be serviced + * @quota: No. of units (packets) that can be serviced in one shot. + * + * Return: num of buffers processed + */ +uint32_t dp_rxdma_err_process(struct dp_intr *int_ctx, struct dp_soc *soc, + uint32_t mac_id, uint32_t quota); #ifndef REMOVE_MON_DBG_STATS /* diff --git a/dp/wifi3.0/dp_tx.c b/dp/wifi3.0/dp_tx.c index 871da42c57..7c6096d999 100644 --- a/dp/wifi3.0/dp_tx.c +++ b/dp/wifi3.0/dp_tx.c @@ -3327,7 +3327,7 @@ more_data: /* Re-initialize local variables to be re-used */ head_desc = NULL; tail_desc = NULL; - if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) { + if (qdf_unlikely(dp_srng_access_start(int_ctx, soc, hal_srng))) { QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, "%s %d : HAL RING Access Failed -- %pK", __func__, __LINE__, hal_srng); @@ -3446,7 +3446,7 @@ more_data: break; } - hal_srng_access_end(soc->hal_soc, hal_srng); + dp_srng_access_end(int_ctx, soc, hal_srng); /* Process the reaped descriptors */ if (head_desc) diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 14a39cc701..225a93245c 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -317,6 +317,114 @@ struct hif_target_info { struct hif_opaque_softc { }; +/** + * enum hif_event_type - Type of DP events to be recorded + * @HIF_EVENT_IRQ_TRIGGER: IRQ trigger event + * @HIF_EVENT_BH_SCHED: NAPI POLL scheduled event + * @HIF_EVENT_SRNG_ACCESS_START: hal ring access start event + * @HIF_EVENT_SRNG_ACCESS_END: hal ring access end event + */ +enum hif_event_type { + HIF_EVENT_IRQ_TRIGGER, + HIF_EVENT_BH_SCHED, + HIF_EVENT_SRNG_ACCESS_START, + HIF_EVENT_SRNG_ACCESS_END, +}; + +#ifdef WLAN_FEATURE_DP_EVENT_HISTORY + +/* HIF_EVENT_HIST_MAX should always be power of 2 */ +#define HIF_EVENT_HIST_MAX 512 +#define HIF_NUM_INT_CONTEXTS 7 +#define HIF_EVENT_HIST_DISABLE_MASK 0 + +/** + * struct hif_event_record - an entry of the DP event history + * @hal_ring_id: ring id for which event is recorded + * @hp: head pointer of the ring (may not be applicable for all events) + * @tp: tail pointer of the ring (may not be applicable for all events) + * @cpu_id: cpu id on which the event occurred + * @timestamp: timestamp when event occurred + * @type: type of the event + * + * This structure represents the information stored for every datapath + * event which is logged in the history. + */ +struct hif_event_record { + uint8_t hal_ring_id; + uint32_t hp; + uint32_t tp; + int cpu_id; + uint64_t timestamp; + enum hif_event_type type; +}; + +/** + * struct hif_event_history - history for one interrupt group + * @index: index to store new event + * @event: event entry + * + * This structure represents the datapath history for one + * interrupt group. + */ +struct hif_event_history { + qdf_atomic_t index; + struct hif_event_record event[HIF_EVENT_HIST_MAX]; +}; + +/** + * hif_hist_record_event() - Record one datapath event in history + * @hif_ctx: HIF opaque context + * @event: DP event entry + * @intr_grp_id: interrupt group ID registered with hif + * + * Return: None + */ +void hif_hist_record_event(struct hif_opaque_softc *hif_ctx, + struct hif_event_record *event, + uint8_t intr_grp_id); + +/** + * hif_record_event() - Wrapper function to form and record DP event + * @hif_ctx: HIF opaque context + * @intr_grp_id: interrupt group ID registered with hif + * @hal_ring_id: ring id for which event is recorded + * @hp: head pointer index of the srng + * @tp: tail pointer index of the srng + * @type: type of the event to be logged in history + * + * Return: None + */ +static inline void hif_record_event(struct hif_opaque_softc *hif_ctx, + uint8_t intr_grp_id, + uint8_t hal_ring_id, + uint32_t hp, + uint32_t tp, + enum hif_event_type type) +{ + struct hif_event_record event; + + event.hal_ring_id = hal_ring_id; + event.hp = hp; + event.tp = tp; + event.type = type; + + return hif_hist_record_event(hif_ctx, &event, + intr_grp_id); +} + +#else + +static inline void hif_record_event(struct hif_opaque_softc *hif_ctx, + uint8_t intr_grp_id, + uint8_t hal_ring_id, + uint32_t hp, + uint32_t tp, + enum hif_event_type type) +{ +} +#endif /* WLAN_FEATURE_DP_EVENT_HISTORY */ + /** * enum HIF_DEVICE_POWER_CHANGE_TYPE: Device Power change type * diff --git a/hif/src/hif_exec.c b/hif/src/hif_exec.c index 4135a6c5bf..944d5a83ad 100644 --- a/hif/src/hif_exec.c +++ b/hif/src/hif_exec.c @@ -32,6 +32,65 @@ static struct hif_exec_context *hif_exec_tasklet_create(void); +#ifdef WLAN_FEATURE_DP_EVENT_HISTORY +struct hif_event_history hif_event_desc_history[HIF_NUM_INT_CONTEXTS]; + +static inline int hif_get_next_record_index(qdf_atomic_t *table_index, + int array_size) +{ + int record_index = qdf_atomic_inc_return(table_index); + + return record_index & (array_size - 1); +} + +void hif_hist_record_event(struct hif_opaque_softc *hif_ctx, + struct hif_event_record *event, uint8_t intr_grp_id) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct hif_exec_context *hif_ext_group; + struct hif_event_history *hist_ev; + struct hif_event_record *record; + int record_index; + + if (!event) + return; + + if (scn->event_disable_mask & BIT(event->type)) + return; + + if (intr_grp_id >= HIF_NUM_INT_CONTEXTS) { + hif_err("Invalid interrupt group id %d", intr_grp_id); + return; + } + + hif_ext_group = hif_state->hif_ext_group[intr_grp_id]; + hist_ev = hif_ext_group->evt_hist; + + record_index = hif_get_next_record_index( + &hist_ev->index, HIF_EVENT_HIST_MAX); + + record = &hist_ev->event[record_index]; + + record->hal_ring_id = event->hal_ring_id; + record->hp = event->hp; + record->tp = event->tp; + record->cpu_id = qdf_get_cpu(); + record->timestamp = qdf_get_log_timestamp(); + record->type = event->type; +} + +static void hif_event_history_init(struct hif_exec_context *hif_ext_grp) +{ + hif_ext_grp->evt_hist = &hif_event_desc_history[hif_ext_grp->grp_id]; + qdf_atomic_set(&hif_ext_grp->evt_hist->index, -1); +} +#else +static inline void hif_event_history_init(struct hif_exec_context *hif_ext_grp) +{ +} +#endif /* WLAN_FEATURE_DP_EVENT_HISTORY */ + /** * hif_print_napi_latency_stats() - print NAPI scheduling latency stats * @hif_state: hif context @@ -449,6 +508,9 @@ static int hif_exec_poll(struct napi_struct *napi, int budget) int shift = hif_ext_group->scale_bin_shift; int cpu = smp_processor_id(); + hif_record_event(hif_ext_group->hif, hif_ext_group->grp_id, + 0, 0, 0, HIF_EVENT_BH_SCHED); + hif_ext_group->force_break = false; hif_exec_update_service_start_time(hif_ext_group); @@ -706,6 +768,9 @@ irqreturn_t hif_ext_group_interrupt_handler(int irq, void *context) if (hif_ext_group->irq_requested) { hif_latency_profile_start(hif_ext_group); + hif_record_event(hif_ext_group->hif, hif_ext_group->grp_id, + 0, 0, 0, HIF_EVENT_IRQ_TRIGGER); + hif_ext_group->irq_disable(hif_ext_group); /* * if private ioctl has issued fake suspend command to put @@ -798,6 +863,7 @@ uint32_t hif_register_ext_group(struct hif_opaque_softc *hif_ctx, hif_ext_group->hif = hif_ctx; hif_ext_group->context_name = context_name; hif_ext_group->type = type; + hif_event_history_init(hif_ext_group); hif_state->hif_num_extgroup++; return QDF_STATUS_SUCCESS; diff --git a/hif/src/hif_exec.h b/hif/src/hif_exec.h index a8d514b4c0..133f029716 100644 --- a/hif/src/hif_exec.h +++ b/hif/src/hif_exec.h @@ -53,6 +53,7 @@ struct hif_execution_ops { * hif_tasklet_exec_context * * @context: context for the handler function to use. + * @evt_hist: a pointer to the DP event history * @context_name: a pointer to a const string for debugging. * this should help whenever there could be ambiguity * in what type of context the void* context points to @@ -87,6 +88,7 @@ struct hif_exec_context { const char *context_name; void *context; ext_intr_handler handler; + struct hif_event_history *evt_hist; bool (*work_complete)(struct hif_exec_context *, int work_done); void (*irq_enable)(struct hif_exec_context *); diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index fcdf028724..3f1a717ae9 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -424,6 +424,7 @@ struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, uint32_t mode, qdf_mem_copy(&scn->callbacks, cbk, sizeof(struct hif_driver_state_callbacks)); scn->bus_type = bus_type; + hif_set_event_hist_mask(GET_HIF_OPAQUE_HDL(scn)); status = hif_bus_open(scn, bus_type); if (status != QDF_STATUS_SUCCESS) { HIF_ERROR("%s: hif_bus_open error = %d, bus_type = %d", diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h index bd7cf8b5e4..0a26d3997d 100644 --- a/hif/src/hif_main.h +++ b/hif/src/hif_main.h @@ -152,6 +152,7 @@ struct hif_softc { /* Packet statistics */ struct hif_ce_stats pkt_stats; enum hif_target_status target_status; + uint64_t event_disable_mask; struct targetdef_s *targetdef; struct ce_reg_def *target_ce_def; @@ -238,6 +239,19 @@ static inline uint8_t hif_is_attribute_set(struct hif_softc *sc, return sc->hif_attribute == hif_attrib; } +#ifdef WLAN_FEATURE_DP_EVENT_HISTORY +static inline void hif_set_event_hist_mask(struct hif_opaque_softc *hif_handle) +{ + struct hif_softc *scn = (struct hif_softc *)hif_handle; + + scn->event_disable_mask = HIF_EVENT_HIST_DISABLE_MASK; +} +#else +static inline void hif_set_event_hist_mask(struct hif_opaque_softc *hif_handle) +{ +} +#endif /* WLAN_FEATURE_DP_EVENT_HISTORY */ + A_target_id_t hif_get_target_id(struct hif_softc *scn); void hif_dump_pipe_debug_count(struct hif_softc *scn); void hif_display_bus_stats(struct hif_opaque_softc *scn);