Browse Source

qcacld-3.0: If BSS is unreachable remove it from scan cache

qcacld-2.0 to qcacld-3.0 propagation

If BSS is present in kernel and driver scan cache, supplicant
tries to connect to the BSS multiple time even if the BSS is
unreachable. Due to multiple failures to connect supplicant
disable the network.

To avoid this, remove the BSS from scan cache:
 - If connect fails due to BSS unreachable i.e. probe
   resp/auth/assoc timeout and scan for ssid failure.
 - If disconnect is due to Link lost.

Change-Id: I3263dd02691000d83d4aef61c75b72d78c28f582
CRS-Fixed: 1039104
Abhishek Singh 8 years ago
parent
commit
c994160fb0

+ 28 - 12
core/hdd/src/wlan_hdd_assoc.c

@@ -1722,6 +1722,15 @@ static QDF_STATUS hdd_dis_connect_handler(hdd_adapter_t *pAdapter,
 		}
 	} else {
 		sta_id = pHddStaCtx->conn_info.staId[0];
+
+		/* clear scan cache for Link Lost */
+		if (pRoamInfo && !pRoamInfo->reasonCode &&
+		   (eCSR_ROAM_RESULT_DEAUTH_IND == roamResult)) {
+			wlan_hdd_cfg80211_update_bss_list(pAdapter,
+				pHddStaCtx->conn_info.bssId.bytes);
+			sme_remove_bssid_from_scan_list(pHddCtx->hHal,
+			pHddStaCtx->conn_info.bssId.bytes);
+		}
 		/* We should clear all sta register with TL,
 		 * for now, only one.
 		 */
@@ -2835,6 +2844,25 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
 				 " result:%d and Status:%d",
 				 MAC_ADDR_ARRAY(pWextState->req_bssId.bytes),
 				 roamResult, roamStatus);
+
+		if ((eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE == roamResult) ||
+		   (pRoamInfo &&
+		   ((eSIR_SME_JOIN_TIMEOUT_RESULT_CODE ==
+					pRoamInfo->statusCode) ||
+		   (eSIR_SME_AUTH_TIMEOUT_RESULT_CODE ==
+					pRoamInfo->statusCode) ||
+		   (eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE ==
+					pRoamInfo->statusCode)))) {
+			wlan_hdd_cfg80211_update_bss_list(pAdapter,
+				pRoamInfo ?
+				pRoamInfo->bssid.bytes :
+				pWextState->req_bssId.bytes);
+			sme_remove_bssid_from_scan_list(pHddCtx->hHal,
+				pRoamInfo ?
+				pRoamInfo->bssid.bytes :
+				pWextState->req_bssId.bytes);
+		}
+
 		/*
 		 * CR465478: Only send up a connection failure result when CSR
 		 * has completed operation - with a ASSOCIATION_FAILURE status.
@@ -2928,18 +2956,6 @@ static QDF_STATUS hdd_association_completion_handler(hdd_adapter_t *pAdapter,
 						GFP_KERNEL);
 		}
 
-		if (pRoamInfo) {
-			if ((eSIR_SME_JOIN_TIMEOUT_RESULT_CODE ==
-			     pRoamInfo->statusCode)
-			    || (eSIR_SME_AUTH_TIMEOUT_RESULT_CODE ==
-				pRoamInfo->statusCode)
-			    || (eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE ==
-				pRoamInfo->statusCode)) {
-				wlan_hdd_cfg80211_update_bss_list(pAdapter,
-								  pRoamInfo);
-			}
-		}
-
 		/*
 		 * Set connection state to eConnectionState_NotConnected only
 		 * when CSR has completed operation - with a

+ 48 - 54
core/hdd/src/wlan_hdd_cfg80211.c

@@ -9720,76 +9720,70 @@ static int wlan_hdd_cfg80211_set_default_key(struct wiphy *wiphy,
 	return ret;
 }
 
-/**
- * wlan_hdd_cfg80211_update_bss_list() - update bss list to NL80211
- * @pAdapter: Pointer to adapter
- * @pRoamInfo: Pointer to roam info
+/*
+ * wlan_hdd_cfg80211_get_bss :to get the bss from kernel cache.
+ * @wiphy: wiphy pointer
+ * @channel: channel of the BSS
+ * @bssid: Bssid of BSS
+ * @ssid: Ssid of the BSS
+ * @ssid_len: ssid length
  *
- * Return: struct cfg80211_bss pointer
+ * Return: bss found in kernel cache
  */
-struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(hdd_adapter_t *pAdapter,
-						       tCsrRoamInfo *pRoamInfo)
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
+struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
+	struct ieee80211_channel *channel, const u8 *bssid,
+	const u8 *ssid, size_t ssid_len)
+{
+	return cfg80211_get_bss(wiphy, channel, bssid,
+			ssid,
+			ssid_len,
+			WLAN_CAPABILITY_ESS,
+			WLAN_CAPABILITY_ESS);
+}
+#else
+struct cfg80211_bss *wlan_hdd_cfg80211_get_bss(struct wiphy *wiphy,
+	struct ieee80211_channel *channel, const u8 *bssid,
+	const u8 *ssid, size_t ssid_len)
+{
+	return cfg80211_get_bss(wiphy, channel, bssid,
+				ssid,
+				ssid_len,
+				IEEE80211_BSS_TYPE_ESS,
+				IEEE80211_PRIVACY_ANY);
+}
+#endif
+
+
+/*
+ * wlan_hdd_cfg80211_update_bss_list :to inform nl80211
+ * interface that BSS might have been lost.
+ * @pAdapter: adaptor
+ * @bssid: bssid which might have been lost
+ *
+ * Return: bss which is unlinked from kernel cache
+ */
+struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(
+	hdd_adapter_t *pAdapter, tSirMacAddr bssid)
 {
 	struct net_device *dev = pAdapter->dev;
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	struct wiphy *wiphy = wdev->wiphy;
-	tSirBssDescription *pBssDesc = pRoamInfo->pBssDesc;
-	int chan_no;
-	unsigned int freq;
-	struct ieee80211_channel *chan;
 	struct cfg80211_bss *bss = NULL;
 
-	ENTER();
-
-	if (NULL == pBssDesc) {
-		hdd_err("pBssDesc is NULL");
-		return bss;
-	}
-
-	if (NULL == pRoamInfo->pProfile) {
-		hdd_err("Roam profile is NULL");
-		return bss;
-	}
-
-	chan_no = pBssDesc->channelId;
-
-	if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_ghz)) {
-		freq =
-			ieee80211_channel_to_frequency(chan_no,
-						       IEEE80211_BAND_2GHZ);
-	} else {
-		freq =
-			ieee80211_channel_to_frequency(chan_no,
-						       IEEE80211_BAND_5GHZ);
-	}
-
-	chan = __ieee80211_get_channel(wiphy, freq);
-
-	if (!chan) {
-		hdd_err("chan pointer is NULL");
-		return NULL;
-	}
-
-	bss = cfg80211_get_bss(wiphy, chan, pBssDesc->bssId,
-			       &pRoamInfo->pProfile->SSIDs.SSIDList->SSID.
-			       ssId[0],
-			       pRoamInfo->pProfile->SSIDs.SSIDList->SSID.length,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)) && !defined(WITH_BACKPORTS)
-			       WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
-#else
-			       IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
-#endif
+	bss = wlan_hdd_cfg80211_get_bss(wiphy, NULL, bssid,
+			NULL, 0);
 	if (bss == NULL) {
 		hdd_err("BSS not present");
 	} else {
-		hdd_notice("cfg80211_unlink_bss called for BSSID "
-				MAC_ADDRESS_STR,
-		       MAC_ADDR_ARRAY(pBssDesc->bssId));
+		hdd_info("cfg80211_unlink_bss called for BSSID "
+			MAC_ADDRESS_STR, MAC_ADDR_ARRAY(bssid));
 		cfg80211_unlink_bss(wiphy, bss);
 	}
 	return bss;
 }
 
