qcacmn: Refactor Unit-Test Suspend
Unit-Test suspend needs to be decoupled from the copy engine implementation in HIF. Split the HIF portion of Unit-Test suspend into their own files, and clean up naming, etc. Change-Id: Ic36c5b98c505f6b62ddf94336838a9e53fe8aa78 CRs-Fixed: 2055328
This commit is contained in:
@@ -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,
|
||||
|
59
hif/inc/hif_unit_test_suspend.h
Normal file
59
hif/inc/hif_unit_test_suspend.h
Normal file
@@ -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_ */
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
114
hif/src/hif_unit_test_suspend.c
Normal file
114
hif/src/hif_unit_test_suspend.c
Normal file
@@ -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;
|
||||
}
|
84
hif/src/hif_unit_test_suspend_i.h
Normal file
84
hif/src/hif_unit_test_suspend_i.h
Normal file
@@ -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_ */
|
Reference in New Issue
Block a user