Merge "qcacld-3.0: Validate wdev before accessing netdev" into wlan-cld3.driver.lnx.2.0
diff --git a/components/blacklist_mgr/core/src/wlan_blm_core.c b/components/blacklist_mgr/core/src/wlan_blm_core.c
index 17d1634..eadbf94 100644
--- a/components/blacklist_mgr/core/src/wlan_blm_core.c
+++ b/components/blacklist_mgr/core/src/wlan_blm_core.c
@@ -1023,13 +1023,20 @@
 							max_entry_time;
 		if ((connection_age >
 		     SECONDS_TO_MS(blm_psoc_obj->blm_cfg.
-				   bad_bssid_counter_reset_time)) ||
-		    !blm_entry->reject_ap_type) {
-			blm_debug("Bad Bssid timer expired/AP cleared from all blacklisting, removed %pM from list",
-				  blm_entry->bssid.bytes);
-			qdf_list_remove_node(&blm_ctx->reject_ap_list,
-					     &blm_entry->node);
-			qdf_mem_free(blm_entry);
+				   bad_bssid_counter_reset_time))) {
+			blm_entry->driver_avoidlist = false;
+			blm_entry->driver_blacklist = false;
+			blm_entry->driver_monitorlist = false;
+			blm_entry->userspace_avoidlist = false;
+			blm_debug("updated reject ap type %d ",
+				  blm_entry->reject_ap_type);
+			if (!blm_entry->reject_ap_type) {
+				blm_debug("Bad Bssid timer expired/AP cleared from all blacklisting, removed %pM from list",
+					  blm_entry->bssid.bytes);
+				qdf_list_remove_node(&blm_ctx->reject_ap_list,
+						     &blm_entry->node);
+				qdf_mem_free(blm_entry);
+			}
 		}
 		break;
 	default:
diff --git a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h
index bb2739e..7796d6e 100644
--- a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h
+++ b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h
@@ -1223,6 +1223,7 @@
  * encryption type.
  * @hdd_is_chan_switch_in_progress: Check if in any adater channel switch is in
  * progress
+ * @wlan_hdd_set_sap_csa_reason: Set the sap csa reason in cases like NAN.
  */
 struct policy_mgr_hdd_cbacks {
 	void (*sap_restart_chan_switch_cb)(struct wlan_objmgr_psoc *psoc,
@@ -1239,6 +1240,8 @@
 	enum QDF_OPMODE (*hdd_get_device_mode)(uint32_t session_id);
 	bool (*hdd_wapi_security_sta_exist)(void);
 	bool (*hdd_is_chan_switch_in_progress)(void);
+	void (*wlan_hdd_set_sap_csa_reason)(struct wlan_objmgr_psoc *psoc,
+					    uint8_t vdev_id, uint8_t reason);
 };
 
 
@@ -1844,29 +1847,19 @@
 		struct wlan_objmgr_psoc *psoc, uint8_t session_id);
 
 /**
- * policy_mgr_set_hw_mode_before_channel_switch() - Set hw mode
- * before channel switch, this is required if DBS mode is 2x2
- * @psoc: PSOC object information
- * @vdev_id: vdev id on which channel switch is required
- * @chan: New channel to which channel switch is requested
- *
- * Return: QDF_STATUS
- */
-QDF_STATUS policy_mgr_set_hw_mode_before_channel_switch(
-		struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t chan);
-
-/**
- * policy_mgr_check_and_set_hw_mode_sta_channel_switch() - check if hw mode
- * change is required before channel switch for STA,
+ * policy_mgr_check_and_set_hw_mode_for_channel_switch() - check if hw mode
+ * change is required before channel switch for STA/SAP,
  * this is required if DBS mode is 2x2
  * @psoc: PSOC object information
  * @vdev_id: vdev id on which channel switch is required
  * @chan: New channel to which channel switch is requested
+ * @reason: reason for hw mode change
  *
  * Return: QDF_STATUS, success if HW mode change is required else Failure
  */
-QDF_STATUS policy_mgr_check_and_set_hw_mode_sta_channel_switch(
-		struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t chan);
+QDF_STATUS policy_mgr_check_and_set_hw_mode_for_channel_switch(
+		struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t chan,
+		enum policy_mgr_conn_update_reason reason);
 
 /**
  * policy_mgr_set_do_hw_mode_change_flag() - Set flag to indicate hw mode change
diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c
index 2e3d061..d132af5 100644
--- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c
+++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c
@@ -34,6 +34,7 @@
 #include "qdf_platform.h"
 #include "wlan_nan_api.h"
 #include "nan_ucfg_api.h"
+#include "sap_api.h"
 
 enum policy_mgr_conc_next_action (*policy_mgr_get_current_pref_hw_mode_ptr)
 	(struct wlan_objmgr_psoc *psoc);
@@ -1543,14 +1544,23 @@
 	if (nan_ch_2g == 0)
 		return;
 
-	status = qdf_wait_single_event(&pm_ctx->channel_switch_complete_evt,
-				       CHANNEL_SWITCH_COMPLETE_TIMEOUT);
-	policy_mgr_reset_chan_switch_complete_evt(psoc);
-	if (!QDF_IS_STATUS_SUCCESS(status))
-		policy_mgr_err("SAP Ch Switch wait fail. Force new Ch switch");
+	if (pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress &&
+	    pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress()) {
+		policy_mgr_debug("wait as channel switch is already in progress");
+		status = qdf_wait_single_event(
+					&pm_ctx->channel_switch_complete_evt,
+					CHANNEL_SWITCH_COMPLETE_TIMEOUT);
+		if (QDF_IS_STATUS_ERROR(status))
+			policy_mgr_err("wait for event failed, still continue with channel switch");
+	}
 
 	policy_mgr_debug("Force SCC for NAN+SAP Ch: %d",
 			 WLAN_REG_IS_5GHZ_CH(sap_ch) ? nan_ch_5g : nan_ch_2g);
+	if (pm_ctx->hdd_cbacks.wlan_hdd_set_sap_csa_reason)
+		pm_ctx->hdd_cbacks.wlan_hdd_set_sap_csa_reason(psoc,
+					sap_info->vdev_id,
+					CSA_REASON_CONCURRENT_NAN_EVENT);
+
 	if (WLAN_REG_IS_5GHZ_CH(sap_ch)) {
 		policy_mgr_change_sap_channel_with_csa(psoc, sap_info->vdev_id,
 						       nan_ch_5g,
@@ -1594,11 +1604,20 @@
 							 false);
 	policy_mgr_debug("User/ACS orig ch: %d New SAP ch: %d",
 			 pm_ctx->user_config_sap_channel, sap_ch);
-	status = qdf_wait_single_event(&pm_ctx->channel_switch_complete_evt,
-				       CHANNEL_SWITCH_COMPLETE_TIMEOUT);
-	policy_mgr_reset_chan_switch_complete_evt(psoc);
-	if (!QDF_IS_STATUS_SUCCESS(status))
-		policy_mgr_err("SAP Ch Switch wait fail. Force new Ch switch");
+	if (pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress &&
+	    pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress()) {
+		policy_mgr_debug("wait as channel switch is already in progress");
+		status = qdf_wait_single_event(
+					&pm_ctx->channel_switch_complete_evt,
+					CHANNEL_SWITCH_COMPLETE_TIMEOUT);
+		if (QDF_IS_STATUS_ERROR(status))
+			policy_mgr_err("wait for event failed, still continue with channel switch");
+	}
+
+	if (pm_ctx->hdd_cbacks.wlan_hdd_set_sap_csa_reason)
+		pm_ctx->hdd_cbacks.wlan_hdd_set_sap_csa_reason(psoc,
+					sap_info->vdev_id,
+					CSA_REASON_CONCURRENT_NAN_EVENT);
 
 	policy_mgr_change_sap_channel_with_csa(psoc, sap_info->vdev_id,
 					       sap_ch,
@@ -2205,106 +2224,15 @@
 	return status;
 }
 
-QDF_STATUS policy_mgr_set_hw_mode_before_channel_switch(
-		struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t chan)
+QDF_STATUS policy_mgr_check_and_set_hw_mode_for_channel_switch(
+		struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t chan,
+		enum policy_mgr_conn_update_reason reason)
 {
 	QDF_STATUS status;
 	struct policy_mgr_conc_connection_info info;
 	uint8_t num_cxn_del = 0;
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
 	enum policy_mgr_conc_next_action next_action = PM_NOP;
-	enum policy_mgr_conn_update_reason reason =
-			POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH;
-
-	pm_ctx = policy_mgr_get_context(psoc);
-	if (!pm_ctx) {
-		policy_mgr_err("Invalid context");
-		return QDF_STATUS_E_FAILURE;
-	}
-
-	if (!policy_mgr_is_hw_dbs_capable(psoc)) {
-		policy_mgr_err("DBS is disabled");
-		return QDF_STATUS_E_NOSUPPORT;
-	}
-
-	/*
-	 * Stop opportunistic timer as current connection info will change once
-	 * channel is switched and thus if required it will be started once
-	 * channel switch is completed. With new connection info.
-	 */
-	policy_mgr_stop_opportunistic_timer(psoc);
-
-	/*
-	 * Return if driver is already in the dbs mode, movement to
-	 * Single mac/SBS mode will be decided and changed once channel
-	 * switch is completed. This will avoid changing to SBS/Single mac
-	 * till new channel is configured, while the old channel still
-	 * requires DBS.
-	 */
-	if (policy_mgr_is_current_hwmode_dbs(psoc)) {
-		policy_mgr_err("Already in DBS mode");
-		return QDF_STATUS_E_ALREADY;
-	}
-
-	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
-	/*
-	 * Store the connection's parameter and temporarily delete it
-	 * from the concurrency table. This way the allow concurrency
-	 * check can be used as though a new connection is coming up,
-	 * after check, restore the connection to concurrency table.
-	 */
-	policy_mgr_store_and_del_conn_info_by_vdev_id(psoc, vdev_id,
-						      &info, &num_cxn_del);
-	status = policy_mgr_get_next_action(psoc, vdev_id, chan, reason,
-					    &next_action);
-	/* Restore the connection entry */
-	if (num_cxn_del)
-		policy_mgr_restore_deleted_conn_info(psoc, &info, num_cxn_del);
-	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
-
-	if (QDF_IS_STATUS_ERROR(status))
-		goto chk_opportunistic_timer;
-
-	status = policy_mgr_reset_connection_update(psoc);
-	if (QDF_IS_STATUS_ERROR(status))
-		policy_mgr_err("clearing event failed");
-
-	if (PM_NOP != next_action)
-		status = policy_mgr_next_actions(psoc, vdev_id,
-						 next_action, reason);
-	else
-		status = QDF_STATUS_E_NOSUPPORT;
-
-	if (QDF_IS_STATUS_SUCCESS(status)) {
-		status = policy_mgr_wait_for_connection_update(psoc);
-		if (QDF_IS_STATUS_ERROR(status)) {
-			policy_mgr_err("qdf wait for event failed");
-		}
-	}
-
-chk_opportunistic_timer:
-	/*
-	 * If hw mode change failed restart the opportunistic timer to
-	 * Switch to single mac if required.
-	 */
-	if (status == QDF_STATUS_E_FAILURE) {
-		policy_mgr_err("Failed to update HW modeStatus %d", status);
-		policy_mgr_check_n_start_opportunistic_timer(psoc);
-	}
-
-	return status;
-}
-
-QDF_STATUS policy_mgr_check_and_set_hw_mode_sta_channel_switch(
-		struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, uint8_t chan)
-{
-	QDF_STATUS status;
-	struct policy_mgr_conc_connection_info info;
-	uint8_t num_cxn_del = 0;
-	struct policy_mgr_psoc_priv_obj *pm_ctx;
-	enum policy_mgr_conc_next_action next_action = PM_NOP;
-	enum policy_mgr_conn_update_reason reason =
-			POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH_STA;
 
 	pm_ctx = policy_mgr_get_context(psoc);
 	if (!pm_ctx) {
diff --git a/components/mlme/dispatcher/inc/cfg_mlme_lfr.h b/components/mlme/dispatcher/inc/cfg_mlme_lfr.h
index a340515..2ba4ee7 100644
--- a/components/mlme/dispatcher/inc/cfg_mlme_lfr.h
+++ b/components/mlme/dispatcher/inc/cfg_mlme_lfr.h
@@ -1427,7 +1427,7 @@
  * gNeighborScanChannelMaxTime - Set neighbor scan channel max time
  * @Min: 3
  * @Max: 300
- * @Default: 30
+ * @Default: 40
  *
  * This ini is used to set the maximum time in secs spent on each
  * channel in LFR scan inside firmware.
@@ -1444,7 +1444,7 @@
 	"gNeighborScanChannelMaxTime", \
 	3, \
 	300, \
-	30, \
+	40, \
 	CFG_VALUE_OR_DEFAULT, \
 	"Neighbor scan channel max time")
 
diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c
index 1757e74..af20008 100644
--- a/core/cds/src/cds_api.c
+++ b/core/cds/src/cds_api.c
@@ -2301,7 +2301,8 @@
  */
 void cds_wlan_flush_host_logs_for_fatal(void)
 {
-	wlan_flush_host_logs_for_fatal();
+	if (cds_is_log_report_in_progress())
+		wlan_flush_host_logs_for_fatal();
 }
 
 /**
@@ -2388,7 +2389,8 @@
  */
 void cds_logging_set_fw_flush_complete(void)
 {
-	wlan_logging_set_fw_flush_complete();
+	if (cds_is_fatal_event_enabled())
+		wlan_logging_set_fw_flush_complete();
 }
 
 /**
diff --git a/core/hdd/src/wlan_hdd_bcn_recv.c b/core/hdd/src/wlan_hdd_bcn_recv.c
index 3267259..e16de6e 100644
--- a/core/hdd/src/wlan_hdd_bcn_recv.c
+++ b/core/hdd/src/wlan_hdd_bcn_recv.c
@@ -492,7 +492,7 @@
 	 * the QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES shall not be
 	 * set by the driver.
 	 */
-	if (!is_disconnected || !do_not_resume)
+	if (!is_disconnected && !do_not_resume)
 		if (nla_put_flag(vendor_event,
 			QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_AUTO_RESUMES)) {
 			hdd_err("QCA_WLAN_VENDOR_ATTR put fail");
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index 369170f..24e6e1c 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -9960,6 +9960,8 @@
 		sap_config->acs_cfg.ch_width = channel_list->chan_width;
 		hdd_ap_ctx->sap_config.ch_width_orig =
 				channel_list->chan_width;
+		wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
+					    CSA_REASON_LTE_COEX);
 		hdd_switch_sap_channel(adapter, sap_config->acs_cfg.pri_ch,
 				       true);
 		break;
@@ -16252,6 +16254,9 @@
 
 	hostapd_state = WLAN_HDD_GET_HOSTAP_STATE_PTR(ap_adapter);
 	qdf_event_reset(&hostapd_state->qdf_event);
+	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->vdev_id,
+				    CSA_REASON_STA_CONNECT_DFS_TO_NON_DFS);
+
 	status = wlansap_set_channel_change_with_csa(
 			WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter), channel,
 			hdd_ap_ctx->sap_config.ch_width_orig, false);
@@ -21106,6 +21111,8 @@
 	if ((QDF_P2P_GO_MODE != adapter->device_mode) &&
 		(QDF_SAP_MODE != adapter->device_mode))
 		return -ENOTSUPP;
+	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
+				    CSA_REASON_USER_INITIATED);
 
 	freq = csa_params->chandef.chan->center_freq;
 	channel = cds_freq_to_chan(freq);
diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c
index 4306e50..9880de8 100644
--- a/core/hdd/src/wlan_hdd_hostapd.c
+++ b/core/hdd/src/wlan_hdd_hostapd.c
@@ -1140,6 +1140,9 @@
 	 * switch to the pre CAC DFS channel, there is no CAC again.
 	 */
 	wlan_hdd_set_pre_cac_complete_status(ap_adapter, true);
+
+	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->vdev_id,
+				    CSA_REASON_PRE_CAC_SUCCESS);
 	i = hdd_softap_set_channel_change(ap_adapter->dev,
 			ap_adapter->pre_cac_chan,
 			CH_WIDTH_MAX, false);
@@ -2591,6 +2594,8 @@
 	case eSAP_ECSA_CHANGE_CHAN_IND:
 		hdd_debug("Channel change indication from peer for channel %d",
 			  sap_event->sapevt.sap_chan_cng_ind.new_chan);
+		wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
+					    CSA_REASON_PEER_ACTION_FRAME);
 		if (hdd_softap_set_channel_change(dev,
 			 sap_event->sapevt.sap_chan_cng_ind.new_chan,
 			 CH_WIDTH_MAX, false))
@@ -3072,6 +3077,20 @@
 					    channel_bw, forced);
 }
 
+void wlan_hdd_set_sap_csa_reason(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+				 uint8_t reason)
+{
+	struct sap_context *sap_ctx;
+	struct hdd_adapter *ap_adapter = wlan_hdd_get_adapter_from_vdev(
+				psoc, vdev_id);
+	if (!ap_adapter) {
+		hdd_err("ap adapter is NULL");
+		return;
+	}
+	sap_ctx = WLAN_HDD_GET_SAP_CTX_PTR(ap_adapter);
+	sap_ctx->csa_reason = reason;
+}
+
 QDF_STATUS wlan_hdd_get_channel_for_sap_restart(
 				struct wlan_objmgr_psoc *psoc,
 				uint8_t vdev_id, uint8_t *channel,
@@ -3170,6 +3189,8 @@
 		 hdd_ap_ctx->sap_config.channel, intf_ch);
 	ch_params.ch_width = CH_WIDTH_MAX;
 	hdd_ap_ctx->bss_stop_reason = BSS_STOP_DUE_TO_MCC_SCC_SWITCH;
+	hdd_ap_ctx->sap_context->csa_reason =
+			CSA_REASON_CONCURRENT_STA_CHANGED_CHANNEL;
 
 	wlan_reg_set_channel_params(hdd_ctx->pdev,
 				    intf_ch,
diff --git a/core/hdd/src/wlan_hdd_hostapd.h b/core/hdd/src/wlan_hdd_hostapd.h
index ab00e7e..615083f 100644
--- a/core/hdd/src/wlan_hdd_hostapd.h
+++ b/core/hdd/src/wlan_hdd_hostapd.h
@@ -89,6 +89,20 @@
 				uint8_t *sec_ch);
 #endif
 
+/**
+ * wlan_hdd_set_sap_csa_reason() - Function to set
+ * sap csa reason
+ * @psoc: PSOC object information
+ * @vdev_id: vdev id
+ * @reason: reason to be updated
+ *
+ * This function sets the reason for SAP channel switch
+ *
+ * Return: None
+ *
+ */
+void wlan_hdd_set_sap_csa_reason(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+				 uint8_t reason);
 eCsrEncryptionType
 hdd_translate_rsn_to_csr_encryption_type(uint8_t cipher_suite[4]);
 
