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:
Dustin Brown
2017-06-01 14:31:01 -07:00
committed by snandini
parent 0014f6238e
commit ccf859d9f5
8 changed files with 273 additions and 125 deletions

View File

@@ -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_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); 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 hif_register_ext_group_int_handler(struct hif_opaque_softc *hif_ctx,
uint32_t numirq, uint32_t irq[], ext_intr_handler handler, uint32_t numirq, uint32_t irq[], ext_intr_handler handler,

View 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_ */

View File

@@ -2415,16 +2415,6 @@ static inline void hif_post_static_buf_to_target(struct hif_softc *scn)
} }
#endif #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 * hif_config_ce() - configure copy engines
* @scn: hif context * @scn: hif context
@@ -2511,7 +2501,6 @@ int hif_config_ce(struct hif_softc *scn)
HIF_DBG("%s: ce_init done", __func__); HIF_DBG("%s: ce_init done", __func__);
init_tasklet_workers(hif_hdl); init_tasklet_workers(hif_hdl);
hif_fake_apps_init_ctx(scn);
HIF_DBG("%s: X, ret = %d", __func__, rv); HIF_DBG("%s: X, ret = %d", __func__, rv);

View File

@@ -270,73 +270,19 @@ int hif_drain_tasklets(struct hif_softc *scn)
#ifdef WLAN_SUSPEND_RESUME_TEST #ifdef WLAN_SUSPEND_RESUME_TEST
/** /**
* hif_fake_apps_resume_work() - Work handler for fake apps resume callback * hif_interrupt_is_ut_resume(): Tests if an irq on the given copy engine should
* @work: The work struct being passed from the linux kernel * trigger a unit-test resume.
* * @scn: The HIF context to operate on
* Return: none
*/
void hif_fake_apps_resume_work(struct work_struct *work)
{
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 * @ce_id: The copy engine Id from the originating interrupt
* *
* Return: true if the raised irq should trigger a fake apps resume * Return: true if the raised irq should trigger a unit-test resume
*/ */
static bool hif_interrupt_is_fake_apps_resume(struct hif_opaque_softc *hif_ctx, static bool hif_interrupt_is_ut_resume(struct hif_softc *scn, int ce_id)
int ce_id)
{ {
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
int errno; int errno;
uint8_t wake_ce_id; 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; return false;
/* ensure passed ce_id matches wake ce_id */ /* 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; 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 #else
static inline bool 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; return false;
} }
#endif /* WLAN_SUSPEND_RESUME_TEST */
static inline void
hif_trigger_fake_apps_resume(struct hif_opaque_softc *hif_ctx)
{
}
#endif /* End of WLAN_SUSPEND_RESUME_TEST */
/** /**
* hif_snoc_interrupt_handler() - hif_snoc_interrupt_handler * 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_record_ce_desc_event(scn, ce_id, HIF_IRQ_EVENT, NULL, NULL, 0);
hif_ce_increment_interrupt_count(hif_ce_state, ce_id); hif_ce_increment_interrupt_count(hif_ce_state, ce_id);
if (unlikely(hif_interrupt_is_fake_apps_resume(hif_hdl, ce_id))) { if (unlikely(hif_interrupt_is_ut_resume(scn, ce_id))) {
hif_trigger_fake_apps_resume(hif_hdl); hif_ut_fw_resume(scn);
hif_irq_enable(scn, ce_id); hif_irq_enable(scn, ce_id);
return IRQ_HANDLED; return IRQ_HANDLED;
} }

View File

@@ -50,6 +50,7 @@
#include "hal_api.h" #include "hal_api.h"
#endif #endif
#include "hif_napi.h" #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) 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; return status;
} }
hif_ut_suspend_init(scn);
/* /*
* Flag to avoid potential unallocated memory access from MSI * Flag to avoid potential unallocated memory access from MSI
* interrupt handler which could get scheduled as soon as MSI * interrupt handler which could get scheduled as soon as MSI

View File

@@ -47,6 +47,7 @@
#include "cepci.h" #include "cepci.h"
#include "hif.h" #include "hif.h"
#include "multibus.h" #include "multibus.h"
#include "hif_unit_test_suspend_i.h"
#define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 #define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50
#define HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS 60 #define HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS 60
@@ -118,20 +119,6 @@ struct hif_ce_stats {
int ce_ring_delta_fail_count; 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_softc {
struct hif_opaque_softc osc; struct hif_opaque_softc osc;
struct hif_config_info hif_config; struct hif_config_info hif_config;
@@ -178,9 +165,7 @@ struct hif_softc {
uint32_t nss_wifi_ol_mode; uint32_t nss_wifi_ol_mode;
#endif #endif
void *hal_soc; void *hal_soc;
#ifdef WLAN_SUSPEND_RESUME_TEST struct hif_ut_suspend_context ut_suspend_ctx;
struct fake_apps_context fake_apps_ctx;
#endif /* WLAN_SUSPEND_RESUME_TEST */
uint32_t hif_attribute; uint32_t hif_attribute;
}; };

View 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;
}

View 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_ */