Эх сурвалжийг харах

qcacld-3.0: Avoid VDEV start for new interface when roaming in progress

Currently driver allows start_bss on SAP interface even when roaming is
in progress on STA interface. This leads to two simultaneous vdev starts
in FW which causes the FW to assert.

Add changes to reject the start_bss request for SAP if roaming is in
progress on any STA interface.
Also, when a connect for STA or start_bss for SAP is received and
roaming is not in progress for any STA interface, stop roaming on all
STA interfaces by sending WMI_ROAM_SCAN_MODE_NONE to FW. Also after
association or start_bss completion, enable roaming again on connected
STA interface.

Change-Id: I3baaffeef3b350e6527660cbac4b79fa4d9f83f0
CRs-Fixed: 2221337
Padma, Santhosh Kumar 6 жил өмнө
parent
commit
86747ece8c

+ 31 - 3
core/hdd/inc/wlan_hdd_main.h

@@ -2413,8 +2413,28 @@ void hdd_ch_avoid_ind(struct hdd_context *hdd_ctxt,
 
 void hdd_update_macaddr(struct hdd_config *config,
 			struct qdf_mac_addr hw_macaddr);
-void wlan_hdd_disable_roaming(struct hdd_adapter *adapter);
-void wlan_hdd_enable_roaming(struct hdd_adapter *adapter);
+
+/**
+ * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
+ * @cur_adapter: Current HDD adapter passed from caller
+ *
+ * This function loops through all adapters and disables roaming on each STA
+ * mode adapter except the current adapter passed from the caller
+ *
+ * Return: None
+ */
+void wlan_hdd_disable_roaming(struct hdd_adapter *cur_adapter);
+
+/**
+ * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
+ * @cur_adapter: Current HDD adapter passed from caller
+ *
+ * This function loops through all adapters and enables roaming on each STA
+ * mode adapter except the current adapter passed from the caller
+ *
+ * Return: None
+ */
+void wlan_hdd_enable_roaming(struct hdd_adapter *cur_adapter);
 
 QDF_STATUS hdd_post_cds_enable_config(struct hdd_context *hdd_ctx);
 
@@ -2785,7 +2805,15 @@ tSirAddie *hdd_assoc_additional_ie(struct hdd_adapter *adapter)
 	return &sta_ctx->assoc_additional_ie;
 }
 
-bool hdd_is_roaming_in_progress(struct hdd_adapter *adapter);
+/**
+ * hdd_is_roaming_in_progress() - check if roaming is in progress
+ * @hdd_ctx - Global HDD context
+ *
+ * Checks if roaming is in progress on any of the adapters
+ *
+ * Return: true if roaming is in progress else false
+ */
+bool hdd_is_roaming_in_progress(struct hdd_context *hdd_ctx);
 void hdd_set_roaming_in_progress(bool value);
 bool hdd_is_connection_in_progress(uint8_t *session_id,
 	enum scan_reject_states *reason);

+ 8 - 0
core/hdd/src/wlan_hdd_assoc.c

@@ -2772,6 +2772,14 @@ hdd_association_completion_handler(struct hdd_adapter *adapter,
 		hdd_err("config is NULL");
 		return QDF_STATUS_E_NULL_VALUE;
 	}
+
+	/*
+	 * Enable roaming on other STA iface except this one.
+	 * Firmware dosent support connection on one STA iface while
+	 * roaming on other STA iface
+	 */
+	wlan_hdd_enable_roaming(adapter);
+
 	/* HDD has initiated disconnect, do not send connect result indication
 	 * to kernel as it will be handled by __cfg80211_disconnect.
 	 */

+ 14 - 2
core/hdd/src/wlan_hdd_cfg80211.c

@@ -17871,6 +17871,9 @@ static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
 		goto ret_status;
 	}
 
+	/* Disable roaming on all other adapters before connect start */
+	wlan_hdd_disable_roaming(adapter);
+
 	hdd_notify_teardown_tdls_links(adapter->hdd_vdev);
 
 	qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
@@ -18177,6 +18180,13 @@ conn_failure:
 	hdd_set_connection_in_progress(false);
 
 ret_status:
