summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDustin Brown <dustinb@codeaurora.org>2017-03-03 11:41:05 -0800
committerqcabuildsw <qcabuildsw@localhost>2017-03-03 14:46:21 -0800
commitd0a6b9932087939f82a3ceed24822e9e82be9c46 (patch)
treeb6144852d5fa0886857b01a5a7a4a5022b7132ff
parent498d2326bb093981566387d83b0713e9a2d2e9aa (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.h32
-rw-r--r--core/wma/src/wma_data.c2
-rw-r--r--core/wma/src/wma_dev_if.c8
-rw-r--r--core/wma/src/wma_mgmt.c2
-rw-r--r--core/wma/src/wma_utils.c28
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;
+}