From 63c5956a0156ae23b61fdb6595617393cf06dd07 Mon Sep 17 00:00:00 2001 From: Edayilliam Jayadev Date: Thu, 16 Feb 2023 17:42:31 +0530 Subject: [PATCH] qcacmn: Add APIs to schedule/cancel custom callbacks Add HIF/CE layer APIs to schedule/cancel custom callbacks. Change-Id: I9cc7dcf73a726cb1ed2d7945d6ce9e736d42af52 CRs-Fixed: 3408690 --- hif/inc/hif.h | 45 ++++++++++++++++++++++++++ hif/src/ce/ce_api.h | 43 +++++++++++++++++++++++++ hif/src/ce/ce_internal.h | 5 +++ hif/src/ce/ce_main.c | 68 ++++++++++++++++++++++++++++++++++++++++ hif/src/ce/ce_service.c | 47 +++++++++++++++++++++++++++ hif/src/ce/ce_tasklet.c | 42 +++++++++++++++++++++++++ 6 files changed, 250 insertions(+) diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 93dc82f19d..d65d58d601 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -1075,6 +1075,51 @@ struct hif_pipe_addl_info { struct hif_bus_id; +#ifdef CUSTOM_CB_SCHEDULER_SUPPORT +/** + * hif_register_ce_custom_cb() - Helper API to register the custom callback + * @hif_ctx: HIF opaque context + * @pipe: Pipe number + * @custom_cb: Custom call back function pointer + * @custom_cb_context: Custom callback context + * + * return: QDF_STATUS + */ +QDF_STATUS +hif_register_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe, + void (*custom_cb)(void *), void *custom_cb_context); + +/** + * hif_unregister_ce_custom_cb() - Helper API to unregister the custom callback + * @hif_ctx: HIF opaque context + * @pipe: Pipe number + * + * return: QDF_STATUS + */ +QDF_STATUS +hif_unregister_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe); + +/** + * hif_enable_ce_custom_cb() - Helper API to enable the custom callback + * @hif_ctx: HIF opaque context + * @pipe: Pipe number + * + * return: QDF_STATUS + */ +QDF_STATUS +hif_enable_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe); + +/** + * hif_disable_ce_custom_cb() - Helper API to disable the custom callback + * @hif_ctx: HIF opaque context + * @pipe: Pipe number + * + * return: QDF_STATUS + */ +QDF_STATUS +hif_disable_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe); +#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */ + void hif_claim_device(struct hif_opaque_softc *hif_ctx); QDF_STATUS hif_get_config_item(struct hif_opaque_softc *hif_ctx, int opcode, void *config, uint32_t config_len); diff --git a/hif/src/ce/ce_api.h b/hif/src/ce/ce_api.h index 2a3540b804..912a3e098b 100644 --- a/hif/src/ce/ce_api.h +++ b/hif/src/ce/ce_api.h @@ -375,6 +375,49 @@ QDF_STATUS ce_completed_send_next(struct CE_handle *copyeng, unsigned int *hw_idx, uint32_t *toeplitz_hash_result); +#ifdef CUSTOM_CB_SCHEDULER_SUPPORT +/*==================CE custom callbacks=================================*/ + +/** + * ce_register_custom_cb() - Helper API to register the custom callback + * @copyeng: Pointer to CE handle + * @custom_cb: Custom call back function pointer + * @custom_cb_context: Custom callback context + * + * return: void + */ +void +ce_register_custom_cb(struct CE_handle *copyeng, void (*custom_cb)(void *), + void *custom_cb_context); + +/** + * ce_unregister_custom_cb() - Helper API to unregister the custom callback + * @copyeng: Pointer to CE handle + * + * return: void + */ +void +ce_unregister_custom_cb(struct CE_handle *copyeng); + +/** + * ce_enable_custom_cb() - Helper API to enable the custom callback + * @copyeng: Pointer to CE handle + * + * return: void + */ +void +ce_enable_custom_cb(struct CE_handle *copyeng); + +/** + * ce_disable_custom_cb() - Helper API to disable the custom callback + * @copyeng: Pointer to CE handle + * + * return: void + */ +void +ce_disable_custom_cb(struct CE_handle *copyeng); +#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */ + /*==================CE Engine Initialization=================================*/ /* Initialize an instance of a CE */ diff --git a/hif/src/ce/ce_internal.h b/hif/src/ce/ce_internal.h index 16640bf3ac..f420cde7fc 100644 --- a/hif/src/ce/ce_internal.h +++ b/hif/src/ce/ce_internal.h @@ -151,6 +151,11 @@ struct CE_state { CE_watermark_cb watermark_cb; void *wm_context; +#ifdef CUSTOM_CB_SCHEDULER_SUPPORT + qdf_atomic_t custom_cb_pending; + void (*custom_cb)(void *arg); + void *custom_cb_context; +#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */ /*Record the state of the copy compl interrupt */ int disable_copy_compl_intr; diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index 2656a5c52e..b74ff642ee 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -3012,6 +3012,74 @@ void hif_send_complete_check(struct hif_opaque_softc *hif_ctx, uint8_t pipe, #endif } +#ifdef CUSTOM_CB_SCHEDULER_SUPPORT +QDF_STATUS +hif_register_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe, + void (*custom_cb)(void *), void *custom_cb_context) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct HIF_CE_pipe_info *pipe_info; + + if (pipe >= CE_COUNT_MAX) + return QDF_STATUS_E_INVAL; + + pipe_info = &hif_state->pipe_info[pipe]; + ce_register_custom_cb(pipe_info->ce_hdl, custom_cb, custom_cb_context); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +hif_unregister_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct HIF_CE_pipe_info *pipe_info; + + if (pipe >= CE_COUNT_MAX) + return QDF_STATUS_E_INVAL; + + pipe_info = &hif_state->pipe_info[pipe]; + ce_unregister_custom_cb(pipe_info->ce_hdl); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +hif_enable_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct HIF_CE_pipe_info *pipe_info; + + if (pipe >= CE_COUNT_MAX) + return QDF_STATUS_E_INVAL; + + pipe_info = &hif_state->pipe_info[pipe]; + ce_enable_custom_cb(pipe_info->ce_hdl); + ce_dispatch_interrupt(pipe, &hif_state->tasklets[pipe]); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +hif_disable_ce_custom_cb(struct hif_opaque_softc *hif_ctx, uint8_t pipe) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct HIF_CE_pipe_info *pipe_info; + + if (pipe >= CE_COUNT_MAX) + return QDF_STATUS_E_INVAL; + + pipe_info = &hif_state->pipe_info[pipe]; + ce_disable_custom_cb(pipe_info->ce_hdl); + + return QDF_STATUS_SUCCESS; +} +#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */ + #if defined(CE_TASKLET_SCHEDULE_ON_FULL) && defined(CE_TASKLET_DEBUG_ENABLE) #define CE_RING_FULL_THRESHOLD_TIME 3000000 #define CE_RING_FULL_THRESHOLD 1024 diff --git a/hif/src/ce/ce_service.c b/hif/src/ce/ce_service.c index 47ac88283a..d8f5724bf7 100644 --- a/hif/src/ce/ce_service.c +++ b/hif/src/ce/ce_service.c @@ -1481,6 +1481,53 @@ ce_watermark_cb_register(struct CE_handle *copyeng, CE_state->misc_cbs = 1; } +#ifdef CUSTOM_CB_SCHEDULER_SUPPORT +void +ce_register_custom_cb(struct CE_handle *copyeng, void (*custom_cb)(void *), + void *custom_cb_context) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + + CE_state->custom_cb = custom_cb; + CE_state->custom_cb_context = custom_cb_context; + qdf_atomic_init(&CE_state->custom_cb_pending); +} + +void +ce_unregister_custom_cb(struct CE_handle *copyeng) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + + qdf_assert_always(!qdf_atomic_read(&CE_state->custom_cb_pending)); + CE_state->custom_cb = NULL; + CE_state->custom_cb_context = NULL; +} + +void +ce_enable_custom_cb(struct CE_handle *copyeng) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + int32_t custom_cb_pending; + + qdf_assert_always(CE_state->custom_cb); + qdf_assert_always(CE_state->custom_cb_context); + + custom_cb_pending = qdf_atomic_inc_return(&CE_state->custom_cb_pending); + qdf_assert_always(custom_cb_pending >= 1); +} + +void +ce_disable_custom_cb(struct CE_handle *copyeng) +{ + struct CE_state *CE_state = (struct CE_state *)copyeng; + + qdf_assert_always(CE_state->custom_cb); + qdf_assert_always(CE_state->custom_cb_context); + + qdf_atomic_dec_if_positive(&CE_state->custom_cb_pending); +} +#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */ + bool ce_get_rx_pending(struct hif_softc *scn) { int CE_id; diff --git a/hif/src/ce/ce_tasklet.c b/hif/src/ce/ce_tasklet.c index 70728134ae..4e008602bd 100644 --- a/hif/src/ce/ce_tasklet.c +++ b/hif/src/ce/ce_tasklet.c @@ -400,6 +400,46 @@ void hif_latency_detect_tasklet_exec( {} #endif +#ifdef CUSTOM_CB_SCHEDULER_SUPPORT +/** + * ce_get_custom_cb_pending() - Helper API to check whether the custom + * callback is pending + * @CE_state: Pointer to CE state + * + * return: bool + */ +static bool +ce_get_custom_cb_pending(struct CE_state *CE_state) +{ + return (qdf_atomic_dec_if_positive(&CE_state->custom_cb_pending) >= 0); +} + +/** + * ce_execute_custom_cb() - Helper API to execute custom callback + * @CE_state: Pointer to CE state + * + * return: void + */ +static void +ce_execute_custom_cb(struct CE_state *CE_state) +{ + while (ce_get_custom_cb_pending(CE_state) && CE_state->custom_cb && + CE_state->custom_cb_context) + CE_state->custom_cb(CE_state->custom_cb_context); +} +#else +/** + * ce_execute_custom_cb() - Helper API to execute custom callback + * @CE_state: Pointer to CE state + * + * return: void + */ +static void +ce_execute_custom_cb(struct CE_state *CE_state) +{ +} +#endif /* CUSTOM_CB_SCHEDULER_SUPPORT */ + /** * ce_tasklet() - ce_tasklet * @data: data @@ -428,6 +468,8 @@ static void ce_tasklet(unsigned long data) QDF_BUG(0); } + ce_execute_custom_cb(CE_state); + ce_per_engine_service(scn, tasklet_entry->ce_id); if (ce_check_rx_pending(CE_state) && tasklet_entry->inited) {