+	/*
+	 * Enable roaming on other STA adapter for failure case.
+	 * For success case, it is enabled in assoc completion handler
+	 */
+	if (status)
+		wlan_hdd_enable_roaming(adapter);
+
 	hdd_exit();
 	return status;
 }
@@ -19281,7 +19291,9 @@ int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
 	int status, result = 0;
 	tHalHandle hal;
 	uint32_t wait_time = WLAN_WAIT_TIME_DISCONNECT;
+	struct hdd_context *hdd_ctx;
 
+	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
 	hal = WLAN_HDD_GET_HAL_CTX(adapter);
 	if (adapter->device_mode ==  QDF_STA_MODE) {
@@ -19295,7 +19307,7 @@ int wlan_hdd_try_disconnect(struct hdd_adapter *adapter)
 		 *
 		 */
 		INIT_COMPLETION(adapter->roaming_comp_var);
-		if (hdd_is_roaming_in_progress(adapter)) {
+		if (hdd_is_roaming_in_progress(hdd_ctx)) {
 			rc = wait_for_completion_timeout(
 				&adapter->roaming_comp_var,
 				msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));
@@ -19696,7 +19708,7 @@ int wlan_hdd_disconnect(struct hdd_adapter *adapter, u16 reason)
 		 *
 		 */
 		INIT_COMPLETION(adapter->roaming_comp_var);
-		if (hdd_is_roaming_in_progress(adapter)) {
+		if (hdd_is_roaming_in_progress(hdd_ctx)) {
 			rc = wait_for_completion_timeout(
 				&adapter->roaming_comp_var,
 				msecs_to_jiffies(WLAN_WAIT_TIME_STOP_ROAM));

+ 20 - 4
core/hdd/src/wlan_hdd_hostapd.c

@@ -7382,10 +7382,25 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 		wlan_hdd_disconnect(sta_adapter, eCSR_DISCONNECT_REASON_DEAUTH);
 	}
 
+	/*
+	 * Reject start bss if reassoc in progress on any adapter.
+	 * sme_is_any_session_in_middle_of_roaming is for LFR2 and
+	 * hdd_is_roaming_in_progress is for LFR3
+	 */
+	if (sme_is_any_session_in_middle_of_roaming(hdd_ctx->hHal) ||
+	    hdd_is_roaming_in_progress(hdd_ctx)) {
+		hdd_info("Reassociation in progress");
+		return -EINVAL;
+	}
+
+	/* Disable Roaming on all adapters before starting bss */
+	wlan_hdd_disable_roaming(adapter);
+
 	sme_config = qdf_mem_malloc(sizeof(*sme_config));
 	if (!sme_config) {
 		hdd_err("failed to allocate memory");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto free;
 	}
 
 	iniConfig = hdd_ctx->config;
@@ -7401,8 +7416,8 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 		    sme_update_channel_list(hdd_ctx->hHal))) {
 			hdd_update_indoor_channel(hdd_ctx, false);
 			hdd_err("Can't start BSS: update channel list failed");
-			qdf_mem_free(sme_config);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto free;
 		}
 	}
 
@@ -8015,7 +8030,6 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 	hdd_unsafe_channel_restart_sap(hdd_ctx);
 
 	hdd_set_connection_in_progress(false);
-	hdd_exit();
 
 	ret = 0;
 	goto free;
@@ -8031,6 +8045,8 @@ error:
 	wlan_hdd_undo_acs(adapter);
 
 free:
+	/* Enable Roaming after start bss in case of failure/success */
+	wlan_hdd_enable_roaming(adapter);
 	qdf_mem_free(sme_config);
 	return ret;
 }

+ 50 - 90
core/hdd/src/wlan_hdd_main.c

@@ -11255,84 +11255,56 @@ QDF_STATUS hdd_issta_p2p_clientconnected(struct hdd_context *hdd_ctx)
 	return sme_is_sta_p2p_client_connected(hdd_ctx->hHal);
 }
 
