From 0c83a5b04c5c79f7006ec30268551b3058a5ac3c Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Tue, 10 Nov 2015 16:52:05 -0800 Subject: [PATCH] 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 --- core/mac/src/include/sir_params.h | 6 +- core/wma/inc/wma.h | 1 + core/wma/inc/wma_api.h | 6 +- core/wma/inc/wma_internal.h | 6 +- core/wma/inc/wma_types.h | 3 + core/wma/src/wma_features.c | 222 ++++++++++++++++++++++++++---- core/wma/src/wma_main.c | 22 ++- 7 files changed, 231 insertions(+), 35 deletions(-) diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 6a4a485a19..ff6f339154 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -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. * @@ -580,6 +580,10 @@ typedef struct sSirMbMsgP2p { #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_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_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 316) #define SIR_HAL_RESET_PASSPOINT_LIST_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 317) diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 03486b165a..bf14268e7a 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1197,6 +1197,7 @@ typedef struct { cdf_event_t wma_ready_event; cdf_event_t wma_resume_event; cdf_event_t target_suspend; + cdf_event_t runtime_suspend; cdf_event_t recovery_event; uint16_t max_station; uint16_t max_bssid; diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index f04500e45e..a0d73deec6 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -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. * @@ -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, uint8_t *pVersion, uint32_t versionBufferSize); +int wma_runtime_suspend(void); +int wma_runtime_resume(void); int wma_bus_suspend(void); int wma_suspend_target(WMA_HANDLE handle, int disable_target_intr); void wma_target_suspend_acknowledge(void *context); @@ -124,7 +126,7 @@ int wma_bus_resume(void); int wma_resume_target(WMA_HANDLE handle); CDF_STATUS wma_disable_wow_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_d0wow_in_fw(WMA_HANDLE handle); bool wma_check_scan_in_progress(WMA_HANDLE handle); diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 8ef008c795..ea192525f6 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -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); } -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, 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_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_del_ts_req(tp_wma_handle wma, tDelTsParams *msg); diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 0a6428a6e3..9460d5f0fc 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -262,6 +262,9 @@ #define WMA_WLAN_RESUME_REQ SIR_HAL_WLAN_RESUME_REQ #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 #define WMA_AGGR_QOS_REQ SIR_HAL_AGGR_QOS_REQ #define WMA_AGGR_QOS_RSP SIR_HAL_AGGR_QOS_RSP diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 541b7eb3dc..c97fccc7dc 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3632,17 +3632,20 @@ error: /** * wma_resume_req() - clear configured wow patterns in fw * @wma: wma handle + * @type: type of suspend * * 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)) - return CDF_STATUS_SUCCESS; + if (wma->no_of_resume_ind < wma_get_vdev_count(wma)) + return CDF_STATUS_SUCCESS; - wma->no_of_resume_ind = 0; + wma->no_of_resume_ind = 0; + } /* Reset the DTIM Parameters */ wma_set_resume_dtim(wma); @@ -3887,6 +3890,23 @@ CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info) 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: wma handle @@ -4131,14 +4151,26 @@ void wma_apply_lphb(tp_wma_handle wma) void wma_apply_lphb(tp_wma_handle wma) {} #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: 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 */ -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)) { WMA_LOGE("WOW Suspend"); @@ -4152,7 +4184,8 @@ CDF_STATUS wma_suspend_req(tp_wma_handle wma) /* Set the Suspend DTIM Parameters */ 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 * 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 */ -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; @@ -6255,6 +6288,118 @@ void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G, 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 * @@ -6264,24 +6409,52 @@ void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G, */ 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); if (NULL == handle) { WMA_LOGE("%s: wma context is NULL", __func__); return -EFAULT; } - WMA_LOGE("%s: wow mode selected %d", __func__, - wma_is_wow_mode_selected(handle)); + ret = __wma_bus_resume(handle); + if (ret) + return ret; - if (wma_check_scan_in_progress(handle)) { - WMA_LOGE("%s: Scan in progress. Aborting suspend", __func__); - 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); + status = wma_post_runtime_resume_msg(handle); + return cdf_status_to_os_return(status); } /** @@ -6295,19 +6468,12 @@ int wma_bus_suspend(void) int wma_bus_resume(void) { WMA_HANDLE handle = cds_get_context(CDF_MODULE_ID_WMA); - int wow_mode; if (NULL == handle) { WMA_LOGE("%s: wma context is NULL", __func__); return -EFAULT; } - wow_mode = wma_is_wow_mode_selected(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)); + return __wma_bus_resume(handle); } /** diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 935db34862..815fbd9c96 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1766,6 +1766,13 @@ CDF_STATUS wma_open(void *cds_context, 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); if (cdf_status != CDF_STATUS_SUCCESS) { 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->wma_resume_event); + cdf_event_destroy(&wma_handle->runtime_suspend); cdf_event_destroy(&wma_handle->recovery_event); wma_cleanup_vdev_resp(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: wma_wow_exit(wma_handle, (tpSirHalWowlExitParams) msg->bodyptr); 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: wma_update_conn_state(wma_handle, msg->bodyval); - wma_suspend_req(wma_handle); + wma_suspend_req(wma_handle, CDF_SYSTEM_SUSPEND); break; case WMA_8023_MULTICAST_LIST_REQ: 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); break; case WMA_WLAN_RESUME_REQ: - wma_resume_req(wma_handle); + wma_resume_req(wma_handle, CDF_SYSTEM_SUSPEND); break; #ifdef WLAN_FEATURE_STATS_EXT