diff options
| author | Dustin Brown <dustinb@codeaurora.org> | 2017-03-03 11:41:05 -0800 |
|---|---|---|
| committer | qcabuildsw <qcabuildsw@localhost> | 2017-03-03 14:46:21 -0800 |
| commit | d0a6b9932087939f82a3ceed24822e9e82be9c46 (patch) | |
| tree | b6144852d5fa0886857b01a5a7a4a5022b7132ff | |
| parent | 498d2326bb093981566387d83b0713e9a2d2e9aa (diff) | |
qcacld-3.0: Acquire wakelock before sending VDEV_STOP
The host driver should not attempt to power collapse while pending
VDEV_STOP commands are in flight. Acquire a wakelock before sending a
VDEV_STOP request to firmware, and release it upon receipt of VDEV_STOP
response.
Change-Id: Iac90fc249e9571090df6948ed931cc07b67e938d
CRs-Fixed: 2014496
| -rw-r--r-- | core/wma/inc/wma_internal.h | 32 | ||||
| -rw-r--r-- | core/wma/src/wma_data.c | 2 | ||||
| -rw-r--r-- | core/wma/src/wma_dev_if.c | 8 | ||||
| -rw-r--r-- | core/wma/src/wma_mgmt.c | 2 | ||||
| -rw-r--r-- | core/wma/src/wma_utils.c | 28 |
5 files changed, 69 insertions, 3 deletions
diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index b9679928671e..381338f822a2 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1300,4 +1300,36 @@ static inline void wma_sta_kickout_event(uint32_t kickout_reason, }; #endif /* FEATURE_WLAN_DIAG_SUPPORT */ +/** + * wma_acquire_wmi_resp_wakelock() - acquire the WMI response wakelock + * @wma: the WMA handle containing the wakelock to acquire + * @msec: the wakelock duration in milliseconds + * + * Return: void + */ +void wma_acquire_wmi_resp_wakelock(t_wma_handle *wma, uint32_t msec); + +/** + * wma_release_wmi_resp_wakelock() - release the WMI response wakelock + * @wma: the WMA handle containing the wakelock to release + * + * Return: void + */ +void wma_release_wmi_resp_wakelock(t_wma_handle *wma); + +/** + * wma_send_vdev_stop_to_fw() - send the vdev stop command to firmware + * @wma: the WMA handle containing a reference to the wmi_handle to use + * @vdev_id: the VDEV Id of the VDEV to stop + * + * This is a helper function that acquires the WMI response wakelock before + * sending down the VDEV_STOP command to firmware. This wakelock is + * automatically released on failure. Consumers should call + * wma_release_wmi_resp_wakelock() upon receipt of the VDEV_STOP response from + * firmware, to avoid power penalties. + * + * Return: QDF_STATUS + */ +QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id); + #endif diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 8f5af679dd22..ffbe1e298431 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -1232,7 +1232,7 @@ void wma_set_linkstate(tp_wma_handle wma, tpLinkStateParams params) params->status = false; status = QDF_STATUS_E_NOMEM; } - if (wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id)) { + if (wma_send_vdev_stop_to_fw(wma, vdev_id)) { WMA_LOGP("%s: %d Failed to send vdev stop vdev %d", __func__, __LINE__, vdev_id); params->status = false; diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 5169cfb2e1ac..6f92aed04deb 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -1509,6 +1509,7 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, return -EINVAL; } + wma_release_wmi_resp_wakelock(wma); wma_hidden_ssid_vdev_restart_on_vdev_stop(wma, resp_event->vdev_id); } @@ -1534,6 +1535,9 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, tpDeleteBssParams params = (tpDeleteBssParams) req_msg->user_data; struct beacon_info *bcn; + + wma_release_wmi_resp_wakelock(wma); + if (resp_event->vdev_id > wma->max_bssid) { WMA_LOGE("%s: Invalid vdev_id %d", __func__, resp_event->vdev_id); @@ -1635,6 +1639,8 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info, tpLinkStateParams params = (tpLinkStateParams) req_msg->user_data; + wma_release_wmi_resp_wakelock(wma); + peer = ol_txrx_find_peer_by_addr(pdev, params->bssid, &peer_id); if (peer) { WMA_LOGP(FL("Deleting peer %pM vdev id %d"), @@ -4760,7 +4766,7 @@ void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params) OL_TXQ_PAUSE_REASON_VDEV_STOP); iface->pause_bitmap |= (1 << PAUSE_TYPE_HOST); - if (wmi_unified_vdev_stop_send(wma->wmi_handle, params->smesessionId)) { + if (wma_send_vdev_stop_to_fw(wma, params->smesessionId)) { WMA_LOGP("%s: %d Failed to send vdev stop", __func__, __LINE__); wma_remove_vdev_req(wma, params->smesessionId, WMA_TARGET_REQ_TYPE_VDEV_STOP); diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index 706a6d9f8958..abcd52f50acb 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -2931,7 +2931,7 @@ void wma_hidden_ssid_vdev_restart(tp_wma_handle wma_handle, OL_TXQ_PAUSE_REASON_VDEV_STOP); wma_handle->interfaces[pReq->sessionId].pause_bitmap |= (1 << PAUSE_TYPE_HOST); - if (wmi_unified_vdev_stop_send(wma_handle->wmi_handle, pReq->sessionId)) { + if (wma_send_vdev_stop_to_fw(wma_handle, pReq->sessionId)) { WMA_LOGE("%s: %d Failed to send vdev stop", __func__, __LINE__); qdf_atomic_set(&intr[pReq->sessionId].vdev_restart_params. hidden_ssid_restart_in_progress, 0); diff --git a/core/wma/src/wma_utils.c b/core/wma/src/wma_utils.c index 6769c3e249fd..ad11465b398d 100644 --- a/core/wma/src/wma_utils.c +++ b/core/wma/src/wma_utils.c @@ -4218,3 +4218,31 @@ void wma_peer_debug_dump(void) dbg_rec->arg2); } while (i != current_index); } + +void wma_acquire_wmi_resp_wakelock(t_wma_handle *wma, uint32_t msec) +{ + cds_host_diag_log_work(&wma->wmi_cmd_rsp_wake_lock, + msec, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + qdf_wake_lock_timeout_acquire(&wma->wmi_cmd_rsp_wake_lock, msec); + qdf_runtime_pm_prevent_suspend(&wma->wmi_cmd_rsp_runtime_lock); +} + +void wma_release_wmi_resp_wakelock(t_wma_handle *wma) +{ + qdf_wake_lock_release(&wma->wmi_cmd_rsp_wake_lock, + WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP); + qdf_runtime_pm_allow_suspend(&wma->wmi_cmd_rsp_runtime_lock); +} + +QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id) +{ + QDF_STATUS status; + + wma_acquire_wmi_resp_wakelock(wma, WMA_VDEV_STOP_REQUEST_TIMEOUT); + status = wmi_unified_vdev_stop_send(wma->wmi_handle, vdev_id); + if (QDF_IS_STATUS_ERROR(status)) + wma_release_wmi_resp_wakelock(wma); + + return status; +} |
