Browse Source

qcacld-3.0: Fix error handling in eWNI_SME_ADD_STA_SELF_RSP

When peer creation fails in wma_create_peer, vdev delete is sent
to the fw and then eWNI_SME_ADD_STA_SELF_RSP is sent to sme.
Here three error cases needs to be handled:
1. The vdev deletion has happened, but the cdp_detach_peer is
not done. So the data path peer remains. Also the vdev_active
flag that was set after vdev creation was not unset.
2. The eWNI_SME_ADD_STA_SELF_RSP msg handler
csr_process_add_sta_session_rsp invokes csr_roam_session_opened
which signals HDD that vdev is created successfully and hdd
calls hdd_vdev_ready and vdev related parameter set commands are
sent to FW for the deleted vdev.
3. Vdev delete is not sent for objmgr peer creation failure in
case of VDEV_TYPE_STA and release vdev object ref count.

Add cdp_vdev_detach() calls during error case and set the
vdev_active flag to false. Handle releasing vdev object ref
count in all needed error case flows.
Propagate the error in wma_vdev_attach() through
csr_roam_session_opened() to HDD and abort the vdev create.

Change-Id: Iec97122d011098fae7ae2a59864fbe8ca8a0980e
CRs-Fixed: 2322212
Pragaspathi Thilagaraj 6 years ago
parent
commit
3551caa95b

+ 2 - 1
core/hdd/inc/wlan_hdd_main.h

@@ -2742,7 +2742,8 @@ static inline int wlan_hdd_nl_init(struct hdd_context *hdd_ctx)
 	return nl_srv_init(hdd_ctx->wiphy);
 }
 #endif
-QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id);
+QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id,
+					 QDF_STATUS qdf_status);
 QDF_STATUS hdd_sme_close_session_callback(uint8_t session_id);
 
 int hdd_reassoc(struct hdd_adapter *adapter, const uint8_t *bssid,

+ 12 - 2
core/hdd/src/wlan_hdd_main.c

@@ -3913,7 +3913,8 @@ static QDF_STATUS hdd_register_interface(struct hdd_adapter *adapter, bool rtnl_
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id)
+QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id,
+					 QDF_STATUS qdf_status)
 {
 	struct hdd_adapter *adapter;
 	struct hdd_context *hdd_ctx;
@@ -3929,7 +3930,10 @@ QDF_STATUS hdd_sme_open_session_callback(uint8_t session_id)
 		hdd_err("NULL adapter for %d", session_id);
 		return QDF_STATUS_E_INVAL;
 	}
-	set_bit(SME_SESSION_OPENED, &adapter->event_flags);
+
+	if (qdf_status == QDF_STATUS_SUCCESS)
+		set_bit(SME_SESSION_OPENED, &adapter->event_flags);
+
 	qdf_event_set(&adapter->qdf_session_open_event);
 	hdd_debug("session %d opened", adapter->session_id);
 
@@ -4152,6 +4156,12 @@ int hdd_vdev_create(struct hdd_adapter *adapter,
 		goto hdd_vdev_destroy_procedure;
 	}
 
+	if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
+		hdd_err("Session failed to open due to vdev create failure");
+		errno = -EINVAL;
+		goto objmgr_vdev_destroy_procedure;
+	}
+
 	/* firmware ready for component communication, raise vdev_ready event */
 	errno = hdd_vdev_ready(adapter);
 	if (errno) {

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

@@ -1599,7 +1599,8 @@ typedef QDF_STATUS (*csr_roam_complete_cb)(void *context,
 					   uint32_t roam_id,
 					   eRoamCmdStatus roam_status,
 					   eCsrRoamResult roam_result);
-typedef QDF_STATUS (*csr_session_open_cb)(uint8_t session_id);
+typedef QDF_STATUS (*csr_session_open_cb)(uint8_t session_id,
+					  QDF_STATUS qdf_status);
 typedef QDF_STATUS (*csr_session_close_cb)(uint8_t session_id);
 
 #define CSR_IS_START_IBSS(pProfile) (eCSR_BSS_TYPE_START_IBSS == \

+ 40 - 26
core/sme/src/csr/csr_api_roam.c

@@ -4071,7 +4071,7 @@ QDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId,
 				  uint32_t roamId,
 				  eRoamCmdStatus u1, eCsrRoamResult u2)
 {
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	QDF_STATUS ret, status = QDF_STATUS_SUCCESS;
 #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR
 
 	WLAN_HOST_DIAG_EVENT_DEF(connectionStatus,
@@ -4147,10 +4147,12 @@ QDF_STATUS csr_roam_call_callback(tpAniSirGlobal pMac, uint32_t sessionId,
 		   && (u2 == eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS)) {
 		pSession->connectedProfile.operationChannel =
 			roam_info->channelChangeRespEvent->newChannelNumber;
-	} else if ((u1 == eCSR_ROAM_SESSION_OPENED) &&
-			(u2 == eCSR_ROAM_RESULT_NONE)) {
+	} else if (u1 == eCSR_ROAM_SESSION_OPENED) {
+		ret = (u2 == eCSR_ROAM_RESULT_SUCCESS) ?
+		      QDF_STATUS_SUCCESS : QDF_STATUS_E_FAILURE;
+
 		if (pSession->session_open_cb)
-			pSession->session_open_cb(sessionId);
+			pSession->session_open_cb(sessionId, ret);
 		else
 			sme_err("session_open_cb is not registered");
 	}
@@ -16943,16 +16945,23 @@ QDF_STATUS csr_reassoc(tpAniSirGlobal pMac, uint32_t sessionId,
 }
 
 static QDF_STATUS csr_roam_session_opened(tpAniSirGlobal pMac,
+					  QDF_STATUS qdf_status,
 					  uint32_t sessionId)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	struct csr_roam_info roamInfo;
+	struct csr_roam_info roam_info;
 
-	qdf_mem_set(&roamInfo, sizeof(struct csr_roam_info), 0);
-	status = csr_roam_call_callback(pMac, sessionId, &roamInfo, 0,
-					eCSR_ROAM_SESSION_OPENED,
-					eCSR_ROAM_RESULT_NONE);
+	qdf_mem_set(&roam_info, sizeof(struct csr_roam_info), 0);
 
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		status = csr_roam_call_callback(pMac, sessionId, &roam_info, 0,
+						eCSR_ROAM_SESSION_OPENED,
+						eCSR_ROAM_RESULT_FAILURE);
+	} else {
+		status = csr_roam_call_callback(pMac, sessionId, &roam_info, 0,
+						eCSR_ROAM_SESSION_OPENED,
+						eCSR_ROAM_RESULT_SUCCESS);
+	}
 	return status;
 }
 
@@ -16969,26 +16978,31 @@ QDF_STATUS csr_process_add_sta_session_rsp(tpAniSirGlobal pMac, uint8_t *pMsg)
 	rsp = (struct add_sta_self_params *) pMsg;
 	sme_debug("Add Sta self rsp status = %d", rsp->status);
 
