qcacld-3.0: Provide wma runtime suspend resume apis

wma has to do some extra steps that were part of 802.11 suspend
for runtime suspend.

Change-Id: I91fbdcacd6c557f30e0d4f422324f2db67cb96dc
CRs-Fixed: 935300
This commit is contained in:
Houston Hoffman
2015-11-10 16:52:05 -08:00
committed by Akash Patel
parent 1688fba972
commit 0c83a5b04c
7 changed files with 231 additions and 35 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
* *
* Previously licensed under the ISC license by Qualcomm Atheros, Inc. * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
* *
@@ -580,6 +580,10 @@ typedef struct sSirMbMsgP2p {
#define SIR_HAL_ENABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 237) #define SIR_HAL_ENABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 237)
#define SIR_HAL_DISABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 238) #define SIR_HAL_DISABLE_UAPSD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 238)
#define SIR_HAL_GATEWAY_PARAM_UPDATE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 239) #define SIR_HAL_GATEWAY_PARAM_UPDATE_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 239)
#define SIR_HAL_RUNTIME_PM_SUSPEND_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 308)
#define SIR_HAL_RUNTIME_PM_RESUME_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 309)
#define SIR_HAL_SET_EPNO_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 313) #define SIR_HAL_SET_EPNO_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 313)
#define SIR_HAL_SET_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 316) #define SIR_HAL_SET_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 316)
#define SIR_HAL_RESET_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 317) #define SIR_HAL_RESET_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 317)

View File

@@ -1197,6 +1197,7 @@ typedef struct {
cdf_event_t wma_ready_event; cdf_event_t wma_ready_event;
cdf_event_t wma_resume_event; cdf_event_t wma_resume_event;
cdf_event_t target_suspend; cdf_event_t target_suspend;
cdf_event_t runtime_suspend;
cdf_event_t recovery_event; cdf_event_t recovery_event;
uint16_t max_station; uint16_t max_station;
uint16_t max_bssid; uint16_t max_bssid;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012-2015 The Linux Foundation. All rights reserved. * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
* *
* Previously licensed under the ISC license by Qualcomm Atheros, Inc. * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
* *
@@ -117,6 +117,8 @@ CDF_STATUS wma_set_reg_domain(void *clientCtxt, v_REGDOMAIN_t regId);
CDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx, CDF_STATUS wma_get_wcnss_software_version(void *p_cds_gctx,
uint8_t *pVersion, uint8_t *pVersion,
uint32_t versionBufferSize); uint32_t versionBufferSize);
int wma_runtime_suspend(void);
int wma_runtime_resume(void);
int wma_bus_suspend(void); int wma_bus_suspend(void);
int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr); int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr);
void wma_target_suspend_acknowledge(void *context); void wma_target_suspend_acknowledge(void *context);
@@ -124,7 +126,7 @@ int wma_bus_resume(void);
int wma_resume_target(WMA_HANDLE handle); int wma_resume_target(WMA_HANDLE handle);
CDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle); CDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle);
CDF_STATUS wma_disable_d0wow_in_fw(WMA_HANDLE handle); CDF_STATUS wma_disable_d0wow_in_fw(WMA_HANDLE handle);
int wma_is_wow_mode_selected(WMA_HANDLE handle); bool wma_is_wow_mode_selected(WMA_HANDLE handle);
CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle); CDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle);
CDF_STATUS wma_enable_d0wow_in_fw(WMA_HANDLE handle); CDF_STATUS wma_enable_d0wow_in_fw(WMA_HANDLE handle);
bool wma_check_scan_in_progress(WMA_HANDLE handle); bool wma_check_scan_in_progress(WMA_HANDLE handle);

View File