-/**
- * wlan_hdd_disable_roaming() - disable roaming on all STAs except the input one
- * @adapter:	HDD adapter pointer
- *
- * This function loop through each adapter and disable roaming on each STA
- * device mode except the input adapter.
- *
- * Note: On the input adapter roaming is not enabled yet hence no need to
- *       disable.
- *
- * Return: None
- */
-void wlan_hdd_disable_roaming(struct hdd_adapter *adapter)
+void wlan_hdd_disable_roaming(struct hdd_adapter *cur_adapter)
 {
-	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	struct hdd_adapter *adapterIdx = NULL;
-
-	if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
-		hdd_ctx->config->isRoamOffloadScanEnabled &&
-		QDF_STA_MODE == adapter->device_mode &&
-		policy_mgr_is_sta_active_connection_exists(
-		hdd_ctx->hdd_psoc)) {
-		hdd_debug("Connect received on STA session Id(%d)",
-		       adapter->session_id);
-		/*
-		 * Loop through adapter and disable roaming for each STA device
-		 * mode except the input adapter.
-		 */
-		hdd_for_each_adapter(hdd_ctx, adapterIdx) {
-			if (QDF_STA_MODE == adapterIdx->device_mode &&
-			    adapter->session_id != adapterIdx->session_id) {
-				hdd_debug("Disable Roaming on session Id(%d)",
-				       adapterIdx->session_id);
-				sme_stop_roaming(WLAN_HDD_GET_HAL_CTX
-							 (adapterIdx),
-						 adapterIdx->session_id, 0);
-			}
+	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(cur_adapter);
+	struct hdd_adapter *adapter = NULL;
+	struct csr_roam_profile *roam_profile;
+	struct hdd_station_ctx *sta_ctx;
+
+	if (!policy_mgr_is_sta_active_connection_exists(hdd_ctx->hdd_psoc)) {
+		hdd_debug("No active sta session");
+		return;
+	}
+
+	hdd_for_each_adapter(hdd_ctx, adapter) {
+		roam_profile = hdd_roam_profile(adapter);
+		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+
+		if (cur_adapter->session_id != adapter->session_id &&
+		    adapter->device_mode == QDF_STA_MODE &&
+		    hdd_conn_is_connected(sta_ctx)) {
+			hdd_debug("%d Disable roaming", adapter->session_id);
+			sme_stop_roaming(WLAN_HDD_GET_HAL_CTX(adapter),
+					 adapter->session_id,
+					 ecsr_driver_disabled);
 		}
 	}
 }
 
-/**
- * wlan_hdd_enable_roaming() - enable roaming on all STAs except the input one
- * @adapter:	HDD adapter pointer
- *
- * This function loop through each adapter and enable roaming on each STA
- * device mode except the input adapter.
- * Note: On the input adapter no need to enable roaming because link got
- *       disconnected on this.
- *
- * Return: None
- */
-void wlan_hdd_enable_roaming(struct hdd_adapter *adapter)
+void wlan_hdd_enable_roaming(struct hdd_adapter *cur_adapter)
 {
-	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
-	struct hdd_adapter *adapterIdx = NULL;
-
-	if (hdd_ctx->config->isFastRoamIniFeatureEnabled &&
-		hdd_ctx->config->isRoamOffloadScanEnabled &&
-		QDF_STA_MODE == adapter->device_mode &&
-		policy_mgr_is_sta_active_connection_exists(
-		hdd_ctx->hdd_psoc)) {
-		hdd_debug("Disconnect received on STA session Id(%d)",
-		       adapter->session_id);
-		/*
-		 * Loop through adapter and enable roaming for each STA device
-		 * mode except the input adapter.
-		 */
-		hdd_for_each_adapter(hdd_ctx, adapterIdx) {
-			if (QDF_STA_MODE == adapterIdx->device_mode &&
-			    adapter->session_id != adapterIdx->session_id) {
-				hdd_debug("Enabling Roaming on session Id(%d)",
-				       adapterIdx->session_id);
-				sme_start_roaming(WLAN_HDD_GET_HAL_CTX
-							  (adapterIdx),
-						  adapterIdx->session_id,
-						  REASON_CONNECT);
-			}
+	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(cur_adapter);
+	struct hdd_adapter *adapter = NULL;
+	struct csr_roam_profile *roam_profile;
+	struct hdd_station_ctx *sta_ctx;
+
+	if (!policy_mgr_is_sta_active_connection_exists(hdd_ctx->hdd_psoc)) {
+		hdd_debug("No active sta session");
+		return;
+	}
+
+	hdd_for_each_adapter(hdd_ctx, adapter) {
+		roam_profile = hdd_roam_profile(adapter);
+		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
+
+		if (cur_adapter->session_id != adapter->session_id &&
+		    adapter->device_mode == QDF_STA_MODE &&
+		    hdd_conn_is_connected(sta_ctx)) {
+			hdd_debug("%d Enable roaming", adapter->session_id);
+			sme_start_roaming(WLAN_HDD_GET_HAL_CTX(adapter),
+					  adapter->session_id,
+					  REASON_DRIVER_ENABLED);
 		}
 	}
 }
@@ -13450,28 +13422,16 @@ void hdd_set_roaming_in_progress(bool value)
 	hdd_debug("Roaming in Progress set to %d", value);
 }
 
-/**
- * hdd_is_roaming_in_progress() - check if roaming is in progress
- * @adapter - HDD adapter
- *
- * Return: true if roaming is in progress for STA type, else false
- */
-bool hdd_is_roaming_in_progress(struct hdd_adapter *adapter)
+bool hdd_is_roaming_in_progress(struct hdd_context *hdd_ctx)
 {
-	struct hdd_context *hdd_ctx;
-	bool ret_status = false;
-
-	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
 	if (!hdd_ctx) {
 		hdd_err("HDD context is NULL");
-		return ret_status;
+		return false;
 	}
-	hdd_debug("dev mode = %d, roaming_in_progress = %d",
-			adapter->device_mode, hdd_ctx->roaming_in_progress);
-	ret_status = ((adapter->device_mode == QDF_STA_MODE) &&
-			hdd_ctx->roaming_in_progress);
 
-	return ret_status;
+	hdd_debug("roaming_in_progress = %d", hdd_ctx->roaming_in_progress);
+
+	return hdd_ctx->roaming_in_progress;
 }
 
 /**
@@ -13526,7 +13486,7 @@ bool hdd_is_connection_in_progress(uint8_t *session_id,
 		     sme_neighbor_middle_of_roaming(
 			     WLAN_HDD_GET_HAL_CTX(adapter),
 			     adapter->session_id)) ||
-		    hdd_is_roaming_in_progress(adapter)) {
+		    hdd_is_roaming_in_progress(hdd_ctx)) {
 			hdd_debug("%pK(%d) Reassociation in progress",
 				WLAN_HDD_GET_STATION_CTX_PTR(adapter),
 				adapter->session_id);

+ 1 - 0
core/sme/inc/csr_api.h

@@ -904,6 +904,7 @@ struct csr_roam_profile {
 	uint32_t cac_duration_ms;
 	uint32_t dfs_regdomain;
 	bool supplicant_disabled_roaming;
+	bool driver_disabled_roaming;
 #ifdef WLAN_FEATURE_FILS_SK
 	bool fils_connection;
 	uint8_t *hlp_ie;

+ 2 - 0
core/sme/inc/csr_internal.h

@@ -140,6 +140,8 @@ enum csr_roam_reason {
 	eCsrForcedDisassocSta,
 	eCsrForcedDeauthSta,
 	eCsrPerformPreauth,
+	/* Roaming disabled from driver during connect/start BSS */
+	ecsr_driver_disabled,
 };
 
 enum csr_roam_substate {

+ 1 - 0
core/sme/inc/csr_neighbor_roam.h

@@ -324,6 +324,7 @@ void csr_roam_reset_roam_params(tpAniSirGlobal mac_ptr);
 #define REASON_CTX_INIT                             40
 #define REASON_FILS_PARAMS_CHANGED                  41
 #define REASON_SME_ISSUED                           42
+#define REASON_DRIVER_ENABLED                       43
 
 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD)
 QDF_STATUS csr_roam_offload_scan(tpAniSirGlobal pMac, uint8_t sessionId,

+ 10 - 0
core/sme/inc/sme_api.h

@@ -1033,6 +1033,16 @@ QDF_STATUS sme_wifi_start_logger(tHalHandle hal,
 bool sme_neighbor_middle_of_roaming(tHalHandle hHal,
 						uint8_t sessionId);
 
+/*
+ * sme_is_any_session_in_middle_of_roaming() - check if roaming is in progress
+ * @hal: MAC Handle
+ *
+ * Checks if any SME session is in middle of roaming
+ *
+ * Return : true if roaming is in progress else false
+ */
+bool sme_is_any_session_in_middle_of_roaming(mac_handle_t hal);
+
 /**
  * sme_enable_uapsd_for_ac() - enable uapsd for access category request to WMA
  * @sta_id: station id

+ 26 - 1
core/sme/src/common/sme_api.c

@@ -6982,6 +6982,17 @@ QDF_STATUS sme_stop_roaming(tHalHandle hal, uint8_t session_id, uint8_t reason)
 
 	session = CSR_GET_SESSION(mac_ctx, session_id);
 
+	/*
+	 * set the driver_disabled_roaming flag to true even if roaming
+	 * is not enabled on this session so that roam start requests for
+	 * this session can be blocked until driver enables roaming
+	 */
+	if (reason == ecsr_driver_disabled && session->pCurRoamProfile) {
+		session->pCurRoamProfile->driver_disabled_roaming = true;
+		sme_debug("driver_disabled_roaming set for session %d",
+			  session_id);
+	}
+
 	roam_info = &mac_ctx->roam.neighborRoamInfo[session_id];
 	if (!roam_info->b_roam_scan_offload_started) {
 		sme_debug("Roaming already disabled for session %d", session_id);
@@ -6994,7 +7005,7 @@ QDF_STATUS sme_stop_roaming(tHalHandle hal, uint8_t session_id, uint8_t reason)
 	}
 
 	req->Command = ROAM_SCAN_OFFLOAD_STOP;
-	if (reason == eCsrForcedDisassoc)
+	if ((reason == eCsrForcedDisassoc) || reason == ecsr_driver_disabled)
 		req->reason = REASON_ROAM_STOP_ALL;
 	else
 		req->reason = REASON_SME_ISSUED;
@@ -12735,6 +12746,20 @@ bool sme_neighbor_middle_of_roaming(tHalHandle hHal, uint8_t sessionId)
 	return val;
 }
 
+bool sme_is_any_session_in_middle_of_roaming(mac_handle_t hal)
+{
+	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+	uint8_t session_id;
+
+	for (session_id = 0; session_id < CSR_ROAM_SESSION_MAX; session_id++) {
+		if (CSR_IS_SESSION_VALID(mac_ctx, session_id) &&
+		    csr_neighbor_middle_of_roaming(mac_ctx, session_id))
+			return true;
+	}
+
+	return false;
+}
+
 /*
  * sme_send_flush_logs_cmd_to_fw() - Flush FW logs
  * @mac: MAC handle

+ 15 - 0
core/sme/src/csr/csr_api_roam.c

@@ -19454,6 +19454,21 @@ csr_roam_offload_scan(tpAniSirGlobal mac_ctx, uint8_t session_id,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (command == ROAM_SCAN_OFFLOAD_START &&
+	    (session->pCurRoamProfile &&
+	    session->pCurRoamProfile->driver_disabled_roaming)) {
+		if (reason == REASON_DRIVER_ENABLED) {
+			session->pCurRoamProfile->driver_disabled_roaming =
+									false;
+			sme_debug("driver_disabled_roaming reset for session %d",
+				  session_id);
+		} else {
+			sme_debug("Roam start received for session %d on which driver has disabled roaming",
+				  session_id);
+			return QDF_STATUS_E_FAILURE;
+		}
+	}
+
 	if (0 == csr_roam_is_roam_offload_scan_enabled(mac_ctx)) {
 		sme_err("isRoamOffloadScanEnabled not set");
 		return QDF_STATUS_E_FAILURE;