diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 2fe3d33738..a7a45cc9a6 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -853,12 +853,6 @@ int hif_bus_reset_resume(struct hif_opaque_softc *hif_ctx); void hif_set_attribute(struct hif_opaque_softc *osc, uint8_t hif_attrib); void *hif_get_lro_info(int ctx_id, struct hif_opaque_softc *hif_hdl); -#ifdef WLAN_SUSPEND_RESUME_TEST -typedef void (*hif_fake_resume_callback)(uint32_t val); -void hif_fake_apps_suspend(struct hif_opaque_softc *hif_ctx, - hif_fake_resume_callback callback); -void hif_fake_apps_resume(struct hif_opaque_softc *hif_ctx); -#endif uint32_t hif_register_ext_group_int_handler(struct hif_opaque_softc *hif_ctx, uint32_t numirq, uint32_t irq[], ext_intr_handler handler, diff --git a/hif/inc/hif_unit_test_suspend.h b/hif/inc/hif_unit_test_suspend.h new file mode 100644 index 0000000000..cb036ecabb --- /dev/null +++ b/hif/inc/hif_unit_test_suspend.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: Public unit-test related APIs for triggering WoW suspend/resume while + * the application processor is still up. + */ + +#ifndef _HIF_UNIT_TEST_SUSPEND_H_ +#define _HIF_UNIT_TEST_SUSPEND_H_ + +#ifdef WLAN_SUSPEND_RESUME_TEST + +#include "qdf_status.h" +#include "hif.h" + +typedef void (*hif_ut_resume_callback)(void); + +/** + * hif_ut_apps_suspend() - Setup unit-test related suspend state. + * @opaque_scn: The HIF context to operate on + * @callback: The function to call when unit-test resume is triggered + * + * Call after a normal WoW suspend has been completed. + * + * Return: QDF_STATUS + */ +QDF_STATUS hif_ut_apps_suspend(struct hif_opaque_softc *opaque_scn, + hif_ut_resume_callback callback); + +/** + * hif_ut_apps_resume() - Cleanup unit-test related suspend state. + * @opaque_scn: The HIF context to operate on + * + * Call before doing a normal WoW resume if suspend was initiated via + * unit-test suspend. + * + * Return: QDF_STATUS + */ +QDF_STATUS hif_ut_apps_resume(struct hif_opaque_softc *opaque_scn); + +#endif /* WLAN_SUSPEND_RESUME_TEST */ + +#endif /* _HIF_UNIT_TEST_SUSPEND_H_ */ diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index d91d991d12..c03c2d1125 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -2415,16 +2415,6 @@ static inline void hif_post_static_buf_to_target(struct hif_softc *scn) } #endif -#ifdef WLAN_SUSPEND_RESUME_TEST -static void hif_fake_apps_init_ctx(struct hif_softc *scn) -{ - INIT_WORK(&scn->fake_apps_ctx.resume_work, - hif_fake_apps_resume_work); -} -#else -static inline void hif_fake_apps_init_ctx(struct hif_softc *scn) {} -#endif - /** * hif_config_ce() - configure copy engines * @scn: hif context @@ -2511,7 +2501,6 @@ int hif_config_ce(struct hif_softc *scn) HIF_DBG("%s: ce_init done", __func__); init_tasklet_workers(hif_hdl); - hif_fake_apps_init_ctx(scn); HIF_DBG("%s: X, ret = %d", __func__, rv); diff --git a/hif/src/ce/ce_tasklet.c b/hif/src/ce/ce_tasklet.c index 8f938742c3..73e0a14443 100644 --- a/hif/src/ce/ce_tasklet.c +++ b/hif/src/ce/ce_tasklet.c @@ -270,73 +270,19 @@ int hif_drain_tasklets(struct hif_softc *scn) #ifdef WLAN_SUSPEND_RESUME_TEST /** - * hif_fake_apps_resume_work() - Work handler for fake apps resume callback - * @work: The work struct being passed from the linux kernel + * hif_interrupt_is_ut_resume(): Tests if an irq on the given copy engine should + * trigger a unit-test resume. + * @scn: The HIF context to operate on + * @ce_id: The copy engine Id from the originating interrupt * - * Return: none + * Return: true if the raised irq should trigger a unit-test resume */ -void hif_fake_apps_resume_work(struct work_struct *work) +static bool hif_interrupt_is_ut_resume(struct hif_softc *scn, int ce_id) { - struct fake_apps_context *ctx = - container_of(work, struct fake_apps_context, resume_work); - - QDF_BUG(ctx->resume_callback); - ctx->resume_callback(0); - ctx->resume_callback = NULL; -} - -/** - * hif_fake_apps_suspend(): Setup unit-test related suspend state. Call after - * a normal WoW suspend has been completed. - * @hif_ctx: The HIF context to operate on - * @callback: The function to call when fake apps resume is triggered - * - * Set the fake suspend flag such that hif knows that it will need - * to fake the apps resume process using hdd_trigger_fake_apps_resume - * - * Return: none - */ -void hif_fake_apps_suspend(struct hif_opaque_softc *hif_ctx, - hif_fake_resume_callback callback) -{ - struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); - - scn->fake_apps_ctx.resume_callback = callback; - set_bit(HIF_FA_SUSPENDED_BIT, &scn->fake_apps_ctx.state); -} - -/** - * hif_fake_apps_resume(): Cleanup unit-test related suspend state. Call before - * doing a normal WoW resume if suspend was initiated via fake apps - * suspend. - * @hif_ctx: The HIF context to operate on - * - * Return: none - */ -void hif_fake_apps_resume(struct hif_opaque_softc *hif_ctx) -{ - struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); - - clear_bit(HIF_FA_SUSPENDED_BIT, &scn->fake_apps_ctx.state); - scn->fake_apps_ctx.resume_callback = NULL; -} - -/** - * hif_interrupt_is_fake_apps_resume(): Determines if the raised irq should - * trigger a fake apps resume. - * @hif_ctx: The HIF context to operate on - * @ce_id: The copy engine Id from the originating interrupt - * - * Return: true if the raised irq should trigger a fake apps resume - */ -static bool hif_interrupt_is_fake_apps_resume(struct hif_opaque_softc *hif_ctx, - int ce_id) -{ - struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); int errno; uint8_t wake_ce_id; - if (!test_bit(HIF_FA_SUSPENDED_BIT, &scn->fake_apps_ctx.state)) + if (!hif_is_ut_suspended(scn)) return false; /* ensure passed ce_id matches wake ce_id */ @@ -348,39 +294,13 @@ static bool hif_interrupt_is_fake_apps_resume(struct hif_opaque_softc *hif_ctx, return ce_id == wake_ce_id; } - -/** - * hif_trigger_fake_apps_resume(): Trigger a fake apps resume by scheduling the - * previously registered callback for execution - * @hif_ctx: The HIF context to operate on - * - * Return: None - */ -static void hif_trigger_fake_apps_resume(struct hif_opaque_softc *hif_ctx) -{ - struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); - - if (!test_and_clear_bit(HIF_FA_SUSPENDED_BIT, - &scn->fake_apps_ctx.state)) - return; - - schedule_work(&scn->fake_apps_ctx.resume_work); -} - #else - static inline bool -hif_interrupt_is_fake_apps_resume(struct hif_opaque_softc *hif_ctx, int ce_id) +hif_interrupt_is_ut_resume(struct hif_softc *scn, int ce_id) { return false; } - -static inline void -hif_trigger_fake_apps_resume(struct hif_opaque_softc *hif_ctx) -{ -} - -#endif /* End of WLAN_SUSPEND_RESUME_TEST */ +#endif /* WLAN_SUSPEND_RESUME_TEST */ /** * hif_snoc_interrupt_handler() - hif_snoc_interrupt_handler @@ -482,8 +402,8 @@ irqreturn_t ce_dispatch_interrupt(int ce_id, hif_record_ce_desc_event(scn, ce_id, HIF_IRQ_EVENT, NULL, NULL, 0); hif_ce_increment_interrupt_count(hif_ce_state, ce_id); - if (unlikely(hif_interrupt_is_fake_apps_resume(hif_hdl, ce_id))) { - hif_trigger_fake_apps_resume(hif_hdl); + if (unlikely(hif_interrupt_is_ut_resume(scn, ce_id))) { + hif_ut_fw_resume(scn); hif_irq_enable(scn, ce_id); return IRQ_HANDLED; } diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index f700572b05..b19ff15175 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -50,6 +50,7 @@ #include "hal_api.h" #endif #include "hif_napi.h" +#include "hif_unit_test_suspend_i.h" void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start) { @@ -534,6 +535,8 @@ QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev, return status; } + hif_ut_suspend_init(scn); + /* * Flag to avoid potential unallocated memory access from MSI * interrupt handler which could get scheduled as soon as MSI diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h index 6c05fdc9d2..78f07c0cc6 100644 --- a/hif/src/hif_main.h +++ b/hif/src/hif_main.h @@ -47,6 +47,7 @@ #include "cepci.h" #include "hif.h" #include "multibus.h" +#include "hif_unit_test_suspend_i.h" #define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 #define HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS 60 @@ -118,20 +119,6 @@ struct hif_ce_stats { int ce_ring_delta_fail_count; }; -#ifdef WLAN_SUSPEND_RESUME_TEST -struct fake_apps_context { - unsigned long state; - hif_fake_resume_callback resume_callback; - struct work_struct resume_work; -}; - -enum hif_fake_apps_state_bits { - HIF_FA_SUSPENDED_BIT = 0 -}; - -void hif_fake_apps_resume_work(struct work_struct *work); -#endif /* WLAN_SUSPEND_RESUME_TEST */ - struct hif_softc { struct hif_opaque_softc osc; struct hif_config_info hif_config; @@ -178,9 +165,7 @@ struct hif_softc { uint32_t nss_wifi_ol_mode; #endif void *hal_soc; -#ifdef WLAN_SUSPEND_RESUME_TEST - struct fake_apps_context fake_apps_ctx; -#endif /* WLAN_SUSPEND_RESUME_TEST */ + struct hif_ut_suspend_context ut_suspend_ctx; uint32_t hif_attribute; }; diff --git a/hif/src/hif_unit_test_suspend.c b/hif/src/hif_unit_test_suspend.c new file mode 100644 index 0000000000..938648c325 --- /dev/null +++ b/hif/src/hif_unit_test_suspend.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "qdf_status.h" +#include "hif_main.h" +#include "hif_unit_test_suspend.h" +#include "hif_unit_test_suspend_i.h" + +enum hif_ut_suspend_state_bits { + UT_SUSPENDED_BIT = 0 +}; + +/** + * hif_ut_fw_resume_work() - Work handler for firmware-triggered resume + * @work: The work struct being passed from the linux kernel + * + * Return: None + */ +static void hif_ut_fw_resume_work(struct work_struct *work) +{ + struct hif_ut_suspend_context *ctx = + container_of(work, struct hif_ut_suspend_context, resume_work); + + QDF_BUG(ctx); + if (!ctx) + return; + + QDF_BUG(ctx->resume_callback); + if (!ctx->resume_callback) + return; + + ctx->resume_callback(); + ctx->resume_callback = NULL; +} + +void hif_ut_suspend_init(struct hif_softc *scn) +{ + INIT_WORK(&scn->ut_suspend_ctx.resume_work, hif_ut_fw_resume_work); +} + +bool hif_is_ut_suspended(struct hif_softc *scn) +{ + QDF_BUG(scn); + if (!scn) + return false; + + return test_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state); +} + +QDF_STATUS hif_ut_apps_suspend(struct hif_opaque_softc *opaque_scn, + hif_ut_resume_callback callback) +{ + struct hif_softc *scn = HIF_GET_SOFTC(opaque_scn); + + QDF_BUG(scn); + if (!scn) + return QDF_STATUS_E_INVAL; + + QDF_BUG(callback); + if (!callback) + return QDF_STATUS_E_INVAL; + + if (test_and_set_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state)) + return QDF_STATUS_E_INVAL; + + scn->ut_suspend_ctx.resume_callback = callback; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS hif_ut_apps_resume(struct hif_opaque_softc *opaque_scn) +{ + struct hif_softc *scn = HIF_GET_SOFTC(opaque_scn); + + QDF_BUG(scn); + if (!scn) + return QDF_STATUS_E_INVAL; + + if (!test_and_clear_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state)) + return QDF_STATUS_E_INVAL; + + scn->ut_suspend_ctx.resume_callback = NULL; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS hif_ut_fw_resume(struct hif_softc *scn) +{ + QDF_BUG(scn); + if (!scn) + return QDF_STATUS_E_INVAL; + + if (!test_and_clear_bit(UT_SUSPENDED_BIT, &scn->ut_suspend_ctx.state)) + return QDF_STATUS_E_INVAL; + + schedule_work(&scn->ut_suspend_ctx.resume_work); + + return QDF_STATUS_SUCCESS; +} diff --git a/hif/src/hif_unit_test_suspend_i.h b/hif/src/hif_unit_test_suspend_i.h new file mode 100644 index 0000000000..dedb1e51cc --- /dev/null +++ b/hif/src/hif_unit_test_suspend_i.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: HIF internal unit-test related APIs for triggering WoW suspend/resume + * while the application processor is still up. + */ + +#ifndef _HIF_UNIT_TEST_SUSPEND_I_H_ +#define _HIF_UNIT_TEST_SUSPEND_I_H_ + +#include "qdf_status.h" +#include "hif_main.h" +#include "hif_unit_test_suspend.h" + +#ifdef WLAN_SUSPEND_RESUME_TEST + +struct hif_ut_suspend_context { + unsigned long state; + hif_ut_resume_callback resume_callback; + struct work_struct resume_work; +}; + +/** + * hif_ut_suspend_init() - Initialize the unit-test suspend context + * @scn: the hif context to initialize + * + * Return: None + */ +void hif_ut_suspend_init(struct hif_softc *scn); + +/** + * hif_is_ut_suspended() - Tests if the given hif context is unit-test suspended + * @scn: The HIF context to check + * + * Return: true, if unit-test suspended, otherwise false + */ +bool hif_is_ut_suspended(struct hif_softc *scn); + +/** + * hif_ut_fw_resume() - Initiate a firmware triggered unit-test resume + * @scn: The HIF context to operate on + * + * This schedules the callback previously registered via a call to + * hif_ut_apps_suspend for execution. + * + * Return: QDF_STATUS + */ +QDF_STATUS hif_ut_fw_resume(struct hif_softc *scn); + +#else /* WLAN_SUSPEND_RESUME_TEST */ + +struct hif_ut_suspend_context {}; + +static inline void hif_ut_suspend_init(struct hif_softc *scn) {} + +static inline bool hif_is_ut_suspended(struct hif_softc *scn) +{ + return false; +} + +static inline QDF_STATUS hif_ut_fw_resume(struct hif_softc *scn) +{ + return QDF_STATUS_SUCCESS; +} + +#endif /* WLAN_SUSPEND_RESUME_TEST */ + +#endif /* _HIF_UNIT_TEST_SUSPEND_I_H_ */