diff options
| author | Komal Seelam <kseelam@qti.qualcomm.com> | 2015-10-14 17:51:27 +0530 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2015-10-16 00:57:53 -0700 |
| commit | 6e0d3383b2e5c86c415fbb081b8d60e6e6a7ded5 (patch) | |
| tree | 0f2584f01085db130054c48498a8e2365e5e6401 | |
| parent | 01ae45b557e662b39fcdf41eed2bfc804ae5bd99 (diff) | |
qcacld-2.0: Prevent runtime suspend untill clean-up completes
When runtime suspend fails because of wma_suspend_req() not
completing in time, PM runtime workqueue posts resume request to
MC thread to clean-up. If MC thread is busy or slow in processing
resume request and after the timeout Runtime PM framework posts
another suspend request then there may be race condition between
MC thread processing resume request (Or even suspend request) and
Runtime PM workqueue posting subsequent suspend request.
Synchronize subsequent suspend request by not allowing the
runtime suspend till resume requests completes in MC thread
context.
Change-Id: Ie9aaf72fbced41f8d23640b9032a3c2236dc6826
CRs-fixed: 921373
| -rw-r--r-- | CORE/SERVICES/WMA/wma.c | 79 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.h | 8 | ||||
| -rw-r--r-- | CORE/SERVICES/WMI/wmi_unified.c | 4 |
3 files changed, 75 insertions, 16 deletions
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c index 6253becad59b..864316efc293 100644 --- a/CORE/SERVICES/WMA/wma.c +++ b/CORE/SERVICES/WMA/wma.c @@ -6331,6 +6331,54 @@ static void wma_set_nan_enable(tp_wma_handle wma_handle, } #endif +#ifdef FEATURE_RUNTIME_PM +/** + * wma_runtime_context_init() - API to init wma runtime contexts + * @handle: wma handle + * + * The API initializes the wma runtime contexts for beaconing interfaces + * and the context to synchronize runtime suspend/resume. + * + * Return: void + */ +static void wma_runtime_context_init(tp_wma_handle handle) +{ + tp_wma_handle wma_handle = handle; + struct wma_runtime_pm_context *runtime_context = + &wma_handle->runtime_context; + + runtime_context->ap = + vos_runtime_pm_prevent_suspend_init("wma_runtime_ap"); + runtime_context->resume = + vos_runtime_pm_prevent_suspend_init("wma_runtime_resume"); +} + +/** + * wma_runtime_context_deinit() - API to deinit wma runtime contexts + * @handle: wma handle + * + * The API deinitializes the wma runtime contexts for beaconing interfaces + * and the context to synchronize runtime suspend/resume. + * + * Return: void + */ +static void wma_runtime_context_deinit(tp_wma_handle handle) +{ + tp_wma_handle wma_handle = handle; + struct wma_runtime_pm_context *runtime_context = + &wma_handle->runtime_context; + + vos_runtime_pm_prevent_suspend_deinit(runtime_context->ap); + runtime_context->ap = NULL; + vos_runtime_pm_prevent_suspend_deinit( + runtime_context->resume); + runtime_context->resume = NULL; +} +#else +static void wma_runtime_context_init(tp_wma_handle handle) { } +static void wma_runtime_context_deinit(tp_wma_handle handle) { } +#endif + /* * Allocate and init wmi adaptation layer. */ @@ -6396,8 +6444,8 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx, wma_handle->htc_handle = htc_handle; wma_handle->vos_context = vos_context; wma_handle->adf_dev = adf_dev; - wma_handle->runtime_pm_ctx = - vos_runtime_pm_prevent_suspend_init("wma_runtime_pm"); + + wma_runtime_context_init(wma_handle); /* initialize default target config */ wma_set_default_tgt_config(wma_handle); @@ -6760,8 +6808,7 @@ err_wma_handle: vos_wake_lock_destroy(&wma_handle->wow_wake_lock); } - vos_runtime_pm_prevent_suspend_deinit(wma_handle->runtime_pm_ctx); - wma_handle->runtime_pm_ctx = NULL; + wma_runtime_context_deinit(wma_handle); vos_free_context(vos_context, VOS_MODULE_ID_WDA, wma_handle); WMA_LOGD("%s: Exit", __func__); @@ -15724,7 +15771,7 @@ out: static void wma_add_pm_vote(tp_wma_handle wma) { if (++wma->ap_client_cnt == 1) { - vos_runtime_pm_prevent_suspend(wma->runtime_pm_ctx); + vos_runtime_pm_prevent_suspend(wma->runtime_context.ap); vos_pm_control(DISABLE_PCIE_POWER_COLLAPSE); } } @@ -15732,7 +15779,7 @@ static void wma_add_pm_vote(tp_wma_handle wma) static void wma_del_pm_vote(tp_wma_handle wma) { if (--wma->ap_client_cnt == 0) { - vos_runtime_pm_allow_suspend(wma->runtime_pm_ctx); + vos_runtime_pm_allow_suspend(wma->runtime_context.ap); vos_pm_control(ENABLE_PCIE_POWER_COLLAPSE); } } @@ -20721,6 +20768,9 @@ pdev_resume: /* unpause the vdev if left paused and hif_pci_suspend fails */ wma_unpause_vdev(wma); + if (runtime_pm) + vos_runtime_pm_allow_suspend(wma->runtime_context.resume); + return ret; } @@ -21056,6 +21106,7 @@ static VOS_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) if (info == NULL) { WMA_LOGD("runtime PM: Request to suspend all interfaces"); + wmi_set_runtime_pm_inprogress(wma->wmi_handle, TRUE); goto suspend_all_iface; } @@ -21214,7 +21265,6 @@ send_ready_to_suspend: wma_send_status_to_suspend_ind(wma, TRUE, info == NULL); - return VOS_STATUS_SUCCESS; } @@ -29371,8 +29421,7 @@ VOS_STATUS wma_close(v_VOID_t *vos_ctx) vos_wake_lock_destroy(&wma_handle->wow_wake_lock); } - vos_runtime_pm_prevent_suspend_deinit(wma_handle->runtime_pm_ctx); - wma_handle->runtime_pm_ctx = NULL; + wma_runtime_context_deinit(wma_handle); /* unregister Firmware debug log */ vos_status = dbglog_deinit(wma_handle->wmi_handle); @@ -32688,7 +32737,6 @@ int wma_runtime_suspend_req(WMA_HANDLE handle) int ret = 0; tp_wma_handle wma = (tp_wma_handle) handle; - wmi_set_runtime_pm_inprogress(wma->wmi_handle, TRUE); vos_event_reset(&wma->runtime_suspend); vosMessage.bodyptr = NULL; @@ -32697,7 +32745,7 @@ int wma_runtime_suspend_req(WMA_HANDLE handle) if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { ret = -EAGAIN; - goto out; + return ret; } if (vos_wait_single_event(&wma->runtime_suspend, @@ -32705,7 +32753,6 @@ int wma_runtime_suspend_req(WMA_HANDLE handle) VOS_STATUS_SUCCESS) { WMA_LOGE("Failed to get runtime suspend event"); ret = -EAGAIN; - wma_runtime_resume_req(wma); goto out; } @@ -32717,7 +32764,8 @@ int wma_runtime_suspend_req(WMA_HANDLE handle) } out: if (ret) - wmi_set_runtime_pm_inprogress(wma->wmi_handle, FALSE); + wma_runtime_resume_req(wma); + return ret; } @@ -32726,6 +32774,10 @@ int wma_runtime_resume_req(WMA_HANDLE handle) vos_msg_t vosMessage; VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; int ret = 0; + tp_wma_handle wma = (tp_wma_handle) handle; + struct wma_runtime_pm_context *runtime_context = &wma->runtime_context; + + vos_runtime_pm_prevent_suspend(runtime_context->resume); vosMessage.bodyptr = NULL; vosMessage.type = WDA_RUNTIME_PM_RESUME_IND; @@ -32734,6 +32786,7 @@ int wma_runtime_resume_req(WMA_HANDLE handle) if (!VOS_IS_STATUS_SUCCESS(vosStatus)) { WMA_LOGE("Failed to post Runtime PM Resume IND to VOS"); ret = -EAGAIN; + vos_runtime_pm_allow_suspend(runtime_context->resume); } return ret; diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h index 19675bb3135f..93a95d1bb0c2 100644 --- a/CORE/SERVICES/WMA/wma.h +++ b/CORE/SERVICES/WMA/wma.h @@ -619,12 +619,16 @@ typedef struct request_handler_entry { wma_request_handler handler; } request_handler_entry_t; +struct wma_runtime_pm_context { + void *ap; + void *resume; +}; + typedef struct wma_handle { void *wmi_handle; void *htc_handle; void *vos_context; void *mac_context; - void *runtime_pm_ctx; vos_event_t wma_ready_event; vos_event_t wma_resume_event; @@ -830,6 +834,8 @@ typedef struct wma_handle { uint32_t wow_wakeup_enable_mask; uint32_t wow_wakeup_disable_mask; uint16_t max_mgmt_tx_fail_count; + + struct wma_runtime_pm_context runtime_context; }t_wma_handle, *tp_wma_handle; struct wma_target_cap { diff --git a/CORE/SERVICES/WMI/wmi_unified.c b/CORE/SERVICES/WMI/wmi_unified.c index 68c7d2c5e062..d6e1e55a9a4d 100644 --- a/CORE/SERVICES/WMI/wmi_unified.c +++ b/CORE/SERVICES/WMI/wmi_unified.c @@ -676,8 +676,8 @@ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len, if (adf_os_atomic_read(&wmi_handle->is_target_suspended) && ( (WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID != cmd_id) && (WMI_PDEV_RESUME_CMDID != cmd_id)) ) { - pr_err("%s: Target is suspended could not send WMI command\n", - __func__); + pr_err("%s: Target is suspended could not send WMI command: %d\n", + __func__, cmd_id); VOS_ASSERT(0); return -EBUSY; } else |
