Procházet zdrojové kódy

qcacld-3.0: Use Reassociation during BSS Transition

This is qcacld-2.0 to qcacld-3.0 propagation

The BSS transition request is handled by the supplicant.
The supplicant upon receiving the request will issue a
connect request to the driver with a hint of prev_bssid
telling the driver to perform a re-association.
Use this hint in the driver and initiate a re-association.
While doing the re-association, there is no need to do a
scan if the target AP is already present in the scan cache.
Optimize the re-association code to not do a scan if not
necessary in this particular case.

Change-Id: Idf1a7058009a8d2082bc1742dca1364cf59c405b
CRs-Fixed: 1010596
Varun Reddy Yeturu před 8 roky
rodič
revize
3e91dad283

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

@@ -1737,4 +1737,7 @@ static inline int wlan_hdd_nl_init(hdd_context_t *hdd_ctx)
 #endif
 QDF_STATUS hdd_sme_close_session_callback(void *pContext);
 
+int hdd_reassoc(hdd_adapter_t *adapter, const uint8_t *bssid,
+		const uint8_t channel, const handoff_src src);
+
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 41 - 0
core/hdd/src/wlan_hdd_cfg80211.c

@@ -10409,6 +10409,41 @@ disconnected:
 	return result;
 }
 
+/**
+ * wlan_hdd_reassoc_bssid_hint() - Start reassociation if bssid is present
+ * @adapter: Pointer to the HDD adapter
+ * @req: Pointer to the structure cfg_connect_params receieved from user space
+ *
+ * This function will start reassociation if bssid hint, channel hint and
+ * previous bssid parameters are present in the connect request
+ *
+ * Return: success if reassociation is happening
+ *         Error code if reassociation is not permitted or not happening
+ */
+#ifdef CFG80211_CONNECT_PREV_BSSID
+static int wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
+				struct cfg80211_connect_params *req)
+{
+	int status = -EPERM;
+	if (req->bssid_hint && req->channel_hint && req->prev_bssid) {
+		hddLog(VOS_TRACE_LEVEL_INFO,
+			FL("REASSOC Attempt on channel %d to "MAC_ADDRESS_STR),
+			req->channel_hint->hw_value,
+			MAC_ADDR_ARRAY(req->bssid_hint));
+		status  = hdd_reassoc(adapter, req->bssid_hint,
+				      req->channel_hint->hw_value,
+				      CONNECT_CMD_USERSPACE);
+	}
+	return status;
+}
+#else
+static int wlan_hdd_reassoc_bssid_hint(hdd_adapter_t *adapter,
+				       struct cfg80211_connect_params *req)
+{
+	return -EPERM;
+}
+#endif
+
 /**
  * __wlan_hdd_cfg80211_connect() - cfg80211 connect api
  * @wiphy: Pointer to wiphy
@@ -10464,6 +10499,11 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
 	status = wlan_hdd_validate_context(pHddCtx);
 	if (0 != status)
 		return status;
+
+	status = wlan_hdd_reassoc_bssid_hint(pAdapter, req);
+	if (0 == status)
+		return status;
+
 	if (req->channel) {
 		if (!cds_allow_concurrency(
 				cds_convert_device_mode_to_qdf_type(
@@ -10480,6 +10520,7 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
 			return -ECONNREFUSED;
 		}
 	}
+
 	wlan_hdd_disable_roaming(pAdapter);
 
 	/*Try disconnecting if already in connected state */

+ 6 - 6
core/hdd/src/wlan_hdd_ioctl.c

@@ -842,14 +842,14 @@ static int hdd_parse_reassoc_command_v1_data(const uint8_t *pValue,
  * @adapter:	Adapter upon which the command was received
  * @bssid:	BSSID with which to reassociate
  * @channel:	channel upon which to reassociate
+ * @src:        The source for the trigger of this action
  *
  * This function performs a userspace-directed reassoc operation
  *
  * Return: 0 for success non-zero for failure
  */
-static int
-hdd_reassoc(hdd_adapter_t *adapter, const uint8_t *bssid,
-	    const uint8_t channel)
+int hdd_reassoc(hdd_adapter_t *adapter, const uint8_t *bssid,
+		const uint8_t channel, const handoff_src src)
 {
 	hdd_station_ctx_t *pHddStaCtx;
 	int ret = 0;
@@ -895,7 +895,7 @@ hdd_reassoc(hdd_adapter_t *adapter, const uint8_t *bssid,
 		hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 
 		handoffInfo.channel = channel;
-		handoffInfo.src = REASSOC;
+		handoffInfo.src = src;
 		qdf_mem_copy(handoffInfo.bssid.bytes, bssid, QDF_MAC_ADDR_SIZE);
 		sme_handoff_request(hdd_ctx->hHal, adapter->sessionId,
 				    &handoffInfo);
@@ -931,7 +931,7 @@ static int hdd_parse_reassoc_v1(hdd_adapter_t *adapter, const char *command)
 	if (ret) {
 		hdd_err("Failed to parse reassoc command data");
 	} else {
-		ret = hdd_reassoc(adapter, bssid, channel);
+		ret = hdd_reassoc(adapter, bssid, channel, REASSOC);
 	}
 	return ret;
 }
@@ -961,7 +961,7 @@ static int hdd_parse_reassoc_v2(hdd_adapter_t *adapter, const char *command)
 		hdd_err("MAC address parsing failed");
 		ret = -EINVAL;
 	} else {
-		ret = hdd_reassoc(adapter, bssid, params.channel);
+		ret = hdd_reassoc(adapter, bssid, params.channel, REASSOC);
 	}
 	return ret;
 }

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

