From 3e91dad283be0cce184b6df449866f40de5e90d7 Mon Sep 17 00:00:00 2001 From: Varun Reddy Yeturu Date: Mon, 18 Jul 2016 15:58:47 -0700 Subject: [PATCH] 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 --- core/hdd/inc/wlan_hdd_main.h | 3 ++ core/hdd/src/wlan_hdd_cfg80211.c | 41 +++++++++++++++++++++++++++ core/hdd/src/wlan_hdd_ioctl.c | 12 ++++---- core/sme/inc/csr_api.h | 3 +- core/sme/inc/csr_internal.h | 5 ++++ core/sme/src/csr/csr_host_scan_roam.c | 10 +++---- core/sme/src/csr/csr_neighbor_roam.c | 41 +++++++++++++++++++++++---- 7 files changed, 97 insertions(+), 18 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index bc5dd3d002e9..10318736dca5 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/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) */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index a26d14894d0e..78010a8534a9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/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 */ diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c index c7bbcda6f172..384783976fb4 100644 --- a/core/hdd/src/wlan_hdd_ioctl.c +++ b/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; } diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index 266e5a0337bf..2c22a81ea407 100644 --- a/core/sme/inc/csr_api.h +++ b/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 { diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 8c3a658bebef..9fff2c3dc61e 100644 --- a/core/sme/inc/csr_internal.h +++ b/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 diff --git a/core/sme/src/csr/csr_host_scan_roam.c b/core/sme/src/csr/csr_host_scan_roam.c index 4e8db71aecc4..9f56f7c303fe 100644 --- a/core/sme/src/csr/csr_host_scan_roam.c +++ b/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); diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 64914e4577d5..4884cfd2cc4b 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/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: