Kaynağa Gözat

qcacld-3.0: Fix race between ht_width_switch and roam start

Host receives ROAM_SYNCH event from FW when MLME SM
is in ST-RESTART_PROG state while processing ht_width_switch
request. This results in MLME SM not able to send SYNC IND failure
to FW and leads to assert in FW.

Below fix are required to handle the above situation:
1. Avoid VDEV-RESTART while handling ht_width_switch if
   roaming is in progress on the same vdev.

2. If Vdev is not UP then send roam sync failure to FW to
   avoid assert in FW.

3. If ht_width_switch req fails then make sure host initiates
   disconnection.

Change-Id: I91cb46cc7b9c3e3a1d5858275ade16c6f0f47286
CRs-Fixed: 2658871
Abhinav Kumar 5 yıl önce
ebeveyn
işleme
1322a2da5f
2 değiştirilmiş dosya ile 44 ekleme ve 29 silme
  1. 18 18
      core/mac/src/pe/lim/lim_utils.c
  2. 26 11
      core/wma/src/wma_scan_roam.c

+ 18 - 18
core/mac/src/pe/lim/lim_utils.c

@@ -68,6 +68,7 @@
 #include "wlan_qct_sys.h"
 #include <wlan_scan_ucfg_api.h>
 #include <wlan_blm_api.h>
+#include <lim_assoc_utils.h>
 
 #define ASCII_SPACE_CHARACTER 0x20
 
@@ -3663,16 +3664,6 @@ QDF_STATUS lim_tx_complete(void *context, qdf_nbuf_t buf, bool free)
 	return QDF_STATUS_SUCCESS;
 }
 
-static void lim_ht_width_switch_cback(struct mac_context *mac,
-				QDF_STATUS status, uint32_t *data,
-				struct pe_session *pe_session)
-{
-	pe_debug("status %d for ht width switch for vdev %d", status,
-		 pe_session->smeSessionId);
-	if (QDF_IS_STATUS_SUCCESS(status))
-		lim_switch_channel_vdev_started(pe_session);
-}
-
 static void lim_ht_switch_chnl_params(struct pe_session *pe_session)
 {
 	uint8_t center_freq = 0;
@@ -3700,14 +3691,23 @@ static void lim_ht_switch_chnl_params(struct pe_session *pe_session)
 		else
 			ch_width = CH_WIDTH_20MHZ;
 	}
+	pe_session->gLimChannelSwitch.primaryChannel = primary_channel;
+	pe_session->curr_req_chan_freq = pe_session->curr_op_freq;
+	pe_session->ch_center_freq_seg0 = center_freq;
+	pe_session->gLimChannelSwitch.ch_center_freq_seg0 = center_freq;
+	pe_session->gLimChannelSwitch.sw_target_freq = center_freq;
+	pe_session->ch_width = ch_width;
+	pe_session->gLimChannelSwitch.ch_width = ch_width;
+	pe_session->gLimChannelSwitch.sec_ch_offset =
+		pe_session->htSecondaryChannelOffset;
+	pe_session->gLimChannelSwitch.ch_center_freq_seg1 = 0;
 
