diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 22f7e0dde3e8..a052fcd476d1 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/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 diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index e25784752e4a..366c2b9ce75e 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/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 diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index ecc0cffe1854..5438f21eb65d 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/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, diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 4fc656726b43..a918aadc49f7 100644 --- a/core/sme/inc/csr_api.h +++ b/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; /*---------------------------------------------------------------------------- diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index a07356174a9a..ba05de447f5c 100644 --- a/core/sme/inc/sme_api.h +++ b/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); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index fa40dd58406f..3c08777f594b 100644 --- a/core/sme/src/common/sme_api.c +++ b/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 diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 76b0c44c4ef2..ecf7939f93f2 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/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 diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index ee6488c5884b..9bce575d6b5e 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/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,