Browse Source

qcacld-3.0: Release vdev start wakelock after vdev up/down

Currently, a wakelock is acquired before vdev start is sent to firmware
and released after a vdev stop response is received. In some cases, this
can cause a race condition where the device will power collapse before
the association process is complete. Instead, release the wakelock after
either vdev up or vdev down is sent to firmware, ensuring the entire
association process is protected.

Change-Id: Iab1a241f1c5810d9f71bfd86e1e8036847ebf602
CRs-Fixed: 2082928
Dustin Brown 7 years ago
parent
commit
ec2c92eb37

+ 4 - 0
core/wma/inc/wma.h

@@ -1006,6 +1006,8 @@ typedef struct {
  * @wow_stats: stat counters for WoW related events
  * It stores parameters per vdev in wma.
  * @in_bmps : Whether bmps for this interface has been enabled
+ * @vdev_start_wakelock: wakelock to protect vdev start op with firmware
+ * @vdev_stop_wakelock: wakelock to protect vdev stop op with firmware
  */
 struct wma_txrx_node {
 	uint8_t addr[IEEE80211_ADDR_LEN];
@@ -1086,6 +1088,8 @@ struct wma_txrx_node {
 	bool in_bmps;
 	struct beacon_filter_param beacon_filter;
 	bool beacon_filter_enabled;
+	qdf_wake_lock_t vdev_start_wakelock;
+	qdf_wake_lock_t vdev_stop_wakelock;
 };
 
 #if defined(QCA_WIFI_FTM)

+ 46 - 22
core/wma/inc/wma_internal.h

@@ -1200,32 +1200,34 @@ 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
+ * wma_acquire_wakelock() - acquire the given wakelock
+ * @wl: the wakelock to acquire
  * @msec: the wakelock duration in milliseconds
  *
- * Return: void
+ * This also acquires the wma runtime pm lock.
+ *
+ * Return: None
  */
-void wma_acquire_wmi_resp_wakelock(t_wma_handle *wma, uint32_t msec);
+void wma_acquire_wakelock(qdf_wake_lock_t *wl, uint32_t msec);
 
 /**
- * wma_release_wmi_resp_wakelock() - release the WMI response wakelock
- * @wma: the WMA handle containing the wakelock to release
+ * wma_release_wakelock() - release the given wakelock
+ * @wl: the wakelock to release
+ *
+ * This also releases the wma runtime pm lock.
  *
- * Return: void
+ * Return: None
  */
-void wma_release_wmi_resp_wakelock(t_wma_handle *wma);
+void wma_release_wakelock(qdf_wake_lock_t *wl);
 
 /**
  * wma_send_vdev_start_to_fw() - send the vdev start command to firmware
- * @wma: the WMA handle containing a reference to the wmi_handle to use
- * @params: the VDEV_START params to send to firmware
+ * @wma: a reference to the global WMA handle
+ * @params: the vdev start params to send to firmware
  *
- * This is a helper function that acquires the WMI response wakelock before
- * sending down the VDEV_START command to firmware. This wakelock is
- * automatically released on failure. Consumers should call
- * wma_release_wmi_resp_wakelock() upon receipt of the VDEV_START response from
- * firmware, to avoid power penalties.
+ * Consumers should call wma_release_wakelock() upon receipt of the vdev start
+ * response from firmware to avoid power penalties. Alternatively, calling the
+ * matching vdev_up or vdev_down APIs will also release this lock.
  *
  * Return: QDF_STATUS
  */
@@ -1234,19 +1236,41 @@ wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params);
 
 /**
  * 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
+ * @wma: a reference to the global WMA handle
+ * @vdev_id: the 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.
+ * Consumers should call wma_release_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);
 
+/**
+ * wma_send_vdev_up_to_fw() - send the vdev up command to firmware
+ * @wma: a reference to the global WMA handle
+ * @params: the vdev up params to send to firmware
+ * @bssid: the BssId to send to firmware
+ *
+ * This also releases the vdev start wakelock.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wma_send_vdev_up_to_fw(t_wma_handle *wma,
+				  struct vdev_up_params *params,
+				  uint8_t bssid[IEEE80211_ADDR_LEN]);
+
+/**
+ * wma_send_vdev_down_to_fw() - send the vdev down command to firmware
+ * @wma: a reference to the global WMA handle
+ * @vdev_id: the Id of the vdev to down
+ *
+ * This also releases the vdev start wakelock.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wma_send_vdev_down_to_fw(t_wma_handle *wma, uint8_t vdev_id);
+
 /*
  * wma_rx_aggr_failure_event_handler - event handler to handle rx aggr failure
  * @handle: the wma handle

+ 16 - 0
core/wma/inc/wma_types.h

@@ -715,6 +715,22 @@ QDF_STATUS wma_tx_packet(void *pWMA,
 QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, void *p_cds_context,
 		    wma_tgt_cfg_cb pTgtUpdCB, struct cds_config_info *cds_cfg);
 
+/**
+ * wma_vdev_init() - initialize a wma vdev
+ * @vdev: the vdev to initialize
+ *
+ * Return: None
+ */
+void wma_vdev_init(struct wma_txrx_node *vdev);
+
+/**
+ * wma_vdev_deinit() - de-initialize a wma vdev
+ * @vdev: the vdev to de-initialize
+ *
+ * Return: None
+ */
+void wma_vdev_deinit(struct wma_txrx_node *vdev);
+
 QDF_STATUS wma_register_mgmt_frm_client(void);
 
 QDF_STATUS wma_de_register_mgmt_frm_client(void);

+ 41 - 86
core/wma/src/wma_dev_if.c

@@ -478,7 +478,10 @@ static void wma_vdev_detach_callback(void *ctx)
 	if (iface->stats_rsp)
 		qdf_mem_free(iface->stats_rsp);
 
+	wma_vdev_deinit(iface);
 	qdf_mem_zero(iface, sizeof(*iface));
+	wma_vdev_init(iface);
+
 	param->status = QDF_STATUS_SUCCESS;
 	wma_send_del_sta_self_resp(param);
 }
@@ -596,15 +599,9 @@ static QDF_STATUS wma_handle_vdev_detach(tp_wma_handle wma_handle,
 
 	/* Acquire wake lock only when you expect a response from firmware */
 	if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
-				    WMI_SERVICE_SYNC_DELETE_CMDS)) {
-		cds_host_diag_log_work(&wma_handle->wmi_cmd_rsp_wake_lock,
-					 WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION,
-					 WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
-		qdf_wake_lock_timeout_acquire(
-					 &wma_handle->wmi_cmd_rsp_wake_lock,
-					 WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION);
-		qdf_runtime_pm_prevent_suspend(
-					wma_handle->wmi_cmd_rsp_runtime_lock);
+				   WMI_SERVICE_SYNC_DELETE_CMDS)) {
+		wma_acquire_wakelock(&wma_handle->wmi_cmd_rsp_wake_lock,
+				     WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION);
 	}
 	WMA_LOGD("Call txrx detach with callback for vdev %d", vdev_id);
 	cdp_vdev_detach(soc,
@@ -932,7 +929,6 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info,
 	tpAniSirGlobal mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
 
 	if (NULL == mac_ctx) {
-		wma_release_wmi_resp_wakelock(wma);
 		WMA_LOGE("%s: Failed to get mac_ctx", __func__);
 		policy_mgr_set_do_hw_mode_change_flag(
 			wma->psoc, false);
@@ -942,8 +938,6 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info,
 
 	WMA_LOGD("%s: Enter", __func__);
 
-	wma_release_wmi_resp_wakelock(wma);
-
 	param_buf = (WMI_VDEV_START_RESP_EVENTID_param_tlvs *) cmd_param_info;
 	if (!param_buf) {
 		WMA_LOGE("Invalid start response event buffer");
@@ -1086,9 +1080,8 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info,
 
 			param.vdev_id = resp_event->vdev_id;
 			param.assoc_id = iface->aid;
-			status = wmi_unified_vdev_up_send(wma->wmi_handle,
-						 iface->bssid,
-						 &param);
+			status = wma_send_vdev_up_to_fw(wma, &param,
+							iface->bssid);
 			if (QDF_IS_STATUS_ERROR(status)) {
 				WMA_LOGE("%s:vdev_up failed vdev_id %d",
 					 __func__, resp_event->vdev_id);
@@ -1115,9 +1108,8 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info,
 	} else if (req_msg->msg_type == WMA_OCB_SET_CONFIG_CMD) {
 		param.vdev_id = resp_event->vdev_id;
 		param.assoc_id = iface->aid;
-		if (wmi_unified_vdev_up_send(wma->wmi_handle,
-					     iface->bssid,
-					     &param) != QDF_STATUS_SUCCESS) {
+		if (wma_send_vdev_up_to_fw(wma, &param, iface->bssid) !=
+		    QDF_STATUS_SUCCESS) {
 			WMA_LOGE(FL("failed to send vdev up"));
 			policy_mgr_set_do_hw_mode_change_flag(
 				wma->psoc, false);
@@ -1689,16 +1681,12 @@ wma_send_del_bss_response(tp_wma_handle wma, struct wma_target_req *req,
 		req->user_data = NULL;
 		return;
 	}
-	params = (tpDeleteBssParams) req->user_data;
 
-	if (wmi_unified_vdev_down_send(wma->wmi_handle,
-	   vdev_id) !=
-	   QDF_STATUS_SUCCESS) {
-		WMA_LOGE("Failed to send vdev down cmd: vdev %d",
-			 vdev_id);
+	params = (tpDeleteBssParams)req->user_data;
+	if (wma_send_vdev_down_to_fw(wma, vdev_id) != QDF_STATUS_SUCCESS) {
+		WMA_LOGE("Failed to send vdev down cmd: vdev %d", vdev_id);
 	} else {
-		wma_vdev_set_mlme_state(wma, vdev_id,
-				WLAN_VDEV_S_STOP);
+		wma_vdev_set_mlme_state(wma, vdev_id, WLAN_VDEV_S_STOP);
 		wma_check_and_find_mcc_ap(wma, vdev_id);
 	}
 
@@ -1769,26 +1757,17 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info,
 	int32_t status = 0;
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
 
-#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
-	tpAniSirGlobal mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
-
-	if (NULL == mac_ctx) {
-		wma_release_wmi_resp_wakelock(wma);
-		WMA_LOGE("%s: Failed to get mac_ctx", __func__);
-		return -EINVAL;
-	}
-#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
-
 	WMA_LOGD("%s: Enter", __func__);
 
-	wma_release_wmi_resp_wakelock(wma);
-
 	param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *) cmd_param_info;
 	if (!param_buf) {
 		WMA_LOGE("Invalid event buffer");
 		return -EINVAL;
 	}
+
 	resp_event = param_buf->fixed_param;
+	iface = &wma->interfaces[resp_event->vdev_id];
+	wma_release_wakelock(&iface->vdev_stop_wakelock);
 
 	req_msg = wma_find_vdev_req(wma, resp_event->vdev_id,
 				    WMA_TARGET_REQ_TYPE_VDEV_STOP, true);
@@ -1843,7 +1822,6 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info,
 				 resp_event->vdev_id);
 		}
 
-		iface = &wma->interfaces[resp_event->vdev_id];
 		if (iface->handle == NULL) {
 			WMA_LOGE("%s vdev id %d is already deleted",
 				 __func__, resp_event->vdev_id);
@@ -1902,9 +1880,8 @@ int wma_vdev_stop_resp_handler(void *handle, uint8_t *cmd_param_info,
 				}
 			}
 		}
-		if (wmi_unified_vdev_down_send(wma->wmi_handle,
-					req_msg->vdev_id) !=
-					QDF_STATUS_SUCCESS) {
+		if (wma_send_vdev_down_to_fw(wma, req_msg->vdev_id) !=
+		    QDF_STATUS_SUCCESS) {
 			WMA_LOGE("Failed to send vdev down cmd: vdev %d",
 				req_msg->vdev_id);
 		}
@@ -2562,9 +2539,9 @@ int wma_vdev_delete_handler(void *handle, uint8_t *cmd_param_info,
 				event->vdev_id);
 		return -EINVAL;
 	}
-	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);
+
+	wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
+
 	/* Send response to upper layers */
 	wma_vdev_detach_callback(req_msg->user_data);
 	qdf_mc_timer_stop(&req_msg->event_timeout);
@@ -2615,10 +2592,9 @@ int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info,
 		return -EINVAL;
 	}
 
-	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);
-		/* Cleanup timeout handler */
+	wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
+
+	/* Cleanup timeout handler */
 	qdf_mc_timer_stop(&req_msg->event_timeout);
 	qdf_mc_timer_destroy(&req_msg->event_timeout);
 
