diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 5190f0aabe72..d9fd995ac6b9 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -1356,17 +1356,17 @@ void hif_srng_init_phase(struct hif_opaque_softc *hif_ctx, #ifdef HIF_CE_LOG_INFO /** * hif_log_ce_info() - API to log ce info - * @hif_ctx: hif opaque handle + * @scn: hif handle * @data: hang event data buffer * @offset: offset at which data needs to be written * * Return: None */ -void hif_log_ce_info(struct hif_opaque_softc *hif_ctx, uint8_t *data, +void hif_log_ce_info(struct hif_softc *scn, uint8_t *data, unsigned int *offset); #else static inline -void hif_log_ce_info(struct hif_opaque_softc *hif_ctx, uint8_t *data, +void hif_log_ce_info(struct hif_softc *scn, uint8_t *data, unsigned int *offset) { } diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index bb09b2207ec7..7a607e4d0660 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -4219,10 +4219,9 @@ int ce_get_index_info(struct hif_softc *scn, void *ce_state, return hif_state->ce_services->ce_get_index_info(scn, ce_state, info); } -void hif_log_ce_info(struct hif_opaque_softc *hif_ctx, uint8_t *data, +void hif_log_ce_info(struct hif_softc *scn, uint8_t *data, unsigned int *offset) { - struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); struct hang_event_info info = {0}; static uint32_t tracked_ce = BIT(CE_ID_1) | BIT(CE_ID_2) | BIT(CE_ID_3) | BIT(CE_ID_4) | BIT(CE_ID_9) | BIT(CE_ID_10); diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index 1ccdf15157e6..ae1ac03d7e96 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -46,6 +46,10 @@ #include "hif_napi.h" #include "hif_unit_test_suspend_i.h" #include "qdf_module.h" +#ifdef HIF_CE_LOG_INFO +#include +#include +#endif void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start) { @@ -429,6 +433,87 @@ void hif_get_cfg_from_psoc(struct hif_softc *scn, } #endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */ +#ifdef HIF_CE_LOG_INFO +/** + * hif_recovery_notifier_cb - Recovery notifier callback to log + * hang event data + * @block: notifier block + * @state: state + * @data: notifier data + * + * Return: status + */ +static +int hif_recovery_notifier_cb(struct notifier_block *block, unsigned long state, + void *data) +{ + struct qdf_notifer_data *notif_data = data; + qdf_notif_block *notif_block; + struct hif_softc *hif_handle; + + if (!data || !block) + return -EINVAL; + + notif_block = qdf_container_of(block, qdf_notif_block, notif_block); + + hif_handle = notif_block->priv_data; + if (!hif_handle) + return -EINVAL; + + hif_log_ce_info(hif_handle, notif_data->hang_data, + ¬if_data->offset); + + return 0; +} + +/** + * hif_register_recovery_notifier - Register hif recovery notifier + * @hif_handle: hif handle + * + * Return: status + */ +static +QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle) +{ + qdf_notif_block *hif_notifier; + + if (!hif_handle) + return QDF_STATUS_E_FAILURE; + + hif_notifier = &hif_handle->hif_recovery_notifier; + + hif_notifier->notif_block.notifier_call = hif_recovery_notifier_cb; + hif_notifier->priv_data = hif_handle; + return qdf_hang_event_register_notifier(hif_notifier); +} + +/** + * hif_unregister_recovery_notifier - Un-register hif recovery notifier + * @hif_handle: hif handle + * + * Return: status + */ +static +QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle) +{ + qdf_notif_block *hif_notifier = &hif_handle->hif_recovery_notifier; + + return qdf_hang_event_unregister_notifier(hif_notifier); +} +#else +static inline +QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle) +{ + return QDF_STATUS_SUCCESS; +} + +static inline +QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle) +{ + return QDF_STATUS_SUCCESS; +} +#endif + struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, uint32_t mode, enum qdf_bus_type bus_type, @@ -610,6 +695,7 @@ QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev, } hif_ut_suspend_init(scn); + hif_register_recovery_notifier(scn); /* * Flag to avoid potential unallocated memory access from MSI @@ -639,6 +725,8 @@ void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type) if (!scn) return; + hif_unregister_recovery_notifier(scn); + hif_nointrs(scn); if (scn->hif_init_done == false) hif_shutdown_device(hif_ctx); diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h index ae0adada08bb..fdec0e83e7e4 100644 --- a/hif/src/hif_main.h +++ b/hif/src/hif_main.h @@ -39,6 +39,9 @@ #include "hif.h" #include "multibus.h" #include "hif_unit_test_suspend_i.h" +#ifdef HIF_CE_LOG_INFO +#include "qdf_notifier.h" +#endif #define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 #define HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS 60 @@ -239,6 +242,9 @@ struct hif_softc { qdf_shared_mem_t *ipa_ce_ring; #endif struct hif_cfg ini_cfg; +#ifdef HIF_CE_LOG_INFO + qdf_notif_block hif_recovery_notifier; +#endif }; static inline