Browse Source

qcacld-3.0: Do HW mode change based on all the candidate APs for STA

The driver currently changes the hw_mode based upon
the first candidate found in the scan list, and tries
to connect to it. It may happen that the connection
fails, and the STA then tries to connect to the AP
on same channel as the concurrent adapter.
It would result in hw_mode = DBS, as it is not
updated after  connection success/failure.
Also if the first AP channel is in same band as that
of concurrent adapter, and the connection fails,
and the STA tries to connect to an AP in a different
band, this too is not allowed as hw_mode is not DBS

Fix is to change the hw_mode based upon the scan list.
If the driver finds any scan result which may lead to
DBS connection, the hw_mode should be set to DBS.
Once the connection is done or failed, the driver
can check and update the hw_mode again.

Change-Id: I42ffe0c63371e048771e2b9b00b887e9c6c65d6c
CRs-Fixed: 2288572
Tushnim Bhattacharyya 6 years ago
parent
commit
3f78053b87

+ 4 - 1
core/hdd/src/wlan_hdd_assoc.c

@@ -3254,9 +3254,12 @@ hdd_association_completion_handler(struct hdd_adapter *adapter,
 		hdd_debug("check for SAP restart");
 		policy_mgr_check_concurrent_intf_and_restart_sap(
 			hdd_ctx->hdd_psoc);
+		policy_mgr_checkn_update_hw_mode_single_mac_mode
+			(hdd_ctx->hdd_psoc, roam_info->pBssDesc->channelId);
 	} else {
 		bool connect_timeout = false;
-
+		/* do we need to change the HW mode */
+		policy_mgr_check_n_start_opportunistic_timer(hdd_ctx->hdd_psoc);
 		if (roam_info && roam_info->is_fils_connection &&
 		    eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE == roamResult)
 			qdf_copy_macaddr(&roam_info->bssid,

+ 8 - 1
core/sme/src/csr/csr_api_roam.c

@@ -8820,6 +8820,7 @@ QDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId,
 	bool fCallCallback = false;
 	struct csr_roam_session *pSession = CSR_GET_SESSION(pMac, sessionId);
 	tSirBssDescription *first_ap_profile;
+	uint8_t channel_id = 0;
 
 	if (NULL == pSession) {
 		sme_err("session does not exist for given sessionId: %d",
@@ -8951,8 +8952,14 @@ QDF_STATUS csr_roam_connect(tpAniSirGlobal pMac, uint32_t sessionId,
 				status = QDF_STATUS_E_INVAL;
 				goto error;
 			}
+
+			channel_id = csr_get_channel_for_hw_mode_change
+					(pMac, hBSSList, sessionId);
+			if (!channel_id)
+				channel_id = first_ap_profile->channelId;
+
 			status = policy_mgr_handle_conc_multiport(pMac->psoc,
-					sessionId, first_ap_profile->channelId);
+					sessionId, channel_id);
 			if ((QDF_IS_STATUS_SUCCESS(status)) &&
 				(!csr_wait_for_connection_update(pMac, true))) {
 					sme_debug("conn update error");

+ 92 - 0
core/sme/src/csr/csr_api_scan.c

@@ -2102,6 +2102,98 @@ csr_get_bssdescr_from_scan_handle(tScanResultHandle result_handle,
 	return bss_descr;
 }
 
+uint8_t
+csr_get_channel_for_hw_mode_change(tpAniSirGlobal mac_ctx,
+				   tScanResultHandle result_handle,
+				   uint32_t session_id)
+{
+	tListElem *next_element = NULL;
+	struct tag_csrscan_result *scan_result = NULL;
+	struct scan_result_list *bss_list =
+				(struct scan_result_list *)result_handle;
+	uint8_t channel_id = 0;
+
+	if (NULL == bss_list) {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+			  FL("Empty bss_list"));
+		goto end;
+	}
+
+	if (policy_mgr_is_hw_dbs_capable(mac_ctx->psoc) == false) {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
+			  FL("driver isn't dbs capable"));
+		goto end;
+	}
+
+	if (policy_mgr_is_current_hwmode_dbs(mac_ctx->psoc)) {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
+			  FL("driver is already in DBS"));
+		goto end;
+	}
+
+	if (!policy_mgr_is_dbs_allowed_for_concurrency(mac_ctx->psoc,
+						       QDF_STA_MODE)) {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
+			  FL("DBS is not allowed for this concurrency combo"));
+		goto end;
+	}
+
+	if (!policy_mgr_is_hw_dbs_2x2_capable(mac_ctx->psoc) &&
+	    !policy_mgr_get_connection_count(mac_ctx->psoc)) {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
+			  FL("1x1 DBS HW with no prior connection"));
+		goto end;
+	}
+
+	if (csr_ll_is_list_empty(&bss_list->List, LL_ACCESS_NOLOCK)) {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+			  FL("bss_list->List is empty"));
+		qdf_mem_free(bss_list);
+		goto end;
+	}
+
+	next_element = csr_ll_peek_head(&bss_list->List, LL_ACCESS_NOLOCK);
+	while (next_element) {
+		scan_result = GET_BASE_ADDR(next_element,
+					    struct tag_csrscan_result,
+					    Link);
+		if (policy_mgr_is_hw_dbs_2x2_capable(mac_ctx->psoc)) {
+			if (WLAN_REG_IS_24GHZ_CH
+				(scan_result->Result.BssDescriptor.channelId)) {
+				channel_id =
+					scan_result->
+					Result.BssDescriptor.channelId;
+				break;
+			}
+		} else {
+			if (WLAN_REG_IS_24GHZ_CH
+				(scan_result->Result.BssDescriptor.channelId) &&
+			    policy_mgr_is_any_mode_active_on_band_along_with_session
+				(mac_ctx->psoc,
+				 session_id, POLICY_MGR_BAND_5)) {
+				channel_id =
+					scan_result->
+					Result.BssDescriptor.channelId;
+				break;
+			}
+			if (WLAN_REG_IS_5GHZ_CH
+				(scan_result->Result.BssDescriptor.channelId) &&
+			    policy_mgr_is_any_mode_active_on_band_along_with_session
+				(mac_ctx->psoc,
+				 session_id, POLICY_MGR_BAND_24)) {
+				channel_id =
+					scan_result->
+					Result.BssDescriptor.channelId;
+				break;
+			}
+		}
+		next_element = csr_ll_next(&bss_list->List, next_element,
+					   LL_ACCESS_NOLOCK);
+	}
+end:
+	return channel_id;
+}
+
 static enum wlan_auth_type csr_covert_auth_type_new(eCsrAuthType auth)
 {
 	switch (auth) {

+ 20 - 1
core/sme/src/csr/csr_inside_api.h

@@ -1095,5 +1095,24 @@ static inline void csr_update_session_he_cap(tpAniSirGlobal mac_ctx,
 {
 }
 #endif
-
+/**
+ * csr_get_channel_for_hw_mode_change() - This function to find
+ *                                       out if HW mode change
+ *                                       is needed for any of
+ *                                       the candidate AP which
+ *                                       STA could join
+ * @mac_ctx: mac context
+ * @result_handle: an object for the result.
+ * @session_id: STA session ID
+ *
+ * This function is written to find out for any bss from scan
+ * handle a HW mode change to DBS will be needed or not.
+ *
+ * Return: AP channel for which DBS HW mode will be needed. 0
+ * means no HW mode change is needed.
+ */
+uint8_t
+csr_get_channel_for_hw_mode_change(tpAniSirGlobal mac_ctx,
+				   tScanResultHandle result_handle,
+				   uint32_t session_id);
 #endif /* CSR_INSIDE_API_H__ */