@@ -2642,9 +2618,8 @@ int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info,
 	} else if (req_msg->type == WMA_SET_LINK_PEER_RSP) {
 		tpLinkStateParams params =
 			(tpLinkStateParams) req_msg->user_data;
-		if (wmi_unified_vdev_down_send(wma->wmi_handle,
-				req_msg->vdev_id) !=
-				QDF_STATUS_SUCCESS) {
+		if (wma_send_vdev_down_to_fw(wma, req_msg->vdev_id) !=
+		    QDF_STATUS_SUCCESS) {
 			WMA_LOGE("Failed to send vdev down cmd: vdev %d",
 					req_msg->vdev_id);
 		}
@@ -2976,8 +2951,8 @@ void wma_vdev_resp_timer(void *data)
 		   WMI_SERVICE_SYNC_DELETE_CMDS))
 			goto free_tgt_req;
 
-		if (wmi_unified_vdev_down_send(wma->wmi_handle,
-				tgt_req->vdev_id) != QDF_STATUS_SUCCESS) {
+		if (wma_send_vdev_down_to_fw(wma, tgt_req->vdev_id) !=
+		    QDF_STATUS_SUCCESS) {
 			WMA_LOGE("Failed to send vdev down cmd: vdev %d",
 				 tgt_req->vdev_id);
 		} else {
@@ -3026,11 +3001,8 @@ void wma_vdev_resp_timer(void *data)
 			(struct del_sta_self_params *) iface->del_staself_req;
 
 		if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap,
-			 WMI_SERVICE_SYNC_DELETE_CMDS)) {
-			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);
+					   WMI_SERVICE_SYNC_DELETE_CMDS)) {
+			wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
 		}
 		params->status = QDF_STATUS_E_TIMEOUT;
 