-	if (QDF_STATUS_SUCCESS == rsp->status &&
-		(WMI_VDEV_TYPE_STA == rsp->type ||
-		(WMI_VDEV_TYPE_AP == rsp->type &&
-		 WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == rsp->sub_type))) {
-		sme_debug("send SET IE msg to PE");
-		msg = qdf_mem_malloc(sizeof(*msg));
-		if (NULL == msg) {
-			sme_err("Memory allocation failed");
-			return QDF_STATUS_E_NOMEM;
-		}
+	if (QDF_IS_STATUS_SUCCESS(rsp->status)) {
+		if ((WMI_VDEV_TYPE_STA == rsp->type ||
+		    (WMI_VDEV_TYPE_AP == rsp->type &&
+		     WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE == rsp->sub_type))) {
+			sme_debug("send SET IE msg to PE");
+			msg = qdf_mem_malloc(sizeof(*msg));
+			if (NULL == msg) {
+				sme_err("Memory allocation failed");
+				return QDF_STATUS_E_NOMEM;
+			}
 
-		msg->msg_type = eWNI_SME_SET_IE_REQ;
-		msg->session_id = rsp->session_id;
-		msg->length = sizeof(*msg);
-		status = umac_send_mb_message_to_mac(msg);
-		if (!QDF_IS_STATUS_SUCCESS(status))
-			sme_err("Failed to send down the set IE req ");
+			msg->msg_type = eWNI_SME_SET_IE_REQ;
+			msg->session_id = rsp->session_id;
+			msg->length = sizeof(*msg);
+			status = umac_send_mb_message_to_mac(msg);
+			if (!QDF_IS_STATUS_SUCCESS(status))
+				sme_err("Failed to send down the set IE req ");
+		}
 	}
 
-	csr_roam_session_opened(pMac, rsp->session_id);
+	csr_roam_session_opened(pMac, rsp->status, rsp->session_id);
+
+	if (QDF_IS_STATUS_ERROR(rsp->status))
+		csr_cleanup_session(pMac, rsp->session_id);
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 56 - 53
core/wma/src/wma_dev_if.c

@@ -2366,12 +2366,13 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 	params.nss_5g = self_sta_req->nss_5g;
 
 	/* Create a vdev in target */
-	status = wmi_unified_vdev_create_send(wma_handle->wmi_handle,
-						self_sta_req->self_mac_addr,
-						&params);
-	if (QDF_IS_STATUS_ERROR(status)) {
+	ret = wmi_unified_vdev_create_send(wma_handle->wmi_handle,
+					   self_sta_req->self_mac_addr,
+					   &params);
+	if (QDF_IS_STATUS_ERROR(ret)) {
 		WMA_LOGE("%s: Unable to add an interface for ath_dev",
 			 __func__);
+		status = QDF_STATUS_E_FAILURE;
 		goto end;
 	}
 
@@ -2389,7 +2390,7 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 					   self_sta_req->self_mac_addr,
 					   vdev_id, txrx_vdev_type);
 
-	WMA_LOGD("vdev_id %hu, txrx_vdev_handle = %pK", self_sta_req->session_id,
+	WMA_LOGD("vdev_id %hu, txrx_vdev_handle = %pK", vdev_id,
 		 txrx_vdev_handle);
 
 	if (!txrx_vdev_handle) {
@@ -2404,6 +2405,17 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 	wma_handle->interfaces[vdev_id].handle = txrx_vdev_handle;
 	wma_vdev_update_pause_bitmap(vdev_id, 0);
 
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma_handle->psoc, vdev_id,
+						    WLAN_LEGACY_WMA_ID);
+	if (!vdev) {
+		WMA_LOGE(FL("vdev obj is NULL for vdev_id: %u"), vdev_id);
+		status = QDF_STATUS_E_FAILURE;
+		wma_handle->interfaces[vdev_id].vdev_active = false;
+		wmi_unified_vdev_delete_send(wma_handle->wmi_handle, vdev_id);
+		goto end;
+	}
+
+	wma_handle->interfaces[vdev_id].vdev = vdev;
 	wma_handle->interfaces[vdev_id].ptrn_match_enable =
 		wma_handle->ptrn_match_enable_all_vdev ? true : false;
 
@@ -2436,9 +2448,9 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 	tx_rx_aggregation_size.vdev_id = self_sta_req->session_id;
 	tx_rx_aggregation_size.aggr_type = WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU;
 
-	status = wma_set_tx_rx_aggregation_size(&tx_rx_aggregation_size);
-	if (status != QDF_STATUS_SUCCESS)
-		WMA_LOGE("failed to set aggregation sizes(err=%d)", status);
+	ret = wma_set_tx_rx_aggregation_size(&tx_rx_aggregation_size);
+	if (QDF_IS_STATUS_ERROR(ret))
+		WMA_LOGE("failed to set aggregation sizes(err=%d)", ret);
 
 	tx_rx_aggregation_size.tx_aggregation_size_be =
 				self_sta_req->tx_aggregation_size_be;
@@ -2462,11 +2474,10 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 
 	switch (self_sta_req->type) {
 	case WMI_VDEV_TYPE_STA:
-		status = wma_set_tx_rx_aggregation_size_per_ac(
+		ret = wma_set_tx_rx_aggregation_size_per_ac(
 						&tx_rx_aggregation_size);
-		if (status != QDF_STATUS_SUCCESS)
-			WMA_LOGE("failed to set aggr sizes per ac(err=%d)",
-				 status);
+		if (QDF_IS_STATUS_ERROR(ret))
+			WMA_LOGE("set aggr sizes per ac(err=%d) failed", ret);
 
 		cfg_val = mac->mlme_cfg->sta.sta_keep_alive_period;
 		wma_set_sta_keep_alive(wma_handle,
@@ -2477,57 +2488,59 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 		/* offload STA SA query related params to fwr */
 		if (wmi_service_enabled(wma_handle->wmi_handle,
 			wmi_service_sta_pmf_offload)) {
-			wma_set_sta_sa_query_param(wma_handle,
-						   self_sta_req->session_id);
+			wma_set_sta_sa_query_param(wma_handle, vdev_id);
 		}
 
-		status = wma_set_sw_retry_threshold(
-						&tx_aggr_sw_retry_threshold);
-		if (status != QDF_STATUS_SUCCESS)
-			WMA_LOGE("failed to set retry threshold(err=%d)",
-				 status);
+		ret = wma_set_sw_retry_threshold(&tx_aggr_sw_retry_threshold);
+		if (QDF_IS_STATUS_ERROR(ret))
+			WMA_LOGE("failed to set retry threshold(err=%d)", ret);
 		break;
 	}
 
-	wma_handle->interfaces[self_sta_req->session_id].type =
-		self_sta_req->type;
-	wma_handle->interfaces[self_sta_req->session_id].sub_type =
-		self_sta_req->sub_type;
-	qdf_atomic_init(&wma_handle->interfaces
-			[self_sta_req->session_id].bss_status);
+	wma_handle->interfaces[vdev_id].type = self_sta_req->type;
+	wma_handle->interfaces[vdev_id].sub_type = self_sta_req->sub_type;
+	qdf_atomic_init(&wma_handle->interfaces[vdev_id].bss_status);
 
 	if (wma_vdev_uses_self_peer(self_sta_req->type,
 				    self_sta_req->sub_type)) {
-		status = wma_create_peer(wma_handle, txrx_pdev,
-					 txrx_vdev_handle,
-					 self_sta_req->self_mac_addr,
-					 WMI_PEER_TYPE_DEFAULT,
-					 self_sta_req->session_id, false);
-		if (status != QDF_STATUS_SUCCESS) {
+		ret = wma_create_peer(wma_handle, txrx_pdev, txrx_vdev_handle,
+				      self_sta_req->self_mac_addr,
+				      WMI_PEER_TYPE_DEFAULT,
+				      self_sta_req->session_id, false);
+		if (QDF_IS_STATUS_ERROR(ret)) {
 			WMA_LOGE("%s: Failed to create peer", __func__);
 			status = QDF_STATUS_E_FAILURE;
+			wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
 			wmi_unified_vdev_delete_send(wma_handle->wmi_handle,
 						     self_sta_req->session_id);
+			wma_handle->interfaces[vdev_id].vdev_active = false;
+			wma_cdp_vdev_detach(soc, wma_handle, vdev_id);
+			wma_handle->interfaces[vdev_id].vdev = NULL;
 			goto end;
 		}
 	} else if (self_sta_req->type == WMI_VDEV_TYPE_STA) {
-		obj_peer = wma_create_objmgr_peer(wma_handle,
-						  vdev_id,
+		obj_peer = wma_create_objmgr_peer(wma_handle, vdev_id,
 						  self_sta_req->self_mac_addr,
 						  WMI_PEER_TYPE_DEFAULT);
 		if (!obj_peer) {
 			WMA_LOGE("%s: Failed to create obj mgr peer for self sta",
 				 __func__);
+			status = QDF_STATUS_E_FAILURE;
+			wmi_unified_vdev_delete_send(wma_handle->wmi_handle,
+						     self_sta_req->session_id);
+			wma_handle->interfaces[vdev_id].vdev_active = false;
+			wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
+			wma_handle->interfaces[vdev_id].vdev = NULL;
+			wma_cdp_vdev_detach(soc, wma_handle, vdev_id);
 			goto end;
 		}
 	}
 
 	WMA_LOGD("Setting WMI_VDEV_PARAM_DISCONNECT_TH: %d",
-		self_sta_req->pkt_err_disconn_th);
-	ret = wma_vdev_set_param(wma_handle->wmi_handle,
-				self_sta_req->session_id,
-				WMI_VDEV_PARAM_DISCONNECT_TH,
-				self_sta_req->pkt_err_disconn_th);
+		 self_sta_req->pkt_err_disconn_th);
+	ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
+				 WMI_VDEV_PARAM_DISCONNECT_TH,
+				 self_sta_req->pkt_err_disconn_th);
 	if (ret)
 		WMA_LOGE("Failed to set WMI_VDEV_PARAM_DISCONNECT_TH");
 
@@ -2538,8 +2551,7 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 	if (QDF_IS_STATUS_ERROR(ret))
 		WMA_LOGE("Failed to set WMI VDEV MCC_RTSCTS_PROTECTION_ENABLE");
 
-	ret = wma_vdev_set_param(wma_handle->wmi_handle,
-			self_sta_req->session_id,
+	ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
 			WMI_VDEV_PARAM_MCC_BROADCAST_PROBE_ENABLE,
 			mac->roam.configParam.mcc_bcast_prob_resp_enable);
 	if (QDF_IS_STATUS_ERROR(ret))
@@ -2655,7 +2667,7 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 		WMA_LOGD("%s: setting ini value for WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED: %d",
 			__func__, cfg_val);
 		ret = wma_set_enable_disable_mcc_adaptive_scheduler(cfg_val);
-		if (ret != QDF_STATUS_SUCCESS) {
+		if (QDF_IS_STATUS_ERROR(ret)) {
 			WMA_LOGE("Failed to set WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED");
 		}
 	} else {
@@ -2663,21 +2675,12 @@ struct cdp_vdev *wma_vdev_attach(tp_wma_handle wma_handle,
 	}
 
 	if (self_sta_req->type == WMI_VDEV_TYPE_STA) {
-		status = wma_config_active_apf_mode(wma_handle,
-						    self_sta_req->session_id);
-		if (QDF_IS_STATUS_ERROR(status))
+		ret = wma_config_active_apf_mode(wma_handle,
+						 self_sta_req->session_id);
+		if (QDF_IS_STATUS_ERROR(ret))
 			WMA_LOGE("Failed to configure active APF mode");
 	}
 
-	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma_handle->psoc,
-						    vdev_id,
-						    WLAN_LEGACY_WMA_ID);
-	if (!vdev) {
-		WMA_LOGE(FL("vdev obj is NULL for vdev_id: %u"), vdev_id);
-		status = QDF_STATUS_E_FAILURE;
-	} else {
-		wma_handle->interfaces[vdev_id].vdev = vdev;
-	}
 end:
 	self_sta_req->status = status;