@@ -981,7 +981,7 @@ static inline int wma_get_wow_bus_suspend(tp_wma_handle wma)
return cdf_atomic_read(&wma->is_wow_bus_suspended); return cdf_atomic_read(&wma->is_wow_bus_suspended);
} }
CDF_STATUS wma_resume_req(tp_wma_handle wma); CDF_STATUS wma_resume_req(tp_wma_handle wma, enum cdf_suspend_type type);
CDF_STATUS wma_wow_add_pattern(tp_wma_handle wma, CDF_STATUS wma_wow_add_pattern(tp_wma_handle wma,
struct wow_add_pattern *ptrn); struct wow_add_pattern *ptrn);
@@ -993,7 +993,9 @@ CDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info);
CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info); CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info);
CDF_STATUS wma_suspend_req(tp_wma_handle wma); CDF_STATUS wma_suspend_req(tp_wma_handle wma, enum cdf_suspend_type type);
void wma_calculate_and_update_conn_state(tp_wma_handle wma);
void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask);
void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask); void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask);
void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg); void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg);

View File

@@ -262,6 +262,9 @@
#define WMA_WLAN_RESUME_REQ SIR_HAL_WLAN_RESUME_REQ #define WMA_WLAN_RESUME_REQ SIR_HAL_WLAN_RESUME_REQ
#define WMA_MSG_TYPES_END SIR_HAL_MSG_TYPES_END #define WMA_MSG_TYPES_END SIR_HAL_MSG_TYPES_END
#define WMA_RUNTIME_PM_SUSPEND_IND SIR_HAL_RUNTIME_PM_SUSPEND_IND
#define WMA_RUNTIME_PM_RESUME_IND SIR_HAL_RUNTIME_PM_RESUME_IND
#ifdef WLAN_FEATURE_VOWIFI_11R #ifdef WLAN_FEATURE_VOWIFI_11R
#define WMA_AGGR_QOS_REQ SIR_HAL_AGGR_QOS_REQ #define WMA_AGGR_QOS_REQ SIR_HAL_AGGR_QOS_REQ
#define WMA_AGGR_QOS_RSP SIR_HAL_AGGR_QOS_RSP #define WMA_AGGR_QOS_RSP SIR_HAL_AGGR_QOS_RSP

View File