+
 /**
  * wlan_hdd_cfg80211_inform_bss_frame() - inform bss details to NL80211
  * @pAdapter: Pointer to adapter

+ 1 - 1
core/hdd/src/wlan_hdd_cfg80211.h

@@ -2916,7 +2916,7 @@ void hdd_rssi_threshold_breached(void *hddctx,
 				 struct rssi_breach_event *data);
 
 struct cfg80211_bss *wlan_hdd_cfg80211_update_bss_list(hdd_adapter_t *pAdapter,
-						       tCsrRoamInfo *pRoamInfo);
+						tSirMacAddr bssid);
 
 int wlan_hdd_cfg80211_update_bss(struct wiphy *wiphy,
 						hdd_adapter_t *pAdapter,

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

@@ -619,6 +619,8 @@ typedef enum {
 	eCSR_ROAM_RESULT_NDP_END_RSP,
 	eCSR_ROAM_RESULT_NDP_PEER_DEPARTED_IND,
 	eCSR_ROAM_RESULT_NDP_END_IND,
+	/* If Scan for SSID failed to found proper BSS */
+	eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE,
 } eCsrRoamResult;
 
 /*----------------------------------------------------------------------------

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

@@ -1151,6 +1151,9 @@ void sme_update_vdev_type_nss(tHalHandle hal, uint8_t max_supp_nss,
 void sme_register_p2p_lo_event(tHalHandle hHal, void *context,
 					p2p_lo_callback callback);
 
+QDF_STATUS sme_remove_bssid_from_scan_list(tHalHandle hal,
+	tSirMacAddr bssid);
+
 QDF_STATUS sme_process_mac_pwr_dbg_cmd(tHalHandle hal, uint32_t session_id,
 				       struct sir_mac_pwr_dbg_cmd*
 				       dbg_args);

+ 25 - 0
core/sme/src/common/sme_api.c

@@ -3226,6 +3226,31 @@ QDF_STATUS sme_close(tHalHandle hHal)
 	return status;
 }
 
+/**
+ * sme_remove_bssid_from_scan_list() - wrapper to remove the bssid from
+ * scan list
+ * @hal: hal context.
+ * @bssid: bssid to be removed
+ *
+ * This function remove the given bssid from scan list.
+ *
+ * Return: QDF status.
+ */
+QDF_STATUS sme_remove_bssid_from_scan_list(tHalHandle hal,
+	tSirMacAddr bssid)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+
+	status = sme_acquire_global_lock(&mac_ctx->sme);
+	if (QDF_IS_STATUS_SUCCESS(status)) {
+		csr_remove_bssid_from_scan_list(mac_ctx, bssid);
+		sme_release_global_lock(&mac_ctx->sme);
+	}
+
+	return status;
+}
+
 /**
  * sme_scan_request() - wrapper function to Request a 11d or full scan from CSR.
  * @hal:          hal global context

+ 41 - 3
core/sme/src/csr/csr_api_scan.c

@@ -1218,7 +1218,7 @@ QDF_STATUS csr_scan_handle_search_for_ssid(tpAniSirGlobal pMac,
 		csr_roam_call_callback(pMac, sessionId, NULL,
 				       pCommand->u.scanCmd.roamId,
 				       eCSR_ROAM_ASSOCIATION_FAILURE,
-				       eCSR_ROAM_RESULT_FAILURE);
+				       eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE);
 	}
 	if (pScanFilter) {
 		csr_free_scan_filter(pMac, pScanFilter);
@@ -1300,12 +1300,12 @@ QDF_STATUS csr_scan_handle_search_for_ssid_failure(tpAniSirGlobal pMac,
 		csr_roam_call_callback(pMac, sessionId, pRoamInfo,
 				       pCommand->u.scanCmd.roamId,
 				       eCSR_ROAM_ASSOCIATION_COMPLETION,
-				       eCSR_ROAM_RESULT_FAILURE);
+				       eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE);
 	} else {
 		csr_roam_call_callback(pMac, sessionId, NULL,
 				       pCommand->u.scanCmd.roamId,
 				       eCSR_ROAM_ASSOCIATION_FAILURE,
-				       eCSR_ROAM_RESULT_FAILURE);
+				       eCSR_ROAM_RESULT_SCAN_FOR_SSID_FAILURE);
 	}
 roam_completion:
 	csr_roam_completion(pMac, sessionId, NULL, pCommand, roam_result,
@@ -1327,6 +1327,44 @@ QDF_STATUS csr_scan_result_purge(tpAniSirGlobal pMac,
 	return status;
 }
 
+/**
+ * csr_remove_bssid_from_scan_list() - remove the bssid from
+ * scan list
+ * @mac_tx: mac context.
+ * @bssid: bssid to be removed
+ *
+ * This function remove the given bssid from scan list.
+ *
+ * Return: void.
+ */
+void csr_remove_bssid_from_scan_list(tpAniSirGlobal mac_ctx,
+			tSirMacAddr bssid)
+{
+	tListElem *entry, *free_elem;
+	tCsrScanResult *bss_desc;
+	tDblLinkList *list = &mac_ctx->scan.scanResultList;
+
+	csr_ll_lock(list);
+	entry = csr_ll_peek_head(list, LL_ACCESS_NOLOCK);
+	while (entry != NULL) {
+		bss_desc = GET_BASE_ADDR(entry, tCsrScanResult, Link);
+		if (!qdf_mem_cmp(bss_desc->Result.BssDescriptor.bssId,
+		   bssid, sizeof(tSirMacAddr))) {
+			free_elem = entry;
+			entry = csr_ll_next(list, entry, LL_ACCESS_NOLOCK);
+			csr_ll_remove_entry(list, free_elem, LL_ACCESS_NOLOCK);
+			csr_free_scan_result_entry(mac_ctx, bss_desc);
+			sms_log(mac_ctx, LOGW, FL("Removed BSS entry:%pM"),
+				bssid);
+			continue;
+		}
+
+		entry = csr_ll_next(list, entry, LL_ACCESS_NOLOCK);
+	}
+
+	csr_ll_unlock(list);
+}
+
 /**
  * csr_derive_prefer_value_from_rssi() - to derive prefer value
  * @mac_ctx: Global MAC Context

+ 3 - 0
core/sme/src/csr/csr_inside_api.h

@@ -1074,6 +1074,9 @@ void csr_roam_prepare_bss_params(tpAniSirGlobal mac_ctx, uint32_t session_id,
 		tCsrRoamProfile *profile, tSirBssDescription *bss_desc,
 		tBssConfigParam *bss_cfg, tDot11fBeaconIEs *ies);
 
+void csr_remove_bssid_from_scan_list(tpAniSirGlobal mac_ctx,
+	tSirMacAddr bssid);
+
 QDF_STATUS csr_roam_set_bss_config_cfg(tpAniSirGlobal mac_ctx,
 		uint32_t session_id,
 		tCsrRoamProfile *profile, tSirBssDescription *bss_desc,