diff --git a/core/hdd/src/wlan_hdd_hostapd_wext.c b/core/hdd/src/wlan_hdd_hostapd_wext.c
index 014fa79..5e32500 100644
--- a/core/hdd/src/wlan_hdd_hostapd_wext.c
+++ b/core/hdd/src/wlan_hdd_hostapd_wext.c
@@ -466,6 +466,9 @@
 	case QCSAP_PARAM_SET_CHANNEL_CHANGE:
 		if ((QDF_SAP_MODE == adapter->device_mode) ||
 		   (QDF_P2P_GO_MODE == adapter->device_mode)) {
+			wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc,
+						    adapter->vdev_id,
+						    CSA_REASON_USER_INITIATED);
 			hdd_debug("SET Channel Change to new channel= %d",
 			       set_value);
 			ret = hdd_softap_set_channel_change(dev, set_value,
diff --git a/core/hdd/src/wlan_hdd_ioctl.c b/core/hdd/src/wlan_hdd_ioctl.c
index 94978ff..a6aa4d5 100644
--- a/core/hdd/src/wlan_hdd_ioctl.c
+++ b/core/hdd/src/wlan_hdd_ioctl.c
@@ -7015,6 +7015,8 @@
 
 	hdd_debug("CH:%d BW:%d", chan_number, chan_bw);
 
+	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
+				    CSA_REASON_USER_INITIATED);
 	status = hdd_softap_set_channel_change(dev, chan_number, width, true);
 	if (status) {
 		hdd_err("Set channel change fail");
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index 097e5d3..5f1362b 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -2735,6 +2735,8 @@
 		hdd_wapi_security_sta_exist;
 	hdd_cbacks.hdd_is_chan_switch_in_progress =
 				hdd_is_chan_switch_in_progress;
+	hdd_cbacks.wlan_hdd_set_sap_csa_reason =
+				wlan_hdd_set_sap_csa_reason;
 
 	if (QDF_STATUS_SUCCESS !=
 	    policy_mgr_register_hdd_cb(psoc, &hdd_cbacks)) {
@@ -7873,7 +7875,7 @@
 	uint64_t temp_tx = 0, avg_rx = 0;
 	uint64_t no_rx_offload_pkts = 0, avg_no_rx_offload_pkts = 0;
 	uint64_t rx_offload_pkts = 0, avg_rx_offload_pkts = 0;
-	enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_NONE;
+	enum pld_bus_width_type next_vote_level = PLD_BUS_WIDTH_IDLE;
 	static enum wlan_tp_level next_rx_level = WLAN_SVC_TP_NONE;
 	enum wlan_tp_level next_tx_level = WLAN_SVC_TP_NONE;
 	uint32_t delack_timer_cnt = hdd_ctx->config->tcp_delack_timer_count;
@@ -7891,10 +7893,10 @@
 	else if (total_pkts > hdd_ctx->config->bus_bw_low_threshold)
 		next_vote_level = PLD_BUS_WIDTH_LOW;
 	else
-		next_vote_level = PLD_BUS_WIDTH_NONE;
+		next_vote_level = PLD_BUS_WIDTH_IDLE;
 
 	dptrace_high_tput_req =
-			next_vote_level > PLD_BUS_WIDTH_NONE ? true : false;
+			next_vote_level > PLD_BUS_WIDTH_IDLE ? true : false;
 
 	if (hdd_ctx->cur_vote_level != next_vote_level) {
 		hdd_debug("trigger level %d, tx_packets: %lld, rx_packets: %lld",
@@ -7903,7 +7905,7 @@
 		vote_level_change = true;
 		pld_request_bus_bandwidth(hdd_ctx->parent_dev, next_vote_level);
 		if ((next_vote_level == PLD_BUS_WIDTH_LOW) ||
-		    (next_vote_level == PLD_BUS_WIDTH_NONE)) {
+		    (next_vote_level == PLD_BUS_WIDTH_IDLE)) {
 			if (hdd_ctx->hbw_requested) {
 				pld_remove_pm_qos(hdd_ctx->parent_dev);
 				hdd_ctx->hbw_requested = false;
@@ -8840,9 +8842,13 @@
 			hdd_ctxt->acs_policy.acs_channel = AUTO_CHANNEL_SELECT;
 			ucfg_mlme_get_sap_internal_restart(hdd_ctxt->psoc,
 							   &value);
-			if (value)
+			if (value) {
+				wlan_hdd_set_sap_csa_reason(hdd_ctxt->psoc,
+						adapter->vdev_id,
+						CSA_REASON_UNSAFE_CHANNEL);
 				hdd_switch_sap_channel(adapter, restart_chan,
 						       true);
+			}
 			else {
 				hdd_debug("sending coex indication");
 				wlan_hdd_send_svc_nlink_msg(
@@ -8912,6 +8918,8 @@
 
 	wlan_hdd_send_svc_nlink_msg(hdd_ctx->radio_index,
 				    WLAN_SVC_LTE_COEX_IND, NULL, 0);
+	wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, adapter->vdev_id,
+				    CSA_REASON_LTE_COEX);
 	hdd_switch_sap_channel(adapter, restart_chan, true);
 }
 
@@ -15078,7 +15086,8 @@
 		if (!restart_chan ||
 		    wlan_reg_is_dfs_ch(hdd_ctx->pdev, restart_chan))
 			restart_chan = SAP_DEFAULT_5GHZ_CHANNEL;
-
+		wlan_hdd_set_sap_csa_reason(hdd_ctx->psoc, ap_adapter->vdev_id,
+					CSA_REASON_STA_CONNECT_DFS_TO_NON_DFS);
 		hdd_switch_sap_channel(ap_adapter, restart_chan, true);
 	}
 }
diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h
index 8b9df9b..5afd526 100644
--- a/core/mac/inc/qwlan_version.h
+++ b/core/mac/inc/qwlan_version.h
@@ -32,9 +32,9 @@
 #define QWLAN_VERSION_MAJOR            5
 #define QWLAN_VERSION_MINOR            2
 #define QWLAN_VERSION_PATCH            0
-#define QWLAN_VERSION_EXTRA            "A"
+#define QWLAN_VERSION_EXTRA            "F"
 #define QWLAN_VERSION_BUILD            139
 
-#define QWLAN_VERSIONSTR               "5.2.0.139A"
+#define QWLAN_VERSIONSTR               "5.2.0.139F"
 
 #endif /* QWLAN_VERSION_H */
diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c
index 46da1f7..a0a99e9 100644
--- a/core/mac/src/pe/lim/lim_process_action_frame.c
+++ b/core/mac/src/pe/lim/lim_process_action_frame.c
@@ -83,9 +83,10 @@
 		       pe_session->gLimChannelSwitch.switchMode);
 
 	mac->lim.limTimers.gLimChannelSwitchTimer.sessionId = sessionId;
-	status = policy_mgr_check_and_set_hw_mode_sta_channel_switch(mac->psoc,
+	status = policy_mgr_check_and_set_hw_mode_for_channel_switch(mac->psoc,
 				pe_session->smeSessionId,
-				pe_session->gLimChannelSwitch.primaryChannel);
+				pe_session->gLimChannelSwitch.primaryChannel,
+				POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH_STA);
 
 	/*
 	 * If status is QDF_STATUS_E_FAILURE, mean HW mode change was required
diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h
index 50701e3..d32d905 100644
--- a/core/pld/inc/pld_common.h
+++ b/core/pld/inc/pld_common.h
@@ -61,12 +61,14 @@
 /**
  * enum pld_bus_width_type - bus bandwidth
  * @PLD_BUS_WIDTH_NONE: don't vote for bus bandwidth
+ * @PLD_BUS_WIDTH_IDLE: vote for idle bandwidth
  * @PLD_BUS_WIDTH_LOW: vote for low bus bandwidth
  * @PLD_BUS_WIDTH_MEDIUM: vote for medium bus bandwidth
  * @PLD_BUS_WIDTH_HIGH: vote for high bus bandwidth
  */
 enum pld_bus_width_type {
 	PLD_BUS_WIDTH_NONE,
+	PLD_BUS_WIDTH_IDLE,
 	PLD_BUS_WIDTH_LOW,
 	PLD_BUS_WIDTH_MEDIUM,
 	PLD_BUS_WIDTH_HIGH
diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h
index 0ce31e1..58d6094 100644
--- a/core/sap/inc/sap_api.h
+++ b/core/sap/inc/sap_api.h
@@ -466,6 +466,31 @@
 	ACS_DFS_MODE_DEPRIORITIZE
 };
 
+/**
+ * enum sap_csa_reason_code - SAP channel switch reason code
+ * @CSA_REASON_UNKNOWN: Unknown reason
+ * @CSA_REASON_STA_CONNECT_DFS_TO_NON_DFS: STA connection from DFS to NON DFS.
+ * @CSA_REASON_USER_INITIATED: User initiated form north bound.
+ * @CSA_REASON_PEER_ACTION_FRAME: Action frame received on sta iface.
+ * @CSA_REASON_PRE_CAC_SUCCESS: Pre CAC success.
+ * @CSA_REASON_CONCURRENT_STA_CHANGED_CHANNEL: concurrent sta changed channel.
+ * @CSA_REASON_UNSAFE_CHANNEL: Unsafe channel.
+ * @CSA_REASON_LTE_COEX: LTE coex.
+ * @CSA_REASON_CONCURRENT_NAN_EVENT: NAN concurrency.
+ *
+ */
+enum sap_csa_reason_code {
+	CSA_REASON_UNKNOWN,
+	CSA_REASON_STA_CONNECT_DFS_TO_NON_DFS,
+	CSA_REASON_USER_INITIATED,
+	CSA_REASON_PEER_ACTION_FRAME,
+	CSA_REASON_PRE_CAC_SUCCESS,
+	CSA_REASON_CONCURRENT_STA_CHANGED_CHANNEL,
+	CSA_REASON_UNSAFE_CHANNEL,
+	CSA_REASON_LTE_COEX,
+	CSA_REASON_CONCURRENT_NAN_EVENT
+};
+
 struct sap_config {
 	tSap_SSIDInfo_t SSIDinfo;
 	eCsrPhyMode SapHw_mode;         /* Wireless Mode */
diff --git a/core/sap/src/sap_fsm.c b/core/sap/src/sap_fsm.c
index f10cf8f..98c76bd 100644
--- a/core/sap/src/sap_fsm.c
+++ b/core/sap/src/sap_fsm.c
@@ -239,8 +239,8 @@
 		 sap_operating_chan_preferred_location == 2)
 		flag |= DFS_RANDOM_CH_FLAG_NO_LOWER_5G_CH;
 
-	if (QDF_IS_STATUS_ERROR(utils_dfs_get_random_channel(
-	    pdev, flag, ch_params, &hw_mode, &ch, &acs_info))) {
+	if (QDF_IS_STATUS_ERROR(utils_dfs_get_vdev_random_channel(
+	    pdev, sap_ctx->vdev, flag, ch_params, &hw_mode, &ch, &acs_info))) {
 		/* No available channel found */
 		QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
 			  FL("No available channel found!!!"));
diff --git a/core/sap/src/sap_internal.h b/core/sap/src/sap_internal.h
index 418832e..cc4a25d 100644
--- a/core/sap/src/sap_internal.h
+++ b/core/sap/src/sap_internal.h
@@ -146,6 +146,7 @@
 	 * track of state machine
 	 */
 	enum sap_fsm_state fsm_state;
+	enum sap_csa_reason_code csa_reason;
 
 	/* Actual storage for AP and self (STA) SSID */
 	tCsrSSIDInfo SSIDList[2];
diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c
index 8128c45..7351914 100644
--- a/core/sap/src/sap_module.c
+++ b/core/sap/src/sap_module.c
@@ -335,6 +335,7 @@
 		sap_ctx->SSIDList[0].ssidHidden;
 
 	sap_ctx->csr_roamProfile.BSSIDs.numOfBSSIDs = 1; /* This is true for now. */
+	sap_ctx->csa_reason = CSA_REASON_UNKNOWN;
 	sap_ctx->csr_roamProfile.BSSIDs.bssid = &sap_ctx->bssid;
 	sap_ctx->csr_roamProfile.csrPersona = mode;
 	qdf_mem_copy(sap_ctx->self_mac_addr, addr, QDF_MAC_ADDR_SIZE);
@@ -1329,6 +1330,38 @@
 }
 
 /**
+ * sap_get_csa_reason_str() - Get csa reason in string
+ * @reason: sap reason enum value
+ *
+ * Return: string reason
+ */
+static char *sap_get_csa_reason_str(enum sap_csa_reason_code reason)
+{
+	switch (reason) {
+	case CSA_REASON_UNKNOWN:
+		return "UNKNOWN";
+	case CSA_REASON_STA_CONNECT_DFS_TO_NON_DFS:
+		return "STA_CONNECT_DFS_TO_NON_DFS";
+	case CSA_REASON_USER_INITIATED:
+		return "USER_INITIATED";
+	case CSA_REASON_PEER_ACTION_FRAME:
+		return "PEER_ACTION_FRAME";
+	case CSA_REASON_PRE_CAC_SUCCESS:
+		return "PRE_CAC_SUCCESS";
+	case CSA_REASON_CONCURRENT_STA_CHANGED_CHANNEL:
+		return "CONCURRENT_STA_CHANGED_CHANNEL";
+	case CSA_REASON_UNSAFE_CHANNEL:
+		return "UNSAFE_CHANNEL";
+	case CSA_REASON_LTE_COEX:
+		return "LTE_COEX";
+	case CSA_REASON_CONCURRENT_NAN_EVENT:
+		return "CONCURRENT_NAN_EVENT";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+/**
  * wlansap_set_channel_change_with_csa() - Set channel change with CSA
  * @sap_ctx: Pointer to SAP context
  * @targetChannel: Target channel
@@ -1350,7 +1383,7 @@
 	struct mac_context *mac;
 	mac_handle_t mac_handle;
 	bool valid;
-	QDF_STATUS status;
+	QDF_STATUS status, hw_mode_status;
 	bool sta_sap_scc_on_dfs_chan;
 
 	if (!sap_ctx) {
@@ -1373,10 +1406,12 @@
 		return QDF_STATUS_E_FAULT;
 	}
 	QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
-		"%s: sap chan:%d target:%d conn on 5GHz:%d",
+		"%s: sap chan:%d target:%d conn on 5GHz:%d, csa_reason:%s(%d)",
 		__func__, sap_ctx->channel, targetChannel,
 		policy_mgr_is_any_mode_active_on_band_along_with_session(
-			mac->psoc, sap_ctx->sessionId, POLICY_MGR_BAND_5));
+			mac->psoc, sap_ctx->sessionId, POLICY_MGR_BAND_5),
+			sap_get_csa_reason_str(sap_ctx->csa_reason),
+			sap_ctx->csa_reason);
 
 	sta_sap_scc_on_dfs_chan =
 		policy_mgr_is_sta_sap_scc_allowed_on_dfs_chan(mac->psoc);
@@ -1421,25 +1456,30 @@
 			if (status != QDF_STATUS_SUCCESS)
 				return status;
 
-			status = policy_mgr_set_hw_mode_before_channel_switch(
-						mac->psoc,
-						sap_ctx->sessionId,
-						targetChannel);
+			hw_mode_status =
+			  policy_mgr_check_and_set_hw_mode_for_channel_switch(
+				   mac->psoc, sap_ctx->sessionId, targetChannel,
+				   POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH);
+
 			/*
-			 * If status is QDF_STATUS_E_FAILURE that mean HW mode
-			 * change was required but set HW mode change failed.
+			 * If hw_mode_status is QDF_STATUS_E_FAILURE, mean HW
+			 * mode change was required but driver failed to set HW
+			 * mode so ignore CSA for the channel.
 			 */
-			if (status == QDF_STATUS_E_FAILURE) {
+			if (hw_mode_status == QDF_STATUS_E_FAILURE) {
 				QDF_TRACE(QDF_MODULE_ID_SAP,
 					  QDF_TRACE_LEVEL_ERROR,
 					  FL("HW change required but failed to set hw mode"));
-				return status;
+				return hw_mode_status;
 			}
 
 			status = policy_mgr_reset_chan_switch_complete_evt(
 								mac->psoc);
-			if (QDF_IS_STATUS_ERROR(status))
+			if (QDF_IS_STATUS_ERROR(status)) {
+				policy_mgr_check_n_start_opportunistic_timer(
+								mac->psoc);
 				return status;
+			}
 			/*
 			 * Copy the requested target channel
 			 * to sap context.
@@ -1494,6 +1534,26 @@
 			mac->sap.SapDfsInfo.cac_state =
 					eSAP_DFS_DO_NOT_SKIP_CAC;
 			sap_cac_reset_notify(mac_handle);
+
+			/*
+			 * If hw_mode_status is QDF_STATUS_SUCCESS mean HW mode
+			 * change was required and was successfully requested so
+			 * the channel switch will continue after HW mode change
+			 * completion.
+			 */
+			if (QDF_IS_STATUS_SUCCESS(hw_mode_status)) {
+				QDF_TRACE(QDF_MODULE_ID_SAP,
+					  QDF_TRACE_LEVEL_INFO,
+					  FL("Channel change will continue after HW mode change"));
+				return QDF_STATUS_SUCCESS;
+			}
+			/*
+			 * If hw_mode_status is QDF_STATUS_E_NOSUPPORT or
+			 * QDF_STATUS_E_ALREADY (not QDF_STATUS_E_FAILURE and
+			 * not QDF_STATUS_SUCCESS), mean DBS is not supported or
+			 * required HW mode is already set, So contunue with
+			 * CSA from here.
+			 */
 			sap_start_csa_restart(mac, sap_ctx);
 		} else {
 			QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c
index 00408bc..cf2348c 100644
--- a/core/sme/src/common/sme_api.c
+++ b/core/sme/src/common/sme_api.c
@@ -211,9 +211,14 @@
 		csr_saved_scan_cmd_free_fields(mac, session);
 	}
 	if (reason == POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH_STA) {
-		sme_debug(" Continue channel switch for STA");
+		sme_info("Continue channel switch for STA");
 		csr_sta_continue_csa(mac, session_id);
 	}
+
+	if (reason == POLICY_MGR_UPDATE_REASON_CHANNEL_SWITCH) {
+		sme_info("Continue channel switch for SAP");
+		csr_csa_restart(mac, session_id);
+	}
 	if (reason == POLICY_MGR_UPDATE_REASON_LFR2_ROAM)
 		csr_continue_lfr2_connect(mac, session_id);
 
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index 6540216..383a518 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -9482,6 +9482,13 @@
 	if (!scan_handle_roam_ap)
 		goto POST_ROAM_FAILURE;
 
+	if ((mac->roam.roamSession[session_id].connectState ==
+				eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED) ||
+	    (mac->roam.roamSession[session_id].connectState ==
+				eCSR_ASSOC_STATE_TYPE_INFRA_DISCONNECTING)) {
+		goto purge_scan_result;
+	}
+
 	status = csr_roam_lfr2_issue_connect(mac, session_id,
 						scan_handle_roam_ap,
 						roam_id);
@@ -9489,6 +9496,8 @@
 		qdf_mem_free(roam_info);
 		return status;
 	}
+
+purge_scan_result:
 	csr_scan_result_purge(mac, scan_handle_roam_ap);
 
 POST_ROAM_FAILURE:
@@ -12577,18 +12586,18 @@
 		}
 		sme_debug("SME pre-auth state timeout");
 
+		status = sme_acquire_global_lock(&mac->sme);
 		if (csr_is_conn_state_connected_infra(mac, session_id)) {
 			csr_roam_link_up(mac,
 					 pSession->connectedProfile.bssid);
-			status = sme_acquire_global_lock(&mac->sme);
 			if (QDF_IS_STATUS_SUCCESS(status)) {
 				csr_roam_disconnect(mac, session_id,
 					eCSR_DISCONNECT_REASON_UNSPECIFIED);
-				sme_release_global_lock(&mac->sme);
 			}
 		} else {
 			sme_err("session not found");
 		}
+		sme_release_global_lock(&mac->sme);
 	} else {
 		spin_unlock(&mac->roam.roam_state_lock);
 	}