From b37bb35ad3f90355e776dd4489f1f9dd1ad60f26 Mon Sep 17 00:00:00 2001 From: Krunal Soni Date: Tue, 20 Dec 2016 14:12:21 -0800 Subject: [PATCH] qcacld-3.0: Fix to handle error conditions when pre-cac adapter fails Currently, driver has following errors while handling pre-cac adapter 1) If SAP start operation fails in upper mac layers like PE or WMA then without checking status of operation, SAP/HDD layer notifies policy manager to add the connection to its table. 2) Driver is doing hardware mode change first and then it does pre-cac adapter open operation followed by starting the bss. If pre-cac adapter open operation fails then nobody is reverting original hardware mode change. 3) While doing CAC wait, If radar gets detected then driver is not releasing interfaces mac address due to which sub sequent adapter doesn't get valid mac address as driver has limited pool of mac addresses. 4) LIM layer is populating some garbage SME session id as it is releasing the memory before it access in case of any failure. Add safety checks to avoid all above conditions. CRs-Fixed: 1103673 Change-Id: Ie94af7783527e6c55490801b52898ec0c3208503 --- core/cds/src/cds_concurrency.c | 5 +- core/hdd/src/wlan_hdd_cfg80211.c | 53 +++++++++++++------ core/hdd/src/wlan_hdd_hostapd.c | 10 +++- core/hdd/src/wlan_hdd_main.c | 3 +- .../src/pe/lim/lim_process_sme_req_messages.c | 49 +++++++---------- 5 files changed, 69 insertions(+), 51 deletions(-) diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index 270bb38f59..9754320de3 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -6491,8 +6491,9 @@ void cds_restart_sap(hdd_adapter_t *ap_adapter) } cds_err("SAP Start Success"); set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); - cds_incr_active_session(ap_adapter->device_mode, - ap_adapter->sessionId); + if (hostapd_state->bssState == BSS_START) + cds_incr_active_session(ap_adapter->device_mode, + ap_adapter->sessionId); hostapd_state->bCommit = true; } end: diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 321d9466db..864171e5ef 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -6830,7 +6830,7 @@ static int wlan_hdd_validate_and_get_pre_cac_ch(hdd_context_t *hdd_ctx, */ int wlan_hdd_request_pre_cac(uint8_t channel) { - uint8_t pre_cac_chan = 0; + uint8_t pre_cac_chan = 0, *mac_addr; hdd_context_t *hdd_ctx; int ret; hdd_adapter_t *ap_adapter, *pre_cac_adapter; @@ -6890,23 +6890,19 @@ int wlan_hdd_request_pre_cac(uint8_t channel) return -EINVAL; } + mac_addr = wlan_hdd_get_intf_addr(hdd_ctx); + if (!mac_addr) { + hdd_err("can't add virtual intf: Not getting valid mac addr"); + return -EINVAL; + } + hdd_info("channel:%d", channel); ret = wlan_hdd_validate_and_get_pre_cac_ch(hdd_ctx, ap_adapter, channel, &pre_cac_chan); - if (ret != 0) - return ret; - - /* Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this - * connection update should result in DBS mode - */ - status = cds_update_and_wait_for_connection_update( - ap_adapter->sessionId, - pre_cac_chan, - SIR_UPDATE_REASON_PRE_CAC); - if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("error in moving to DBS mode"); - return -EINVAL; + if (ret != 0) { + hdd_err("can't validate pre-cac channel"); + goto release_intf_addr_and_return_failure; } hdd_debug("starting pre cac SAP adapter"); @@ -6929,11 +6925,10 @@ int wlan_hdd_request_pre_cac(uint8_t channel) * from user space. */ pre_cac_adapter = hdd_open_adapter(hdd_ctx, QDF_SAP_MODE, "precac%d", - wlan_hdd_get_intf_addr(hdd_ctx), - NET_NAME_UNKNOWN, true); + mac_addr, NET_NAME_UNKNOWN, true); if (!pre_cac_adapter) { hdd_err("error opening the pre cac adapter"); - return -EINVAL; + goto release_intf_addr_and_return_failure; } /* @@ -7001,6 +6996,22 @@ int wlan_hdd_request_pre_cac(uint8_t channel) hdd_debug("orig width:%d channel_type:%d freq:%d", ap_adapter->sessionCtx.ap.sapConfig.ch_width_orig, channel_type, freq); + /* + * Doing update after opening and starting pre-cac adapter will make + * sure that driver won't do hardware mode change if there are any + * initial hick-ups or issues in pre-cac adapter's configuration. + * Since current SAP is in 2.4GHz and pre CAC channel is in 5GHz, this + * connection update should result in DBS mode + */ + status = cds_update_and_wait_for_connection_update( + ap_adapter->sessionId, + pre_cac_chan, + SIR_UPDATE_REASON_PRE_CAC); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("error in moving to DBS mode"); + goto stop_close_pre_cac_adapter; + } + ret = wlan_hdd_set_channel(wiphy, dev, &chandef, channel_type); if (0 != ret) { @@ -7044,6 +7055,14 @@ stop_close_pre_cac_adapter: pre_cac_adapter->sessionCtx.ap.beacon = NULL; close_pre_cac_adapter: hdd_close_adapter(hdd_ctx, pre_cac_adapter, false); +release_intf_addr_and_return_failure: + /* + * Release the interface address as the adapter + * failed to start, if you don't release then next + * adapter which is trying to come wouldn't get valid + * mac address. Remember we have limited pool of mac addresses + */ + wlan_hdd_release_intf_addr(hdd_ctx, mac_addr); return -EINVAL; } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index ad78765077..76a062cf03 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -901,6 +901,8 @@ void wlan_hdd_sap_pre_cac_failure(void *data) } cds_ssr_protect(__func__); + wlan_hdd_release_intf_addr(hdd_ctx, + pHostapdAdapter->macAddressCurrent.bytes); hdd_stop_adapter(hdd_ctx, pHostapdAdapter, true); hdd_close_adapter(hdd_ctx, pHostapdAdapter, false); cds_ssr_unprotect(__func__); @@ -1130,6 +1132,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, * wait till 10 secs and no other connection will * go through before that. */ + pHostapdState->bssState = BSS_STOP; qdf_event_set(&pHostapdState->qdf_event); goto stopbss; } else { @@ -2088,6 +2091,8 @@ stopbss: we_custom_event_generic = we_custom_event; wireless_send_event(dev, we_event, &wrqu, (char *)we_custom_event_generic); + cds_decr_session_set_pcl(pHostapdAdapter->device_mode, + pHostapdAdapter->sessionId); cds_dump_concurrency_info(); /* Send SCC/MCC Switching event to IPA */ hdd_ipa_send_mcc_scc_msg(pHddCtx, pHddCtx->mcc_mode); @@ -7648,8 +7653,9 @@ int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); /* Initialize WMM configuation */ hdd_wmm_init(pHostapdAdapter); - cds_incr_active_session(pHostapdAdapter->device_mode, - pHostapdAdapter->sessionId); + if (pHostapdState->bssState == BSS_START) + cds_incr_active_session(pHostapdAdapter->device_mode, + pHostapdAdapter->sessionId); #ifdef DHCP_SERVER_OFFLOAD if (iniConfig->enableDHCPServerOffload) wlan_hdd_set_dhcp_server_offload(pHostapdAdapter); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 3766da88c9..b5ec1aa5b9 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -8984,7 +8984,8 @@ void wlan_hdd_start_sap(hdd_adapter_t *ap_adapter) } hdd_info("SAP Start Success"); set_bit(SOFTAP_BSS_STARTED, &ap_adapter->event_flags); - cds_incr_active_session(ap_adapter->device_mode, + if (hostapd_state->bssState == BSS_START) + cds_incr_active_session(ap_adapter->device_mode, ap_adapter->sessionId); hostapd_state->bCommit = true; diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 4d68a0f13b..a153139305 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -637,8 +637,8 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) uint32_t auto_gen_bssid = false; uint8_t session_id; tpPESession session = NULL; - uint8_t sme_session_id = 0; - uint16_t sme_transaction_id = 0; + uint8_t sme_session_id = 0xFF; + uint16_t sme_transaction_id = 0xFF; uint32_t chanwidth; struct vdev_type_nss *vdev_type_nss; tSirRetStatus cfg_get_wmi_dfs_master_param = eSIR_SUCCESS; @@ -654,26 +654,21 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) #endif /* FEATURE_WLAN_DIAG_SUPPORT */ lim_log(mac_ctx, LOG1, FL("Received START_BSS_REQ")); + size = sizeof(tSirSmeStartBssReq); + sme_start_bss_req = qdf_mem_malloc(size); + if (NULL == sme_start_bss_req) { + lim_log(mac_ctx, LOGE, + FL("Allocate Memory fail for LimStartBssReq")); + /* Send failure response to host */ + ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; + goto free; + } + qdf_mem_copy(sme_start_bss_req, msg_buf, sizeof(tSirSmeStartBssReq)); + sme_session_id = sme_start_bss_req->sessionId; + sme_transaction_id = sme_start_bss_req->transactionId; - /* - * Global Sme state and mlm states are not defined yet, - * for BT-AMP Suppoprt . TO BE DONE - */ if ((mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) || (mac_ctx->lim.gLimSmeState == eLIM_SME_IDLE_STATE)) { - size = sizeof(tSirSmeStartBssReq); - - sme_start_bss_req = qdf_mem_malloc(size); - if (NULL == sme_start_bss_req) { - lim_log(mac_ctx, LOGE, - FL("Allocate Memory fail for LimStartBssReq")); - /* Send failure response to host */ - ret_code = eSIR_SME_RESOURCES_UNAVAILABLE; - goto end; - } - - qdf_mem_copy(sme_start_bss_req, msg_buf, - sizeof(tSirSmeStartBssReq)); if (!lim_is_sme_start_bss_req_valid(mac_ctx, sme_start_bss_req)) { lim_log(mac_ctx, LOGW, @@ -1141,22 +1136,18 @@ __lim_handle_sme_start_bss_request(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) FL("Received unexpected START_BSS_REQ, in state %X"), mac_ctx->lim.gLimSmeState); ret_code = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; - goto end; + goto free; } /* if (mac_ctx->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) */ free: if ((session != NULL) && - (session->pLimStartBssReq == sme_start_bss_req)) { + (session->pLimStartBssReq == sme_start_bss_req)) { session->pLimStartBssReq = NULL; } - qdf_mem_free(sme_start_bss_req); - qdf_mem_free(mlm_start_req); - -end: - if (sme_start_bss_req != NULL) { - sme_session_id = sme_start_bss_req->sessionId; - sme_transaction_id = sme_start_bss_req->transactionId; - } + if (NULL != sme_start_bss_req) + qdf_mem_free(sme_start_bss_req); + if (NULL != mlm_start_req) + qdf_mem_free(mlm_start_req); if (NULL != session) { pe_delete_session(mac_ctx, session); session = NULL;