-	/* notify HAL */
-	pe_debug("HT IE changed: Primary Channel: %d Secondary Channel Offset: %d Channel Width: %d",
+	pe_debug("HT IE changed: Primary Channel: %d center chan: %d Channel Width: %d",
 		 primary_channel, center_freq,
 		 pe_session->htRecommendedTxWidthSet);
 	pe_session->channelChangeReasonCode =
 			LIM_SWITCH_CHANNEL_HT_WIDTH;
-	mac->lim.gpchangeChannelCallback = lim_ht_width_switch_cback;
+	mac->lim.gpchangeChannelCallback = lim_switch_channel_cback;
 	mac->lim.gpchangeChannelData = NULL;
 
 	lim_send_switch_chnl_params(mac, pe_session);
@@ -3777,15 +3777,15 @@ void lim_update_sta_run_time_ht_switch_chnl_params(struct mac_context *mac,
 		return;
 	}
 
+	if (lim_is_roam_synch_in_progress(pe_session)) {
+		pe_debug("Roaming in progress, ignore HT IE BW update");
+		return;
+	}
+
 	if (pe_session->htSecondaryChannelOffset !=
 	    (uint8_t) pHTInfo->secondaryChannelOffset
 	    || pe_session->htRecommendedTxWidthSet !=
 	    (uint8_t) pHTInfo->recommendedTxWidthSet) {
-		pe_session->gLimChannelSwitch.primaryChannel =
-						pHTInfo->primaryChannel;
-		pe_session->gLimChannelSwitch.sw_target_freq =
-			wlan_reg_legacy_chan_to_freq(mac->pdev,
-						     pHTInfo->primaryChannel);
 		pe_session->htSecondaryChannelOffset =
 			(ePhyChanBondState) pHTInfo->secondaryChannelOffset;
 		pe_session->htRecommendedTxWidthSet =

+ 26 - 11
core/wma/src/wma_scan_roam.c

@@ -2802,6 +2802,29 @@ static void wma_update_phymode_on_roam(tp_wma_handle wma, uint8_t *bssid,
 	WMA_LOGD("LFR3: new phymode %d", bss_phymode);
 }
 
+/**
+ * wma_post_roam_sync_failure: Send roam sync failure ind to fw
+ * @wma: wma handle
+ * @vdev_id: session id
+ *
+ * Return: None
+ */
+static void wma_post_roam_sync_failure(tp_wma_handle wma, uint8_t vdev_id)
+{
+	struct roam_offload_scan_req *roam_req;
+
+	roam_req = qdf_mem_malloc(sizeof(struct roam_offload_scan_req));
+	if (roam_req) {
+		roam_req->Command = ROAM_SCAN_OFFLOAD_STOP;
+		roam_req->reason = REASON_ROAM_SYNCH_FAILED;
+		roam_req->sessionId = vdev_id;
+		wma_debug("In cleanup: RSO Command:%d, reason %d vdev %d",
+			  roam_req->Command, roam_req->reason,
+			  roam_req->sessionId);
+		wma_process_roaming_config(wma, roam_req);
+	}
+}
+
 int wma_mlme_roam_synch_event_handler_cb(void *handle, uint8_t *event,
 					 uint32_t len)
 {
@@ -2812,7 +2835,6 @@ int wma_mlme_roam_synch_event_handler_cb(void *handle, uint8_t *event,
 	struct bss_description *bss_desc_ptr = NULL;
 	uint16_t ie_len = 0;
 	int status = -EINVAL;
-	struct roam_offload_scan_req *roam_req;
 	qdf_time_t roam_synch_received = qdf_get_system_timestamp();
 	uint32_t roam_synch_data_len;
 	A_UINT32 bcn_probe_rsp_len;
@@ -3024,16 +3046,8 @@ cleanup_label:
 			wma->csr_roam_synch_cb(wma->mac_context,
 					       roam_synch_ind_ptr, NULL,
 					       SIR_ROAMING_ABORT);
-		roam_req = qdf_mem_malloc(sizeof(struct roam_offload_scan_req));
-		if (roam_req && synch_event) {
-			roam_req->Command = ROAM_SCAN_OFFLOAD_STOP;
-			roam_req->reason = REASON_ROAM_SYNCH_FAILED;
-			roam_req->sessionId = synch_event->vdev_id;
-			wma_debug("In cleanup: RSO Command:%d, reason %d vdev %d",
-				  roam_req->Command, roam_req->reason,
-				  roam_req->sessionId);
-			wma_process_roaming_config(wma, roam_req);
-		}
+		if (synch_event)
+			wma_post_roam_sync_failure(wma, synch_event->vdev_id);
 	}
 	if (roam_synch_ind_ptr && roam_synch_ind_ptr->join_rsp)
 		qdf_mem_free(roam_synch_ind_ptr->join_rsp);
@@ -3234,6 +3248,7 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event,
 						   event);
 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
 		wma_err("Failed to send the EV_ROAM");
+		wma_post_roam_sync_failure(wma, synch_event->vdev_id);
 		return status;
 	}
 	wma_debug("Posted EV_ROAM to VDEV SM");