@@ -1570,7 +1570,8 @@ typedef void *tScanResultHandle;
 
 typedef enum {
 	REASSOC = 0,
-	FASTREASSOC = 1
+	FASTREASSOC = 1,
+	CONNECT_CMD_USERSPACE = 2,
 } handoff_src;
 
 typedef struct tagCsrHandoffRequest {

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

@@ -1422,4 +1422,9 @@ enum tQDF_ADAPTER_MODE csr_get_session_persona(tpAniSirGlobal pmac,
 void csr_roam_substate_change(tpAniSirGlobal pMac, eCsrRoamSubState NewSubstate,
 			      uint32_t sessionId);
 
+void csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx,
+		uint8_t sessionid, tScanResultHandle *scan_results_list);
+
+void csr_neighbor_roam_trigger_handoff(tpAniSirGlobal mac_ctx,
+					uint8_t session_id);
 #endif

+ 4 - 6
core/sme/src/csr/csr_host_scan_roam.c

@@ -142,10 +142,8 @@ QDF_STATUS csr_roam_issue_reassociate_cmd(tpAniSirGlobal pMac,
  * Return: void
  */
 
-static void
-csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx,
-		uint8_t sessionid,
-		tScanResultHandle *scan_results_list)
+void csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx,
+		uint8_t sessionid, tScanResultHandle *scan_results_list)
 {
 	tCsrScanResultInfo *scan_result;
 	tpCsrNeighborRoamControlInfo n_roam_info =
@@ -356,8 +354,8 @@ csr_neighbor_roam_process_scan_results(tpAniSirGlobal mac_ctx,
  *
  * Return: None
  */
-static void csr_neighbor_roam_trigger_handoff(tpAniSirGlobal mac_ctx,
-					      uint8_t session_id)
+void csr_neighbor_roam_trigger_handoff(tpAniSirGlobal mac_ctx,
+				      uint8_t session_id)
 {
 	if (csr_roam_is_fast_roam_enabled(mac_ctx, session_id))
 		csr_neighbor_roam_issue_preauth_req(mac_ctx, session_id);

+ 36 - 5
core/sme/src/csr/csr_neighbor_roam.c

@@ -371,6 +371,8 @@ csr_neighbor_roam_prepare_scan_profile_filter(tpAniSirGlobal pMac,
 	pScanFilter->scan_filter_for_roam = 1;
 	/* only for HDD requested handoff fill in the BSSID in the filter */
 	if (nbr_roam_info->uOsRequestedHandoff) {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG,
+			FL("OS Requested Handoff"));
 		pScanFilter->BSSIDs.numOfBSSIDs = 1;
 		pScanFilter->BSSIDs.bssid =
 			qdf_mem_malloc(sizeof(tSirMacAddr) *
@@ -1494,6 +1496,10 @@ QDF_STATUS csr_neighbor_roam_process_handoff_req(
 	tCsrRoamProfile *profile = NULL;
 	tCsrRoamSession *session = CSR_GET_SESSION(mac_ctx, session_id);
 	uint8_t i = 0;
+	uint8_t roam_now = 0;
+	uint8_t roamable_ap_count = 0;
+	tCsrScanResultFilter    scan_filter;
+	tScanResultHandle       scan_result;
 
 	if (NULL == session) {
 		sms_log(mac_ctx, LOGE, FL("session is NULL "));
@@ -1553,11 +1559,36 @@ QDF_STATUS csr_neighbor_roam_process_handoff_req(
 	profile->ChannelInfo.ChannelList[0] =
 		roam_ctrl_info->handoffReqInfo.channel;
 
-	/* do a SSID scan */
-	status =
-		csr_scan_for_ssid(mac_ctx, session_id, profile, roam_id, false);
-	if (!QDF_IS_STATUS_SUCCESS(status)) {
-		sms_log(mac_ctx, LOGE, FL("SSID scan failed"));
+	/*
+	 * For User space connect requests, the scan has already been done.
+	 * So, check if the BSS descriptor exists in the scan cache and
+	 * proceed with the handoff instead of a redundant scan again.
+	 */
+	if (roam_ctrl_info->handoffReqInfo.src == CONNECT_CMD_USERSPACE) {
+		sms_log(mac_ctx, LOG1,
+			FL("Connect cmd with bssid within same ESS"));
+		status = csr_neighbor_roam_prepare_scan_profile_filter(mac_ctx,
+								&scan_filter,
+								session_id);
+		sms_log(mac_ctx, LOG1, FL("Filter creation status = %d"),
+			status);
+		status = csr_scan_get_result(mac_ctx, &scan_filter,
+					     &scan_result);
+		csr_neighbor_roam_process_scan_results(mac_ctx, session_id,
+							&scan_result);
+		roamable_ap_count = csr_ll_count(
+					&roam_ctrl_info->roamableAPList);
+		csr_free_scan_filter(mac_ctx, &scan_filter);
+		sms_log(mac_ctx, LOG1, FL("roam_now=%d, roamable_ap_count=%d"),
+			roam_now, roamable_ap_count);
+	}
+	if (roam_now && roamable_ap_count) {
+		csr_neighbor_roam_trigger_handoff(mac_ctx, session_id);
+	} else {
+		status = csr_scan_for_ssid(mac_ctx, session_id, profile,
+					   roam_id, false);
+		if (status != QDF_STATUS_SUCCESS)
+			sms_log(mac_ctx, LOGE, FL("SSID scan failed"));
 	}
 
 end: