Browse Source

qcacld-3.0: Handle Vdev restart Failure in STA mode

When switch channel failed,  need handle it gracefully,
pass failure to PE and disconnect current session.

Change-Id: If489e519a1784dabf630d5bde34ef8de56abf5e1
CRs-Fixed: 2360726
Jianmin Zhu 6 years ago
parent
commit
3c50e40af5

+ 1 - 0
core/mac/inc/sir_api.h

@@ -1573,6 +1573,7 @@ typedef struct sSirSmeSwitchChannelInd {
 	uint16_t newChannelId;
 	struct ch_params chan_params;
 	struct qdf_mac_addr bssid;      /* BSSID */
+	QDF_STATUS status;
 } tSirSmeSwitchChannelInd, *tpSirSmeSwitchChannelInd;
 
 /* / Definition for MIC failure indication */

+ 23 - 24
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -4792,6 +4792,20 @@ QDF_STATUS lim_sta_mlme_vdev_disconnect_bss(struct vdev_mlme_obj *vdev_mlme,
 	}
 	return QDF_STATUS_SUCCESS;
 }
+
+static void lim_process_disconnect_sta(struct pe_session *session,
+				       struct scheduler_msg *msg)
+{
+	if (wlan_vdev_mlme_get_substate(session->vdev) ==
+	    WLAN_VDEV_SS_START_RESTART_PROGRESS)
+		wlan_vdev_mlme_sm_deliver_evt(session->vdev,
+					      WLAN_VDEV_SM_EV_RESTART_REQ_FAIL,
+					      sizeof(*msg), msg);
+	else
+		wlan_vdev_mlme_sm_deliver_evt(session->vdev,
+					      WLAN_VDEV_SM_EV_DOWN,
+					      sizeof(*msg), msg);
+}
 #endif
 
 static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx,
@@ -4801,7 +4815,6 @@ static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx,
 	tSirSmeDisassocCnf sme_disassoc_cnf;
 	struct pe_session *session;
 	uint8_t session_id;
-	QDF_STATUS status;
 
 	qdf_mem_copy(&sme_disassoc_cnf, msg->bodyptr,
 		     sizeof(struct sSirSmeDisassocCnf));
@@ -4810,15 +4823,11 @@ static void lim_process_sme_disassoc_cnf(struct mac_context *mac_ctx,
 					   sme_disassoc_cnf.bssid.bytes,
 					   &session_id);
 
-	if (LIM_IS_STA_ROLE(session)) {
-		status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
-						       WLAN_VDEV_SM_EV_DOWN,
-						       sizeof(*msg),
-						       msg);
-	} else {
+	if (LIM_IS_STA_ROLE(session))
+		lim_process_disconnect_sta(session, msg);
+	else
 		__lim_process_sme_disassoc_cnf(mac_ctx,
 					       (uint32_t *)msg->bodyptr);
-	}
 #else
 	__lim_process_sme_disassoc_cnf(mac_ctx, (uint32_t *)msg->bodyptr);
 #endif
@@ -4831,22 +4840,17 @@ static void lim_process_sme_disassoc_req(struct mac_context *mac_ctx,
 	tSirSmeDisassocReq disassoc_req;
 	struct pe_session *session;
 	uint8_t session_id;
-	QDF_STATUS status;
 
 	qdf_mem_copy(&disassoc_req, msg->bodyptr, sizeof(tSirSmeDisassocReq));
 
 	session = pe_find_session_by_bssid(mac_ctx,
 					   disassoc_req.bssid.bytes,
 					   &session_id);
-	if (LIM_IS_STA_ROLE(session)) {
-		status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
-						       WLAN_VDEV_SM_EV_DOWN,
-						       sizeof(*msg),
-						       msg);
-	} else {
+	if (LIM_IS_STA_ROLE(session))
+		lim_process_disconnect_sta(session, msg);
+	else
 		__lim_process_sme_disassoc_req(mac_ctx,
 					       (uint32_t *)msg->bodyptr);
-	}
 #else
 	__lim_process_sme_disassoc_req(mac_ctx, (uint32_t *)msg->bodyptr);
 #endif
@@ -4859,22 +4863,17 @@ static void lim_process_sme_deauth_req(struct mac_context *mac_ctx,
 	tSirSmeDeauthReq sme_deauth_req;
 	struct pe_session *session;
 	uint8_t session_id;
-	QDF_STATUS status;
 
 	qdf_mem_copy(&sme_deauth_req, msg->bodyptr, sizeof(tSirSmeDeauthReq));
 
 	session = pe_find_session_by_bssid(mac_ctx,
 					   sme_deauth_req.bssid.bytes,
 					   &session_id);
-	if (LIM_IS_STA_ROLE(session)) {
-		status = wlan_vdev_mlme_sm_deliver_evt(session->vdev,
-						       WLAN_VDEV_SM_EV_DOWN,
-						       sizeof(*msg),
-						       msg);
-	} else {
+	if (LIM_IS_STA_ROLE(session))
+		lim_process_disconnect_sta(session, msg);
+	else
 		__lim_process_sme_deauth_req(mac_ctx,
 					     (uint32_t *)msg->bodyptr);
-	}
 #else
 	__lim_process_sme_deauth_req(mac_ctx, (uint32_t *)msg->bodyptr);
 #endif

+ 9 - 3
core/mac/src/pe/lim/lim_utils.c

@@ -2054,7 +2054,7 @@ static void __lim_process_channel_switch_timeout(struct mac_context *mac)
 #ifdef CONFIG_VDEV_SM
 void lim_process_channel_switch_timeout(struct mac_context *mac_ctx)
 {
-	tpPESession session_entry = NULL;
+	struct pe_session *session_entry = NULL;
 	QDF_STATUS status;
 
 	session_entry = pe_find_session_by_session_id(
@@ -2321,13 +2321,16 @@ void lim_switch_channel_cback(struct mac_context *mac, QDF_STATUS status,
 	pSirSmeSwitchChInd->chan_params.center_freq_seg1 =
 			pe_session->gLimChannelSwitch.ch_center_freq_seg1;
 
-	pe_debug("session: %d chan: %d width: %d sec offset: %d seg0: %d seg1: %d",
+	pSirSmeSwitchChInd->status = status;
+	pe_debug(
+		"session: %d chan: %d width: %d sec offset: %d seg0: %d seg1: %d status %d",
 		pSirSmeSwitchChInd->sessionId,
 		pSirSmeSwitchChInd->newChannelId,
 		pSirSmeSwitchChInd->chan_params.ch_width,
 		pSirSmeSwitchChInd->chan_params.sec_ch_offset,
 		pSirSmeSwitchChInd->chan_params.center_freq_seg0,
-		pSirSmeSwitchChInd->chan_params.center_freq_seg1);
+		pSirSmeSwitchChInd->chan_params.center_freq_seg1,
+		status);
 
 	qdf_mem_copy(pSirSmeSwitchChInd->bssid.bytes, pe_session->bssId,
 		     QDF_MAC_ADDR_SIZE);
@@ -2339,6 +2342,9 @@ void lim_switch_channel_cback(struct mac_context *mac, QDF_STATUS status,
 
 	sys_process_mmh_msg(mac, &mmhMsg);
 #ifdef CONFIG_VDEV_SM
+	if (QDF_IS_STATUS_ERROR(status))
+		return;
+
 	evt_status = wlan_vdev_mlme_sm_deliver_evt(
 				pe_session->vdev,
 				WLAN_VDEV_SM_EV_START_SUCCESS,

+ 9 - 0
core/sme/src/csr/csr_api_roam.c

@@ -11254,6 +11254,15 @@ csr_roam_chk_lnk_swt_ch_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
 		sme_err("session %d not found", sessionId);
 		return;
 	}
+
+#ifdef CONFIG_VDEV_SM
+	if (QDF_IS_STATUS_ERROR(pSwitchChnInd->status)) {
+		sme_err("Channel switch failed");
+		csr_roam_disconnect_internal(mac_ctx, sessionId,
+					     eCSR_DISCONNECT_REASON_DEAUTH);
+		return;
+	}
+#endif
 	session->connectedProfile.operationChannel =
 			(uint8_t) pSwitchChnInd->newChannelId;
 	if (session->pConnectBssDesc) {

+ 15 - 7
core/wma/src/wma_dev_if.c

@@ -1402,6 +1402,16 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info,
 			wma->interfaces[resp_event->vdev_id].is_channel_switch =
 				false;
 		}
+#else
+		/* Indicate channel switch failure to LIM */
+		if (QDF_IS_STATUS_ERROR(params->status) &&
+		    (wma_is_vdev_in_ap_mode(wma, resp_event->vdev_id) ||
+		     mlme_is_chan_switch_in_progress(iface->vdev))) {
+			mlme_set_chan_switch_in_progress(iface->vdev, false);
+			wma_send_msg_high_priority(wma, WMA_SWITCH_CHANNEL_RSP,
+						   (void *)params, 0);
+			goto error;
+		}
 #endif
 		if ((QDF_IS_STATUS_SUCCESS(resp_event->status) &&
 		     (resp_event->resp_type == WMI_VDEV_RESTART_RESP_EVENT) &&
@@ -1484,7 +1494,9 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info,
 #endif
 		ucfg_ocb_config_channel(wma->pdev);
 	}
-
+#ifdef CONFIG_VDEV_SM
+error:
+#endif
 	if ((wma->interfaces[resp_event->vdev_id].type == WMI_VDEV_TYPE_AP) &&
 		wma_is_vdev_up(resp_event->vdev_id))
 		wma_set_sap_keepalive(wma, resp_event->vdev_id);
@@ -3763,14 +3775,10 @@ void wma_vdev_resp_timer(void *data)
 		} else {
 #ifdef CONFIG_VDEV_SM
 			iface = &wma->interfaces[tgt_req->vdev_id];
-
-			wlan_vdev_mlme_sm_deliver_evt(iface->vdev,
-						   WLAN_VDEV_SM_EV_RESTART_RESP,
-						   sizeof(*params), params);
-#else
+			mlme_set_chan_switch_in_progress(iface->vdev, false);
+#endif
 			wma_send_msg_high_priority(wma, WMA_SWITCH_CHANNEL_RSP,
 				    (void *)params, 0);
-#endif
 		}
 #ifndef CONFIG_VDEV_SM
 		if (wma->interfaces[tgt_req->vdev_id].is_channel_switch) {