Ver código fonte

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
Krunal Soni 8 anos atrás
pai
commit
b37bb35ad3

+ 3 - 2
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:

+ 36 - 17
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;
 }
 

+ 8 - 2
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);

+ 2 - 1
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;
 

+ 20 - 29
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;