qcacld-3.0: Power offload unit test framework enhancements

Recently host power offload suspend/resume has switched to 3
stage process. Enhance power offload unit test framework accordingly,
and improve error handling.

Change-Id: I8cc1e955fbaca631ee7fd76b0c907d1e68c836bf
CRs-Fixed: 1072423
This commit is contained in:
Rajeev Kumar 2016-09-24 12:29:25 -07:00 • committed by qcabuildsw
commit 9bb2e85aff
5 changed files with 188 additions and 36 deletions

View file

@ -38,7 +38,9 @@
int wlan_hdd_register_driver(void);
void wlan_hdd_unregister_driver(void);
int wlan_hdd_bus_suspend(pm_message_t state);
int wlan_hdd_bus_suspend_noirq(void);
int wlan_hdd_bus_resume(void);
int wlan_hdd_bus_resume_noirq(void);
void hdd_hif_close(void *hif_ctx);
int hdd_hif_open(struct device *dev, void *bdev, const hif_bus_id *bid,
enum qdf_bus_type bus_type, bool reinit);

View file

@ -200,4 +200,26 @@ void hdd_wlan_suspend_resume_event(uint8_t state) {}
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
/*
* Unit-test suspend/resume is a testing feature that allows putting firmware
* into WoW suspend irrespective of Apps suspend status. It emulates the chain
* of events that occur durring normal system-level suspend/resume, such as
* initiating all of the suspend/resume stages in the correct order, and
* enabling/disabling appropriate copy engine irqs.
*/
#ifdef WLAN_SUSPEND_RESUME_TEST
int hdd_wlan_fake_apps_resume(struct wiphy *wiphy);
int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy);
#else
static inline int hdd_wlan_fake_apps_resume(struct wiphy *wiphy)
{
return 0;
}
static inline int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy)
{
return 0;
}
#endif /* WLAN_SUSPEND_RESUME_TEST */
#endif /* __WLAN_HDD_POWER_H */

View file

@ -74,6 +74,7 @@
#include "cds_concurrency.h"
#include "cdp_txrx_flow_ctrl_v2.h"
#include "pld_common.h"
#include "wlan_hdd_driver_ops.h"
/* Preprocessor definitions and constants */
#define HDD_SSR_BRING_UP_TIME 30000
@ -2349,3 +2350,159 @@ int hdd_set_qpower_config(hdd_context_t *hddctx, hdd_adapter_t *adapter,
}
return 0;
}
#ifdef WLAN_SUSPEND_RESUME_TEST
/*
* On Rome/iHelium there are 12 CE irqs and #2 is the wake irq. This may not be
* a valid assumption on future platforms.
*/
#define CE_IRQ_COUNT 12
#define CE_WAKE_IRQ 2
static struct wiphy *g_wiphy;
#define HDD_FA_SUSPENDED_BIT (0)
static unsigned long fake_apps_state;
static int __hdd_wlan_fake_apps_resume(struct wiphy *wiphy);
/**
* hdd_wlan_fake_apps_resume_irq_callback() - Irq callback function for resuming
* from unit-test initiated suspend from irq wakeup signal
* @val: interrupt val
*
* Resume wlan after getting very 1st CE interrupt from target
*
* Return: none
*/
static void hdd_wlan_fake_apps_resume_irq_callback(uint32_t val)
{
hdd_info("Trigger unit-test resume WLAN; val: 0x%x", val);
QDF_BUG(g_wiphy);
__hdd_wlan_fake_apps_resume(g_wiphy);
g_wiphy = NULL;
}
/**
* hdd_wlan_fake_apps_suspend() - Initiate a unit-test triggered suspend
* @wiphy: wiphy struct from a validated hdd context
*
* Return: Zero on success, suspend related non-zero error code on failure
*/
int hdd_wlan_fake_apps_suspend(struct wiphy *wiphy)
{
qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
struct hif_opaque_softc *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
pm_message_t state;
int i, resume_err, suspend_err;
hdd_info("Unit-test suspend WLAN");
if (test_and_set_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state)) {
hdd_info("Already unit-test suspended; Nothing to do");
return 0;
}
suspend_err = wlan_hdd_cfg80211_suspend_wlan(wiphy, NULL);
if (suspend_err)
goto resume_done;
state.event = PM_EVENT_SUSPEND;
suspend_err = wlan_hdd_bus_suspend(state);
if (suspend_err)
goto cfg80211_resume;
/* simulate kernel disabling irqs */
for (i = 0; i < CE_IRQ_COUNT; i++)
pld_disable_irq(qdf_dev->dev, i);
suspend_err = wlan_hdd_bus_suspend_noirq();
if (suspend_err)
goto enable_irqs_and_bus_resume;
/* re-enable wake irq */
pld_enable_irq(qdf_dev->dev, CE_WAKE_IRQ);
/* pass wiphy to callback via global variable */
g_wiphy = wiphy;
hif_fake_apps_suspend(hif_ctx, hdd_wlan_fake_apps_resume_irq_callback);
return 0;
enable_irqs_and_bus_resume:
/* re-enable irqs */
for (i = 0; i < CE_IRQ_COUNT; i++)
pld_enable_irq(qdf_dev->dev, i);
resume_err = wlan_hdd_bus_resume();
QDF_BUG(resume_err == 0);
cfg80211_resume:
resume_err = wlan_hdd_cfg80211_resume_wlan(wiphy);
QDF_BUG(resume_err == 0);
resume_done:
clear_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state);
hdd_err("Unit-test suspend failed: %d", suspend_err);
return suspend_err;
}
/**
* hdd_wlan_fake_apps_resume() - Resume from unit-test triggered suspend
* @wiphy: wiphy struct from a validated hdd context
*
* Return: Zero on success, calls QDF_BUG() on failure
*/
int hdd_wlan_fake_apps_resume(struct wiphy *wiphy)
{
struct hif_opaque_softc *hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
int err;
hif_fake_apps_resume(hif_ctx);
err = __hdd_wlan_fake_apps_resume(wiphy);
if (err) {
hif_fake_apps_suspend(hif_ctx,
hdd_wlan_fake_apps_resume_irq_callback);
return err;
}
return 0;
}
/**
* __hdd_wlan_fake_apps_resume() - The core logic for
* hdd_wlan_fake_apps_resume() skipping the call to hif_fake_apps_resume(),
* which is only need for non-irq resume
* @wiphy: wiphy struct from a validated hdd context
*
* Return: Zero on success, calls QDF_BUG() on failure
*/
static int __hdd_wlan_fake_apps_resume(struct wiphy *wiphy)
{
qdf_device_t qdf_dev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
int i, resume_err;
hdd_info("Unit-test resume WLAN");
if (!test_and_clear_bit(HDD_FA_SUSPENDED_BIT, &fake_apps_state)) {
hdd_info("Not unit-test suspended; Nothing to do");
return 0;
}
/* disable wake irq */
pld_disable_irq(qdf_dev->dev, CE_WAKE_IRQ);
resume_err = wlan_hdd_bus_resume_noirq();
QDF_BUG(resume_err == 0);
/* simulate kernel enable irqs */
for (i = 0; i < CE_IRQ_COUNT; i++)
pld_enable_irq(qdf_dev->dev, i);
resume_err = wlan_hdd_bus_resume();
QDF_BUG(resume_err == 0);
resume_err = wlan_hdd_cfg80211_resume_wlan(wiphy);
QDF_BUG(resume_err == 0);
return 0;
}
#endif

