Browse Source

qcacld-3.0: Handle bss peer delete before vdev start

Delete the BSS peer if failure happens before STA "Join"
and wait for peer delete event.
After peer delete event is received, send lim_cm_send_connect_rsp
to CM to continue the next candidate try.
This is to avoid previous bss peer deleting pending and send
new bss peer create wmi command to target, which is unexpected
by target.

Change-Id: I5da969546994d9a6fe3cd5053f468fb59ba13e18
CRs-Fixed: 3100305
Liangwei Dong 3 years ago
parent
commit
b92a4f7f7b

+ 8 - 40
core/mac/src/pe/lim/lim_process_mlm_req_messages.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -348,44 +349,6 @@ end:
 		lim_send_start_bss_confirm(mac_ctx, &mlm_start_cnf);
 }
 
-void
-lim_post_join_set_link_state_callback(struct mac_context *mac, uint32_t vdev_id,
-				      QDF_STATUS status)
-{
-	tLimMlmJoinCnf mlm_join_cnf;
-	struct pe_session *session_entry;
-
-	session_entry = pe_find_session_by_vdev_id(mac, vdev_id);
-	if (!session_entry) {
-		pe_err("vdev_id:%d PE session is NULL", vdev_id);
-		return;
-	}
-
-	if (QDF_IS_STATUS_ERROR(status)) {
-		pe_err("vdev%d: Failed to create peer", session_entry->vdev_id);
-		goto failure;
-	}
-
-	/*
-	 * store the channel switch session_entry in the lim
-	 * global variable
-	 */
-	session_entry->channelChangeReasonCode = LIM_SWITCH_CHANNEL_JOIN;
-	session_entry->pLimMlmReassocRetryReq = NULL;
-	lim_send_switch_chnl_params(mac, session_entry);
-
-	return;
-
-failure:
-	MTRACE(mac_trace(mac, TRACE_CODE_MLM_STATE, session_entry->peSessionId,
-			 session_entry->limMlmState));
-	session_entry->limMlmState = eLIM_MLM_IDLE_STATE;
-	mlm_join_cnf.resultCode = eSIR_SME_PEER_CREATE_FAILED;
-	mlm_join_cnf.sessionId = session_entry->peSessionId;
-	mlm_join_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
-	lim_post_sme_message(mac, LIM_MLM_JOIN_CNF, (uint32_t *) &mlm_join_cnf);
-}
-
 void lim_send_peer_create_resp(struct mac_context *mac, uint8_t vdev_id,
 			       QDF_STATUS qdf_status, uint8_t *peer_mac)
 {
@@ -451,8 +414,13 @@ lim_process_mlm_post_join_suspend_link(struct mac_context *mac_ctx,
 	mac_ctx->lim.lim_timers.gLimJoinFailureTimer.sessionId =
 		session->peSessionId;
 
-	lim_post_join_set_link_state_callback(mac_ctx, session->vdev_id,
-					      QDF_STATUS_SUCCESS);
+	/*
+	 * store the channel switch session_entry in the lim
+	 * global variable
+	 */
+	session->channelChangeReasonCode = LIM_SWITCH_CHANNEL_JOIN;
+	session->pLimMlmReassocRetryReq = NULL;
+	lim_send_switch_chnl_params(mac_ctx, session);
 }
 
 /**

+ 12 - 5
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -3939,6 +3939,10 @@ lim_cm_handle_join_req(struct cm_vdev_join_req *req)
 	struct mac_context *mac_ctx;
 	struct pe_session *pe_session;
 	QDF_STATUS status;
+	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
+
+	if (!wma)
+		return QDF_STATUS_E_INVAL;
 
 	if (!req)
 		return QDF_STATUS_E_INVAL;
@@ -3994,10 +3998,13 @@ lim_cm_handle_join_req(struct cm_vdev_join_req *req)
 fail:
 	if (pe_session)
 		pe_delete_session(mac_ctx, pe_session);
-
+	status = wma_remove_bss_peer_before_join(wma, req->vdev_id, req);
+	if (status == QDF_STATUS_E_PENDING)
+		return status;
 	lim_cm_send_connect_rsp(mac_ctx, NULL, req, CM_GENERIC_FAILURE,
-				QDF_STATUS_E_FAILURE, 0, false);
-	return QDF_STATUS_E_FAILURE;
+					QDF_STATUS_E_FAILURE, 0, false);
+
+	return status;
 }
 
 QDF_STATUS cm_process_join_req(struct scheduler_msg *msg)
@@ -4013,8 +4020,8 @@ QDF_STATUS cm_process_join_req(struct scheduler_msg *msg)
 	req = msg->bodyptr;
 
 	status = lim_cm_handle_join_req(req);
-
-	cm_free_join_req(req);
+	if (status != QDF_STATUS_E_PENDING)
+		cm_free_join_req(req);
 
 	return status;
 }

+ 0 - 16
core/mac/src/pe/lim/lim_types.h

@@ -1402,22 +1402,6 @@ void lim_process_mlm_start_req(struct mac_context *mac_ctx,
 void lim_process_mlm_join_req(struct mac_context *mac_ctx,
 			      tLimMlmJoinReq *mlm_join_req);
 
-/**
- * lim_post_join_set_link_state_callback()- registered callback to perform post
- * peer creation operations
- * @mac: pointer to global mac structure
- * @callback_arg: registered callback argument
- * @status: peer creation status
- *
- * This is registered callback function during association to perform
- * post peer creation operation based on the peer creation status
- *
- * Return: none
- */
-void
-lim_post_join_set_link_state_callback(struct mac_context *mac, uint32_t vdev_id,
-				      QDF_STATUS status);
-
 void lim_send_peer_create_resp(struct mac_context *mac, uint8_t vdev_id,
 			       QDF_STATUS status, uint8_t *peer_mac);
 /*

+ 21 - 0
core/wma/inc/wma.h

@@ -176,6 +176,9 @@
 #define WMA_PEER_CREATE_RESPONSE 0x08
 #define WMA_PEER_CREATE_RESPONSE_TIMEOUT SIR_PEER_CREATE_RESPONSE_TIMEOUT
 
+/* send connect respone after bss peer is deleted */
+#define WMA_DELETE_STA_CONNECT_RSP 0x09
+
 /* FW response timeout values in milli seconds */
 #define WMA_VDEV_PLCY_MGR_TIMEOUT        SIR_VDEV_PLCY_MGR_TIMEOUT
 #define WMA_VDEV_HW_MODE_REQUEST_TIMEOUT WMA_VDEV_PLCY_MGR_TIMEOUT
@@ -2512,6 +2515,24 @@ QDF_STATUS wma_vdev_pre_start(uint8_t vdev_id, bool restart);
  */
 void wma_remove_bss_peer_on_failure(tp_wma_handle wma, uint8_t vdev_id);
 
+/**
+ * wma_remove_bss_peer_before_join() - remove the bss peers in case of
+ * failure before join (vdev start) for sta mode
+ * @wma: wma handle.
+ * @vdev_id: vdev id
+ * @cm_join_req: join cm context
+ *
+ * This API deletes the BSS peer if any failure before "join" (vdev start).
+ * And indicate connection failure to CM after bss peer delete event comes
+ * from FW.
+ *
+ * Return: QDF_STATUS_SUCCESS if success, QDF_STATUS_E_PENDING if peer delete
+ *  event will be indicated later from target.
+ */
+QDF_STATUS wma_remove_bss_peer_before_join(
+		tp_wma_handle wma, uint8_t vdev_id,
+		void *cm_join_req);
+
 /**
  * wma_send_add_bss_resp() - send add bss failure
  * @wma: wma handle.

+ 26 - 0
core/wma/src/wma_dev_if.c

@@ -3252,7 +3252,12 @@ int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info,
 	tDeleteStaParams *del_sta;
 	uint8_t macaddr[QDF_MAC_ADDR_SIZE];
 	int status = 0;
+	struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
 
+	if (!mac) {
+		wma_err("mac context is null");
+		return -EINVAL;
+	}
 	param_buf = (WMI_PEER_DELETE_RESP_EVENTID_param_tlvs *)cmd_param_info;
 	if (!param_buf) {
 		wma_err("Invalid vdev delete event buffer");
@@ -3303,7 +3308,15 @@ int wma_peer_delete_handler(void *handle, uint8_t *cmd_param_info,
 	} else if (req_msg->type == WMA_SET_LINK_PEER_RSP ||
 		   req_msg->type == WMA_DELETE_PEER_RSP) {
 		wma_send_vdev_down_req(wma, req_msg->user_data);
+	} else if (req_msg->type == WMA_DELETE_STA_CONNECT_RSP) {
+		wma_debug("wma delete peer completed vdev %d",
+			  req_msg->vdev_id);
+		lim_cm_send_connect_rsp(mac, NULL, req_msg->user_data,
+					CM_GENERIC_FAILURE,
+					QDF_STATUS_E_FAILURE, 0, false);
+		cm_free_join_req(req_msg->user_data);
 	}
+
 	qdf_mem_free(req_msg);
 
 	return status;
@@ -3435,6 +3448,19 @@ void wma_hold_req_timer(void *data)
 				WMA_DELETE_STA_REQ,
 				QDF_PEER_DELETION_TIMEDOUT);
 		wma_send_vdev_down_req(wma, params);
+	} else if ((tgt_req->msg_type == WMA_DELETE_STA_REQ) &&
+		   (tgt_req->type == WMA_DELETE_STA_CONNECT_RSP)) {
+		wma_err("wma delete peer timed out vdev %d",
+			tgt_req->vdev_id);
+
+		if (wma_crash_on_fw_timeout(wma->fw_timeout_crash))
+			wma_trigger_recovery_assert_on_fw_timeout(
+				WMA_DELETE_STA_REQ,
+				QDF_PEER_DELETION_TIMEDOUT);
+		lim_cm_send_connect_rsp(mac, NULL, tgt_req->user_data,
+					CM_GENERIC_FAILURE,
+					QDF_STATUS_E_FAILURE, 0, false);
+		cm_free_join_req(tgt_req->user_data);
 	} else if ((tgt_req->msg_type == SIR_HAL_PDEV_SET_HW_MODE) &&
 			(tgt_req->type == WMA_PDEV_SET_HW_MODE_RESP)) {
 		struct sir_set_hw_mode_resp *params =

+ 67 - 0
core/wma/src/wma_utils.c

@@ -4249,6 +4249,73 @@ void wma_remove_bss_peer_on_failure(tp_wma_handle wma, uint8_t vdev_id)
 	wma_remove_peer(wma, bss_peer.bytes, vdev_id, false);
 }
 
+QDF_STATUS wma_remove_bss_peer_before_join(
+	tp_wma_handle wma, uint8_t vdev_id,
+	void *cm_join_req)
+{
+	uint8_t *mac_addr;
+	struct wma_target_req *del_req;
+	QDF_STATUS qdf_status;
+	struct qdf_mac_addr bssid;
+	enum QDF_OPMODE mode;
+	struct wlan_objmgr_vdev *vdev;
+
+	if (!wma || !wma->interfaces)
+		return QDF_STATUS_E_FAILURE;
+
+	if (vdev_id >= WLAN_MAX_VDEVS) {
+		wma_err("Invalid vdev id %d", vdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+	vdev = wma->interfaces[vdev_id].vdev;
+	if (!vdev) {
+		wma_err("Invalid vdev, %d", vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	mode = wlan_vdev_mlme_get_opmode(vdev);
+	if (mode != QDF_STA_MODE && mode != QDF_P2P_CLIENT_MODE) {
+		wma_err("unexpected mode %d vdev %d", mode, vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	qdf_status = wlan_vdev_get_bss_peer_mac(vdev, &bssid);
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		wma_err("Failed to get bssid for vdev_id: %d", vdev_id);
+		return qdf_status;
+	}
+	mac_addr = bssid.bytes;
+
+	qdf_status = wma_remove_peer(wma, mac_addr, vdev_id, false);
+
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		wma_err("wma_remove_peer failed vdev_id:%d", vdev_id);
+		return qdf_status;
+	}
+
+	if (cds_is_driver_recovering())
+		return QDF_STATUS_E_FAILURE;
+
+	if (wmi_service_enabled(wma->wmi_handle,
+				wmi_service_sync_delete_cmds)) {
+		wma_debug("Wait for the peer delete. vdev_id %d", vdev_id);
+		del_req = wma_fill_hold_req(wma, vdev_id,
+					    WMA_DELETE_STA_REQ,
+					    WMA_DELETE_STA_CONNECT_RSP,
+					    cm_join_req,
+					    WMA_DELETE_STA_TIMEOUT);
+		if (!del_req) {
+			wma_err("Failed to allocate request. vdev_id %d",
+				vdev_id);
+			qdf_status = QDF_STATUS_E_NOMEM;
+		} else {
+			qdf_status = QDF_STATUS_E_PENDING;
+		}
+	}
+
+	return qdf_status;
+}
+
 QDF_STATUS wma_sta_vdev_up_send(struct vdev_mlme_obj *vdev_mlme,
 				uint16_t data_len, void *data)
 {