Browse Source

qcacld-3.0: Host sends VDEV_DELETE cmd to fw before stop_bss

When stop_ap command comes from userspace, __wlan_hdd_cfg80211_stop_ap
calls sap_fsm to change the states of SAP from started to disconnect.
In order to change SAP states, __wlan_hdd_cfg80211_stop_ap sends
WMI_VDEV_STOP_CMDID followed by WMI_VDEV_DOWN_CMDID and
WMI_VDEV_DELETE_CMDID to fw. After the successful change in state of
SAP machine, driver invokes an HDD callback, hdd_hostapd_sap_event_cb
for cleanup and subsequently invokes hdd_softap_stop_bss to reclaim all
resources. This API sends IPA_OFFLOAD_ENABLE_DISABLE cmd to fw for the
VDEV on which SAP started. Which results assert in firmware as host
sends HDD IPA event for the VDEV which is already deleted while changing
the state of SAP.

Fix is to send HDD_IPA_AP_DISCONNECT IPA events before stop BSS.

Change-Id: Ief9318bb476b480fd52f4155a0788a34c1e2ed53
CRs-Fixed: 2276125
Abhinav Kumar 6 years ago
parent
commit
85a4bb876a

+ 22 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -757,6 +757,7 @@ static int hdd_stop_bss_link(struct hdd_adapter *adapter)
 		return errno;
 
 	if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
+		hdd_ipa_ap_disconnect(adapter);
 		status = wlansap_stop_bss(
 			WLAN_HDD_GET_SAP_CTX_PTR(adapter));
 		if (QDF_IS_STATUS_SUCCESS(status))
@@ -5138,6 +5139,7 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy,
 			WLAN_HDD_GET_SAP_CTX_PTR(adapter), true);
 
 		qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
+		hdd_ipa_ap_disconnect(adapter);
 		status = wlansap_stop_bss(WLAN_HDD_GET_SAP_CTX_PTR(adapter));
 		if (QDF_IS_STATUS_SUCCESS(status)) {
 			qdf_status =
@@ -5811,3 +5813,23 @@ bool hdd_is_peer_associated(struct hdd_adapter *adapter,
 
 	return false;
 }
+
+void hdd_ipa_ap_disconnect(struct hdd_adapter *adapter)
+{
+	struct hdd_context *hdd_ctx;
+	struct hdd_ap_ctx *ap_ctx;
+
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
+
+	if (ucfg_ipa_is_enabled()) {
+		if (ucfg_ipa_wlan_evt(hdd_ctx->hdd_pdev,
+				adapter->dev, adapter->device_mode,
+				ap_ctx->broadcast_sta_id,
+				adapter->session_id,
+				WLAN_IPA_AP_DISCONNECT,
+				adapter->dev->dev_addr) != QDF_STATUS_SUCCESS)
+			hdd_err("WLAN_AP_DISCONNECT event failed");
+	}
+}
+

+ 10 - 0
core/hdd/src/wlan_hdd_hostapd.h

@@ -194,4 +194,14 @@ QDF_STATUS wlan_hdd_config_acs(struct hdd_context *hdd_ctx,
 			       struct hdd_adapter *adapter);
 
 void hdd_sap_indicate_disconnect_for_sta(struct hdd_adapter *adapter);
+
+/**
+ * hdd_ipa_ap_disconnect() - call hdd_ipa_wlan_evt if
+ * ipa is enabled
+ * @pAdapter: pointer to adapter context
+ *
+ * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error
+ */
+void hdd_ipa_ap_disconnect(struct hdd_adapter *adapter);
+
 #endif /* end #if !defined(WLAN_HDD_HOSTAPD_H) */

+ 3 - 0
core/hdd/src/wlan_hdd_main.c

@@ -5266,6 +5266,7 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
 			QDF_STATUS status;
 			QDF_STATUS qdf_status;
 
+			hdd_ipa_ap_disconnect(adapter);
 			/* Stop Bss. */
 			status = wlansap_stop_bss(
 					WLAN_HDD_GET_SAP_CTX_PTR(adapter));
@@ -12012,6 +12013,7 @@ void wlan_hdd_stop_sap(struct hdd_adapter *ap_adapter)
 		hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
 		hdd_debug("Now doing SAP STOPBSS");
 		qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
+		hdd_ipa_ap_disconnect(ap_adapter);
 		if (QDF_STATUS_SUCCESS == wlansap_stop_bss(hdd_ap_ctx->
 							sap_context)) {
 			qdf_status = qdf_wait_for_event_completion(&hostapd_state->
@@ -13874,6 +13876,7 @@ void hdd_restart_sap(struct hdd_adapter *ap_adapter)
 		wlan_hdd_del_station(ap_adapter);
 		hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
 		qdf_event_reset(&hostapd_state->qdf_stop_bss_event);
+		hdd_ipa_ap_disconnect(ap_adapter);
 		if (QDF_STATUS_SUCCESS == wlansap_stop_bss(sap_ctx)) {
 			qdf_status =
 				qdf_wait_for_event_completion(&hostapd_state->

+ 0 - 10
core/hdd/src/wlan_hdd_softap_tx_rx.c

@@ -1175,16 +1175,6 @@ QDF_STATUS hdd_softap_stop_bss(struct hdd_adapter *adapter)
 		sme_update_channel_list(hdd_ctx->mac_handle);
 	}
 
-	if (ucfg_ipa_is_enabled()) {
-		if (ucfg_ipa_wlan_evt(hdd_ctx->hdd_pdev,
-				adapter->dev, adapter->device_mode,
-				ap_ctx->broadcast_sta_id,
-				adapter->session_id,
-				WLAN_IPA_AP_DISCONNECT,
-				adapter->dev->dev_addr) != QDF_STATUS_SUCCESS)
-			hdd_err("WLAN_AP_DISCONNECT event failed");
-	}
-
 	return qdf_status;
 }