@@ -3632,17 +3632,20 @@ error:
/** /**
* wma_resume_req() - clear configured wow patterns in fw * wma_resume_req() - clear configured wow patterns in fw
* @wma: wma handle * @wma: wma handle
* @type: type of suspend
* *
* Return: CDF status * Return: CDF status
*/ */
CDF_STATUS wma_resume_req(tp_wma_handle wma) CDF_STATUS wma_resume_req(tp_wma_handle wma, enum cdf_suspend_type type)
{ {
wma->no_of_resume_ind++; if (type == CDF_SYSTEM_SUSPEND) {
wma->no_of_resume_ind++;
if (wma->no_of_resume_ind < wma_get_vdev_count(wma)) if (wma->no_of_resume_ind < wma_get_vdev_count(wma))
return CDF_STATUS_SUCCESS; return CDF_STATUS_SUCCESS;
wma->no_of_resume_ind = 0; wma->no_of_resume_ind = 0;
}
/* Reset the DTIM Parameters */ /* Reset the DTIM Parameters */
wma_set_resume_dtim(wma); wma_set_resume_dtim(wma);
@@ -3887,6 +3890,23 @@ CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info)
return CDF_STATUS_SUCCESS; return CDF_STATUS_SUCCESS;
} }
/**
* wma_calculate_and_update_conn_state(): calculate each interfaces conn state
* @wma: validated wma handle
*
* Identifies any vdev that is up and not in ap mode as connected.
* stores this in the interfaces conn_state varible.
*/
void wma_calculate_and_update_conn_state(tp_wma_handle wma)
{
int i;
for (i = 0; i < wma->max_bssid; i++) {
wma->interfaces[i].conn_state =
!!(wma->interfaces[i].vdev_up &&
!wma_is_vdev_in_ap_mode(wma, i));
}
}
/** /**
* wma_update_conn_state(): synchronize wma & hdd * wma_update_conn_state(): synchronize wma & hdd
* @wma: wma handle * @wma: wma handle
@@ -4131,14 +4151,26 @@ void wma_apply_lphb(tp_wma_handle wma)
void wma_apply_lphb(tp_wma_handle wma) {} void wma_apply_lphb(tp_wma_handle wma) {}
#endif /* FEATURE_WLAN_LPHB */ #endif /* FEATURE_WLAN_LPHB */
static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
enum cdf_suspend_type type)
{
if (type == CDF_SYSTEM_SUSPEND)
wma_send_status_to_suspend_ind(wma, true);
else if (type == CDF_RUNTIME_SUSPEND)
cdf_event_set(&wma->runtime_suspend);
}
/** /**
* wma_suspend_req() - Handles suspend indication request received from umac. * wma_suspend_req() - Handles suspend indication request received from umac.
* @wma: wma handle * @wma: wma handle
* @info: suspend params * @type: type of suspend
*
* The type controlls how we notify the indicator that the indication has
* been processed
* *
* Return: CDF status * Return: CDF status
*/ */
CDF_STATUS wma_suspend_req(tp_wma_handle wma) CDF_STATUS wma_suspend_req(tp_wma_handle wma, enum cdf_suspend_type type)
{ {
if (wma_is_wow_applicable(wma)) { if (wma_is_wow_applicable(wma)) {
WMA_LOGE("WOW Suspend"); WMA_LOGE("WOW Suspend");
@@ -4152,7 +4184,8 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma)
/* Set the Suspend DTIM Parameters */ /* Set the Suspend DTIM Parameters */
wma_set_suspend_dtim(wma); wma_set_suspend_dtim(wma);
wma_send_status_to_suspend_ind(wma, true);
wma_notify_suspend_req_procesed(wma, type);
/* to handle race between hif_pci_suspend and /* to handle race between hif_pci_suspend and
* unpause/pause tx handler * unpause/pause tx handler
@@ -4333,7 +4366,7 @@ bool static wma_is_nan_enabled(tp_wma_handle wma)
* *
* Return: true is wow mode is needed else false * Return: true is wow mode is needed else false
*/ */
int wma_is_wow_mode_selected(WMA_HANDLE handle) bool wma_is_wow_mode_selected(WMA_HANDLE handle)
{ {
tp_wma_handle wma = (tp_wma_handle) handle; tp_wma_handle wma = (tp_wma_handle) handle;
@@ -6255,6 +6288,118 @@ void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
return; return;
} }
/**
* wma_post_runtime_resume_msg() - post the resume request
* @handle: validated wma handle
*
* request the MC thread unpaus the vdev and set resume dtim
*
* Return: cdf status of the mq post
*/
static CDF_STATUS wma_post_runtime_resume_msg(WMA_HANDLE handle)
{
cds_msg_t resume_msg;
resume_msg.bodyptr = NULL;
resume_msg.type = WMA_RUNTIME_PM_RESUME_IND;
return cds_mq_post_message(CDF_MODULE_ID_WMA, &resume_msg);
}
/**
* wma_post_runtime_suspend_msg() - post the suspend request
* @handle: validated wma handle
*
* Requests for offloads to be configured for runtime suspend
* on the MC thread
*
* Return CDF_STATUS_E_AGAIN in case of timeout or CDF_STATUS_SUCCESS
*/
static CDF_STATUS wma_post_runtime_suspend_msg(WMA_HANDLE handle)
{
cds_msg_t cds_msg;
CDF_STATUS cdf_status;
tp_wma_handle wma = (tp_wma_handle) handle;
cdf_event_reset(&wma->runtime_suspend);
cds_msg.bodyptr = NULL;
cds_msg.type = WMA_RUNTIME_PM_SUSPEND_IND;
cdf_status = cds_mq_post_message(CDF_MODULE_ID_WMA, &cds_msg);
if (cdf_status != CDF_STATUS_SUCCESS)
goto failure;
if (cdf_wait_single_event(&wma->runtime_suspend,
WMA_TGT_SUSPEND_COMPLETE_TIMEOUT) !=
CDF_STATUS_SUCCESS) {
WMA_LOGE("Failed to get runtime suspend event");
goto failure;
}
return CDF_STATUS_SUCCESS;
failure:
return CDF_STATUS_E_AGAIN;
}
/**
* __wma_bus_suspend(): handles bus suspend for wma
* @type: is this suspend part of runtime suspend or system suspend?
*
* Bails if a scan is in progress.
* Calls the appropriate handlers based on configuration and event.
*
* Return: 0 for success or error code
*/
static int __wma_bus_suspend(enum cdf_suspend_type type)
{
WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
if (NULL == handle) {
WMA_LOGE("%s: wma context is NULL", __func__);
return -EFAULT;
}
if (wma_check_scan_in_progress(handle)) {
WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__);
return -EBUSY;
}
if (type == CDF_RUNTIME_SUSPEND) {
CDF_STATUS status = wma_post_runtime_suspend_msg(handle);
if (status)
return cdf_status_to_os_return(status);
}
if (type == CDF_SYSTEM_SUSPEND)
WMA_LOGE("%s: wow mode selected %d", __func__,
wma_is_wow_mode_selected(handle));
if (wma_is_wow_mode_selected(handle)) {
CDF_STATUS status = wma_enable_wow_in_fw(handle);
return cdf_status_to_os_return(status);
}
return wma_suspend_target(handle, 0);
}
/**
* wma_runtime_suspend() - handles runtime suspend request from hdd
*
* Calls the appropriate handler based on configuration and event.
* Last busy marking should prevent race conditions between processing
* of asyncronous fw events and the running of runtime suspend.
* (eg. last busy marking should guarantee that any auth requests have
* been processed)
* Events comming from the host are not protected, but aren't expected
* to be an issue.
*
* Return: 0 for success or error code
*/
int wma_runtime_suspend(void)
{
return __wma_bus_suspend(CDF_RUNTIME_SUSPEND);
}
/** /**
* wma_bus_suspend() - handles bus suspend request from hdd * wma_bus_suspend() - handles bus suspend request from hdd
* *
@@ -6264,24 +6409,52 @@ void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G,
*/ */
int wma_bus_suspend(void) int wma_bus_suspend(void)
{ {
return __wma_bus_suspend(CDF_RUNTIME_SUSPEND);
}
/**
* __wma_bus_resume() - bus resume for wma
*
* does the part of the bus resume common to bus and system suspend
*
* Return: os error code.
*/
int __wma_bus_resume(WMA_HANDLE handle)
{
bool wow_mode = wma_is_wow_mode_selected(handle);
CDF_STATUS status;
WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
if (!wow_mode)
return wma_resume_target(handle);
status = wma_disable_wow_in_fw(handle);
return cdf_status_to_os_return(status);
}
/**
* wma_runtime_resume() - do the runtime resume operation for wma
*
* Return: os error code.
*/
int wma_runtime_resume(void)
{
int ret;
CDF_STATUS status;
WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA); WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
if (NULL == handle) { if (NULL == handle) {
WMA_LOGE("%s: wma context is NULL", __func__); WMA_LOGE("%s: wma context is NULL", __func__);
return -EFAULT; return -EFAULT;
} }
WMA_LOGE("%s: wow mode selected %d", __func__, ret = __wma_bus_resume(handle);
wma_is_wow_mode_selected(handle)); if (ret)
return ret;
if (wma_check_scan_in_progress(handle)) { status = wma_post_runtime_resume_msg(handle);
WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__); return cdf_status_to_os_return(status);
return -EBUSY;
}
if (wma_is_wow_mode_selected(handle))
return cdf_status_to_os_return(wma_enable_wow_in_fw(handle));
return wma_suspend_target(handle, 0);
} }
/** /**
@@ -6295,19 +6468,12 @@ int wma_bus_suspend(void)
int wma_bus_resume(void) int wma_bus_resume(void)
{ {
WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA); WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA);
int wow_mode;
if (NULL == handle) { if (NULL == handle) {
WMA_LOGE("%s: wma context is NULL", __func__); WMA_LOGE("%s: wma context is NULL", __func__);
return -EFAULT; return -EFAULT;
} }
wow_mode = wma_is_wow_mode_selected(handle); return __wma_bus_resume(handle);
WMA_LOGE("%s: wow mode %d", __func__, wow_mode);
if (!wow_mode)
return wma_resume_target(handle);
return cdf_status_to_os_return(wma_disable_wow_in_fw(handle));
} }
/** /**

View File

@@ -1766,6 +1766,13 @@ CDF_STATUS wma_open(void *cds_context,
goto err_event_init; goto err_event_init;
} }
cdf_status = cdf_event_init(&wma_handle->runtime_suspend);
if (cdf_status != CDF_STATUS_SUCCESS) {
WMA_LOGP("%s: runtime_suspend event initialization failed",
__func__);
goto err_event_init;
}
cdf_status = cdf_event_init(&wma_handle->recovery_event); cdf_status = cdf_event_init(&wma_handle->recovery_event);
if (cdf_status != CDF_STATUS_SUCCESS) { if (cdf_status != CDF_STATUS_SUCCESS) {
WMA_LOGP("%s: recovery event initialization failed", __func__); WMA_LOGP("%s: recovery event initialization failed", __func__);
@@ -3083,6 +3090,7 @@ CDF_STATUS wma_close(void *cds_ctx)
cdf_event_destroy(&wma_handle->target_suspend); cdf_event_destroy(&wma_handle->target_suspend);
cdf_event_destroy(&wma_handle->wma_resume_event); cdf_event_destroy(&wma_handle->wma_resume_event);
cdf_event_destroy(&wma_handle->runtime_suspend);
cdf_event_destroy(&wma_handle->recovery_event); cdf_event_destroy(&wma_handle->recovery_event);
wma_cleanup_vdev_resp(wma_handle); wma_cleanup_vdev_resp(wma_handle);
wma_cleanup_hold_req(wma_handle); wma_cleanup_hold_req(wma_handle);
@@ -4874,9 +4882,19 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg)
case WMA_WOWL_EXIT_REQ: case WMA_WOWL_EXIT_REQ:
wma_wow_exit(wma_handle, (tpSirHalWowlExitParams) msg->bodyptr); wma_wow_exit(wma_handle, (tpSirHalWowlExitParams) msg->bodyptr);
break; break;
case WMA_RUNTIME_PM_SUSPEND_IND:
wma_calculate_and_update_conn_state(wma_handle);
wma_suspend_req(wma_handle, CDF_RUNTIME_SUSPEND);
break;
case WMA_RUNTIME_PM_RESUME_IND:
wma_resume_req(wma_handle, CDF_RUNTIME_SUSPEND);
break;
case WMA_WLAN_SUSPEND_IND: case WMA_WLAN_SUSPEND_IND:
wma_update_conn_state(wma_handle, msg->bodyval); wma_update_conn_state(wma_handle, msg->bodyval);
wma_suspend_req(wma_handle); wma_suspend_req(wma_handle, CDF_SYSTEM_SUSPEND);
break; break;
case WMA_8023_MULTICAST_LIST_REQ: case WMA_8023_MULTICAST_LIST_REQ:
wma_process_mcbc_set_filter_req(wma_handle, wma_process_mcbc_set_filter_req(wma_handle,
@@ -5015,7 +5033,7 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg)
cdf_mem_free(msg->bodyptr); cdf_mem_free(msg->bodyptr);
break; break;
case WMA_WLAN_RESUME_REQ: case WMA_WLAN_RESUME_REQ:
wma_resume_req(wma_handle); wma_resume_req(wma_handle, CDF_SYSTEM_SUSPEND);
break; break;
#ifdef WLAN_FEATURE_STATS_EXT #ifdef WLAN_FEATURE_STATS_EXT