@@ -3081,9 +3053,8 @@ void wma_vdev_resp_timer(void *data)
 			wma_remove_peer(wma, params->bssid, tgt_req->vdev_id,
 					peer, false);
 		}
-		if (wmi_unified_vdev_down_send(wma->wmi_handle,
-					tgt_req->vdev_id) !=
-					QDF_STATUS_SUCCESS) {
+		if (wma_send_vdev_down_to_fw(wma, tgt_req->vdev_id) !=
+		    QDF_STATUS_SUCCESS) {
 			WMA_LOGE("Failed to send vdev down cmd: vdev %d",
 				tgt_req->vdev_id);
 		}
@@ -4449,8 +4420,8 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params)
 
 	param.vdev_id = params->smesessionId;
 	param.assoc_id = params->assocId;
-	if (wmi_unified_vdev_up_send(wma->wmi_handle, params->bssId,
-				     &param) != QDF_STATUS_SUCCESS) {
+	if (wma_send_vdev_up_to_fw(wma, &param, params->bssId) !=
+	    QDF_STATUS_SUCCESS) {
 		WMA_LOGE("%s: Failed to send vdev up cmd: vdev %d bssid %pM",
 			 __func__, params->smesessionId, params->bssId);
 		policy_mgr_set_do_hw_mode_change_flag(
@@ -4563,16 +4534,10 @@ static void wma_delete_sta_req_ap_mode(tp_wma_handle wma,
 			del_sta->status = QDF_STATUS_E_NOMEM;
 			goto send_del_rsp;
 		}
-		/*
-		 * Acquire wake lock and bus lock till
-		 * firmware sends the response
-		 */
-		cds_host_diag_log_work(&wma->wmi_cmd_rsp_wake_lock,
-				      WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION,
-				      WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
-		qdf_wake_lock_timeout_acquire(&wma->wmi_cmd_rsp_wake_lock,
-				      WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION);
-		qdf_runtime_pm_prevent_suspend(wma->wmi_cmd_rsp_runtime_lock);
+
+		wma_acquire_wakelock(&wma->wmi_cmd_rsp_wake_lock,
+				     WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION);
+
 		return;
 	}
 
@@ -4648,19 +4613,9 @@ static void wma_del_tdls_sta(tp_wma_handle wma, tpDeleteStaParams del_sta)
 			del_sta->status = QDF_STATUS_E_NOMEM;
 			goto send_del_rsp;
 		}
-		/*
-		 * Acquire wake lock and bus lock till
-		 * firmware sends the response
-		 */
-		cds_host_diag_log_work(&wma->
-				wmi_cmd_rsp_wake_lock,
-				WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION,
-				WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
-		qdf_wake_lock_timeout_acquire(&wma->
-				wmi_cmd_rsp_wake_lock,
+
+		wma_acquire_wakelock(&wma->wmi_cmd_rsp_wake_lock,
 				WMA_FW_RSP_EVENT_WAKE_LOCK_DURATION);
-		qdf_runtime_pm_prevent_suspend(wma->
-				wmi_cmd_rsp_runtime_lock);
 	}
 
 	return;

+ 34 - 10
core/wma/src/wma_main.c

@@ -2170,6 +2170,18 @@ static int wma_flush_complete_evt_handler(void *handle,
 	return QDF_STATUS_E_FAILURE;
 }
 
+void wma_vdev_init(struct wma_txrx_node *vdev)
+{
+	qdf_wake_lock_create(&vdev->vdev_start_wakelock, "vdev_start");
+	qdf_wake_lock_create(&vdev->vdev_stop_wakelock, "vdev_stop");
+}
+
+void wma_vdev_deinit(struct wma_txrx_node *vdev)
+{
+	qdf_wake_lock_destroy(&vdev->vdev_start_wakelock);
+	qdf_wake_lock_destroy(&vdev->vdev_stop_wakelock);
+}
+
 /**
  * wma_open() - Allocate wma context and initialize it.
  * @psoc: Psoc pointer
@@ -2191,8 +2203,8 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, void *cds_context,
 	struct wmi_rx_ops ops;
 	struct policy_mgr_wma_cbacks wma_cbacks;
 	struct target_psoc_info *tgt_psoc_info;
-
 	bool use_cookie = false;
+	int i;
 
 	WMA_LOGD("%s: Enter", __func__);
 
@@ -2366,8 +2378,10 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, void *cds_context,
 		qdf_status = QDF_STATUS_E_NOMEM;
 		goto err_scn_context;
 	}
-	qdf_mem_zero(wma_handle->interfaces, sizeof(struct wma_txrx_node) *
-		     wma_handle->max_bssid);
+
+	for (i = 0; i < wma_handle->max_bssid; ++i)
+		wma_vdev_init(&wma_handle->interfaces[i]);
+
 	/* Register the debug print event handler */
 	wmi_unified_register_event_handler(wma_handle->wmi_handle,
 					WMI_DEBUG_PRINT_EVENTID,
@@ -2697,7 +2711,12 @@ err_dbglog_init:
 err_event_init:
 	wmi_unified_unregister_event_handler(wma_handle->wmi_handle,
 					     WMI_DEBUG_PRINT_EVENTID);
+
+	for (i = 0; i < wma_handle->max_bssid; ++i)
+		wma_vdev_deinit(&wma_handle->interfaces[i]);
+
 	qdf_mem_free(wma_handle->interfaces);
+
 err_scn_context:
 #if defined(QCA_WIFI_FTM)
 	wma_utf_detach(wma_handle);
@@ -2866,7 +2885,7 @@ static int wma_log_supported_evt_handler(void *handle,
  * driver in response to a WMI_PDEV_SET_HW_MODE_CMDID being sent to WLAN
  * firmware
  *
- * Return: Success on receiving valid params from FW
+ * Return: QDF_STATUS
  */
 static int wma_pdev_set_hw_mode_resp_evt_handler(void *handle,
 		uint8_t *event,
@@ -2886,7 +2905,9 @@ static int wma_pdev_set_hw_mode_resp_evt_handler(void *handle,
 		 */
 		return QDF_STATUS_E_NULL_VALUE;
 	}
-	wma_release_wmi_resp_wakelock(wma);
+
+	wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
+
 	hw_mode_resp = qdf_mem_malloc(sizeof(*hw_mode_resp));
 	if (!hw_mode_resp) {
 		WMA_LOGE("%s: Memory allocation failed", __func__);
@@ -3556,9 +3577,12 @@ QDF_STATUS wma_wmi_service_close(void *cds_ctx)
 				     interfaces[i].psnr_req);
 			wma_handle->interfaces[i].psnr_req = NULL;
 		}
+
+		wma_vdev_deinit(&wma_handle->interfaces[i]);
 	}
 
 	qdf_mem_free(wma_handle->interfaces);
+
 	/* free the wma_handle */
 	cds_free_context(wma_handle->cds_context, QDF_MODULE_ID_WMA,
 			 wma_handle);
@@ -7484,7 +7508,7 @@ QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle,
  * Return: Success if the cmd is sent successfully to the firmware
  */
 QDF_STATUS wma_send_pdev_set_hw_mode_cmd(tp_wma_handle wma_handle,
-				struct policy_mgr_hw_mode *msg)
+					 struct policy_mgr_hw_mode *msg)
 {
 	struct sir_set_hw_mode_resp *param;
 
@@ -7503,11 +7527,11 @@ QDF_STATUS wma_send_pdev_set_hw_mode_cmd(tp_wma_handle wma_handle,
 		goto fail;
 	}
 
-	wma_acquire_wmi_resp_wakelock(wma_handle,
-				WMA_VDEV_HW_MODE_REQUEST_TIMEOUT);
+	wma_acquire_wakelock(&wma_handle->wmi_cmd_rsp_wake_lock,
+			     WMA_VDEV_HW_MODE_REQUEST_TIMEOUT);
 	if (wmi_unified_soc_set_hw_mode_cmd(wma_handle->wmi_handle,
-				msg->hw_mode_index)) {
-		wma_release_wmi_resp_wakelock(wma_handle);
+					    msg->hw_mode_index)) {
+		wma_release_wakelock(&wma_handle->wmi_cmd_rsp_wake_lock);
 		goto fail;
 	}
 

+ 2 - 3
core/wma/src/wma_mgmt.c

@@ -2672,9 +2672,8 @@ void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info)
 		if (!wma_is_vdev_up(vdev_id)) {
 			param.vdev_id = vdev_id;
 			param.assoc_id = 0;
-			status = wmi_unified_vdev_up_send(wma->wmi_handle,
-					bcn_info->bssId,
-					&param);
+			status = wma_send_vdev_up_to_fw(wma, &param,
+							bcn_info->bssId);
 			if (QDF_IS_STATUS_ERROR(status)) {
 				WMA_LOGE(FL("failed to send vdev up"));
 				policy_mgr_set_do_hw_mode_change_flag(

+ 41 - 12
core/wma/src/wma_utils.c

@@ -4259,19 +4259,20 @@ bool wma_is_vdev_up(uint8_t vdev_id)
 	return (state == WLAN_VDEV_S_RUN) ? true : false;
 }
 
-void wma_acquire_wmi_resp_wakelock(t_wma_handle *wma, uint32_t msec)
+void wma_acquire_wakelock(qdf_wake_lock_t *wl, 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);
+	t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
+
+	cds_host_diag_log_work(wl, msec, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
+	qdf_wake_lock_timeout_acquire(wl, msec);
 	qdf_runtime_pm_prevent_suspend(wma->wmi_cmd_rsp_runtime_lock);
 }
 
-void wma_release_wmi_resp_wakelock(t_wma_handle *wma)
+void wma_release_wakelock(qdf_wake_lock_t *wl)
 {
-	qdf_wake_lock_release(&wma->wmi_cmd_rsp_wake_lock,
-			      WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
+	t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA);
+
+	qdf_wake_lock_release(wl, WIFI_POWER_EVENT_WAKELOCK_WMI_CMD_RSP);
 	qdf_runtime_pm_allow_suspend(wma->wmi_cmd_rsp_runtime_lock);
 }
 
@@ -4279,11 +4280,13 @@ QDF_STATUS
 wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params)
 {
 	QDF_STATUS status;
+	struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
 
-	wma_acquire_wmi_resp_wakelock(wma, WMA_VDEV_START_REQUEST_TIMEOUT);
+	wma_acquire_wakelock(&vdev->vdev_start_wakelock,
+			     WMA_VDEV_START_REQUEST_TIMEOUT);
 	status = wmi_unified_vdev_start_send(wma->wmi_handle, params);
 	if (QDF_IS_STATUS_ERROR(status))
-		wma_release_wmi_resp_wakelock(wma);
+		wma_release_wakelock(&vdev->vdev_start_wakelock);
 
 	return status;
 }
@@ -4291,11 +4294,13 @@ wma_send_vdev_start_to_fw(t_wma_handle *wma, struct vdev_start_params *params)
 QDF_STATUS wma_send_vdev_stop_to_fw(t_wma_handle *wma, uint8_t vdev_id)
 {
 	QDF_STATUS status;
+	struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
 
-	wma_acquire_wmi_resp_wakelock(wma, WMA_VDEV_STOP_REQUEST_TIMEOUT);
+	wma_acquire_wakelock(&vdev->vdev_stop_wakelock,
+			     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);
+		wma_release_wakelock(&vdev->vdev_stop_wakelock);
 
 	return status;
 }
@@ -4312,6 +4317,30 @@ bool wma_is_service_enabled(WMI_SERVICE service_type)
 	return WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, service_type);
 }
 
+QDF_STATUS wma_send_vdev_up_to_fw(t_wma_handle *wma,
+				  struct vdev_up_params *params,
+				  uint8_t bssid[IEEE80211_ADDR_LEN])
+{
+	QDF_STATUS status;
+	struct wma_txrx_node *vdev = &wma->interfaces[params->vdev_id];
+
+	status = wmi_unified_vdev_up_send(wma->wmi_handle, bssid, params);
+	wma_release_wakelock(&vdev->vdev_start_wakelock);
+
+	return status;
+}
+
+QDF_STATUS wma_send_vdev_down_to_fw(t_wma_handle *wma, uint8_t vdev_id)
+{
+	QDF_STATUS status;
+	struct wma_txrx_node *vdev = &wma->interfaces[vdev_id];
+
+	status = wmi_unified_vdev_down_send(wma->wmi_handle, vdev_id);
+	wma_release_wakelock(&vdev->vdev_start_wakelock);
+
+	return status;
+}
+
 tSirWifiPeerType wmi_to_sir_peer_type(enum wmi_peer_type type)
 {
 	switch (type) {