View file

@ -92,6 +92,7 @@
#ifdef WLAN_SUSPEND_RESUME_TEST
#include "wlan_hdd_driver_ops.h"
#include "hif.h"
#include "pld_common.h"
#endif
#define HDD_FINISH_ULA_TIME_OUT 800
@ -439,10 +440,9 @@ static const hdd_freq_chan_map_t freq_chan_map[] = {
#define WE_ENABLE_FW_PROFILE 4
#define WE_SET_FW_PROFILE_HIST_INTVL 5
#ifdef WLAN_SUSPEND_RESUME_TEST
/* Private sub-ioctl for initiating WoW suspend without Apps suspend */
#define WE_SET_WLAN_SUSPEND 6
#define WE_SET_WLAN_RESUME 7
#endif
/* (SIOCIWFIRSTPRIV + 29) is currently unused */
@ -9782,25 +9782,6 @@ static int wlan_hdd_set_mon_chan(hdd_adapter_t *adapter, uint32_t chan,
return qdf_status_to_os_return(status);
}
#ifdef WLAN_SUSPEND_RESUME_TEST
static void *g_wiphy;
/**
* hdd_wlan_trigger_resume() - resume wlan
* @val: interrupt val
*
* Resume wlan after getting very 1st CE interrupt from target
*
* Return: none
*/
static void hdd_wlan_trigger_resume(uint32_t val)
{
hdd_err("Resume WLAN val 0x%x", val);
wlan_hdd_bus_resume();
wlan_hdd_cfg80211_resume_wlan(g_wiphy);
}
#endif
static int __iw_set_two_ints_getnone(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
@ -9810,10 +9791,6 @@ static int __iw_set_two_ints_getnone(struct net_device *dev,
int sub_cmd = value[0];
int ret;
hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(pAdapter);
#ifdef WLAN_SUSPEND_RESUME_TEST
pm_message_t state;
#endif
ENTER_DEV(dev);
@ -9877,21 +9854,12 @@ static int __iw_set_two_ints_getnone(struct net_device *dev,
case WE_SET_MON_MODE_CHAN:
ret = wlan_hdd_set_mon_chan(pAdapter, value[1], value[2]);
break;
#ifdef WLAN_SUSPEND_RESUME_TEST
case WE_SET_WLAN_SUSPEND:
hdd_err("Suspend WLAN");
g_wiphy = hdd_ctx->wiphy;
state.event = PM_EVENT_SUSPEND;
ret = wlan_hdd_cfg80211_suspend_wlan(hdd_ctx->wiphy, NULL);
wlan_hdd_bus_suspend(state);
hif_fake_apps_suspend(hdd_wlan_trigger_resume);
ret = hdd_wlan_fake_apps_suspend(hdd_ctx->wiphy);
break;
case WE_SET_WLAN_RESUME:
hdd_err("Resume WLAN");
wlan_hdd_bus_resume();
ret = wlan_hdd_cfg80211_resume_wlan(hdd_ctx->wiphy);
ret = hdd_wlan_fake_apps_resume(hdd_ctx->wiphy);
break;
#endif
default:
hdd_err("Invalid IOCTL command %d", sub_cmd);
break;

View file

@ -379,4 +379,7 @@ void *pld_smmu_get_mapping(struct device *dev);
int pld_smmu_map(struct device *dev, phys_addr_t paddr,
uint32_t *iova_addr, size_t size);
unsigned int pld_socinfo_get_serial_number(struct device *dev);
void pld_enable_irq(struct device *dev, unsigned int ce_id);
void pld_disable_irq(struct device *dev, unsigned int ce_id);
#endif