Browse Source

qcacld-3.0: Send vdev pcl command when STA + STA roaming is active

Send Vdev pcl command on both connected STA vdev when sta+sta
roaming is enabled. Handle below cases:
1. When 1st STA is connected send PDEV pcl command for the
first sta. Set pcl_vdev_cmd_active false.
2. When 2nd STA comes up, Set pcl_vdev_cmd_active to true,
send vdev PCL for 1st sta before enabling roaming(disabled
as part of the connect on 2nd STA).
3. For second STA force dbs connection when
enable_dual_sta_roam_offload ini is enabled. Set the channels
of the 1st connected STA band as invalid and remove these
channels from the scan filter.
4. On disconnection of 2nd STA connection, clear the vdev
PCL sent for 1st STA and then send PDEV pcl command.

Also make changes to send set PCL command after roam init
is done before RSO start is done at firmware to avoid assert.
Post set pcl command from sme/csr through lim/wma/wmi to avoid
the above condition.
Disable roaming on the vdev before sending set PCL command to
avoid roaming on undesirable band & channels.

Change-Id: I6bd869015b7248fe5c5c90b6e2fa0174995be197
CRs-Fixed: 2725360
Pragaspathi Thilagaraj 4 years ago
parent
commit
750e889d9e

+ 16 - 3
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -30,7 +30,9 @@
 #include "qdf_status.h"
 #include "wlan_objmgr_psoc_obj.h"
 #include "wlan_policy_mgr_public_struct.h"
+#include "wlan_cm_roam_public_srtuct.h"
 #include "wlan_utility.h"
+#include "sir_types.h"
 
 struct target_psoc_info;
 
@@ -595,11 +597,13 @@ static inline void policy_mgr_change_sap_channel_with_csa(
  * policy_mgr_set_pcl_for_existing_combo() - SET PCL for existing combo
  * @psoc: PSOC object information
  * @mode: Adapter mode
+ * @vdev_id: Vdev Id
  *
  * Return: None
  */
 void policy_mgr_set_pcl_for_existing_combo(struct wlan_objmgr_psoc *psoc,
-					   enum policy_mgr_con_mode mode);
+					   enum policy_mgr_con_mode mode,
+					   uint8_t vdev_id);
 /**
  * policy_mgr_incr_active_session() - increments the number of active sessions
  * @psoc: PSOC object information
@@ -1344,9 +1348,11 @@ typedef void (*policy_mgr_nss_update_cback)(struct wlan_objmgr_psoc *psoc,
  * @sme_soc_set_dual_mac_config: Set the dual MAC scan & FW
  *                             config
  * @sme_pdev_set_hw_mode: Set the new HW mode to FW
- * @sme_pdev_set_pcl: Set new PCL to FW
+ * @sme_set_pcl: Set new PCL to FW
  * @sme_nss_update_request: Update NSS value to FW
  * @sme_change_mcc_beacon_interval: Set MCC beacon interval to FW
+ * @sme_rso_start_cb: Enable roaming offload callback
+ * @sme_rso_stop_cb: Disable roaming offload callback
  */
 struct policy_mgr_sme_cbacks {
 	void (*sme_get_nss_for_vdev)(enum QDF_OPMODE,
@@ -1354,7 +1360,8 @@ struct policy_mgr_sme_cbacks {
 	QDF_STATUS (*sme_soc_set_dual_mac_config)(
 		struct policy_mgr_dual_mac_config msg);
 	QDF_STATUS (*sme_pdev_set_hw_mode)(struct policy_mgr_hw_mode msg);
-	QDF_STATUS (*sme_pdev_set_pcl)(struct policy_mgr_pcl_list *msg);
+	QDF_STATUS (*sme_set_pcl)(struct policy_mgr_pcl_list *msg,
+				  uint8_t vdev_id, bool clear_vdev_pcl);
 	QDF_STATUS (*sme_nss_update_request)(uint32_t vdev_id,
 		uint8_t new_nss, uint8_t ch_width,
 		policy_mgr_nss_update_cback cback,
@@ -1368,6 +1375,12 @@ struct policy_mgr_sme_cbacks {
 		uint32_t *ch_freq);
 	QDF_STATUS (*sme_scan_result_purge)(
 				void *scan_result);
+	QDF_STATUS (*sme_rso_start_cb)(
+		mac_handle_t mac_handle, uint8_t vdev_id,
+		uint8_t reason, enum wlan_cm_rso_control_requestor requestor);
+	QDF_STATUS (*sme_rso_stop_cb)(
+		mac_handle_t mac_handle, uint8_t vdev_id,
+		uint8_t reason, enum wlan_cm_rso_control_requestor requestor);
 };
 
 /**

+ 5 - 3
components/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c

@@ -1346,13 +1346,15 @@ QDF_STATUS policy_mgr_pdev_get_pcl(struct wlan_objmgr_psoc *psoc,
 /**
  * policy_mgr_set_pcl_for_existing_combo() - Set PCL for existing connection
  * @mode: Connection mode of type 'policy_mgr_con_mode'
+ * @vdev_id: Vdev Id
  *
  * Set the PCL for an existing connection
  *
  * Return: None
  */
-void policy_mgr_set_pcl_for_existing_combo(
-		struct wlan_objmgr_psoc *psoc, enum policy_mgr_con_mode mode)
+void policy_mgr_set_pcl_for_existing_combo(struct wlan_objmgr_psoc *psoc,
+					   enum policy_mgr_con_mode mode,
+					   uint8_t vdev_id)
 {
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 	struct policy_mgr_conc_connection_info
@@ -1386,7 +1388,7 @@ void policy_mgr_set_pcl_for_existing_combo(
 
 	/* Send PCL only if policy_mgr_pdev_get_pcl returned success */
 	if (QDF_IS_STATUS_SUCCESS(status)) {
-		status = pm_ctx->sme_cbacks.sme_pdev_set_pcl(&pcl);
+		status = pm_ctx->sme_cbacks.sme_set_pcl(&pcl, vdev_id, false);
 		if (QDF_IS_STATUS_ERROR(status))
 			policy_mgr_err("Send set PCL to SME failed");
 	}

+ 32 - 2
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -35,6 +35,8 @@
 #include "wlan_nan_api.h"
 #include "nan_public_structs.h"
 #include "wlan_reg_services_api.h"
+#include "wlan_cm_roam_public_srtuct.h"
+#include "csr_neighbor_roam.h"
 
 /* invalid channel id. */
 #define INVALID_CHANNEL_ID 0
@@ -1717,8 +1719,10 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc,
 				enum QDF_OPMODE mode,
 				uint8_t session_id)
 {
+	mac_handle_t mac_handle = cds_get_context(QDF_MODULE_ID_SME);
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
-	uint32_t conn_6ghz_flag = 0;
+	uint32_t conn_6ghz_flag = 0, conn_idx = 0;
+	uint8_t vdev_id = WLAN_INVALID_VDEV_ID;
 
 	pm_ctx = policy_mgr_get_context(psoc);
 	if (!pm_ctx) {
@@ -1759,10 +1763,36 @@ void policy_mgr_incr_active_session(struct wlan_objmgr_psoc *psoc,
 	policy_mgr_debug("No.# of active sessions for mode %d = %d",
 		mode, pm_ctx->no_of_active_sessions[mode]);
 	policy_mgr_incr_connection_count(psoc, session_id, mode);
+
 	if ((policy_mgr_mode_specific_connection_count(
 		psoc, PM_STA_MODE, NULL) > 0) && (mode != QDF_STA_MODE)) {
+		/* Send set pcl for all the connected STA vdev */
 		qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
-		policy_mgr_set_pcl_for_existing_combo(psoc, PM_STA_MODE);
+		for (conn_idx = 0; conn_idx < MAX_NUMBER_OF_CONC_CONNECTIONS;
+		     conn_idx++) {
+			qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+			if (!(pm_conc_connection_list[conn_idx].mode ==
+			      PM_STA_MODE &&
+			      pm_conc_connection_list[conn_idx].in_use)) {
+				qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+				continue;
+			}
+
+			vdev_id = pm_conc_connection_list[conn_idx].vdev_id;
+			qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+			pm_ctx->sme_cbacks.sme_rso_stop_cb(
+					mac_handle, vdev_id,
+					REASON_DRIVER_DISABLED,
+					RSO_SET_PCL);
+
+			policy_mgr_set_pcl_for_existing_combo(psoc, PM_STA_MODE,
+							      vdev_id);
+			pm_ctx->sme_cbacks.sme_rso_start_cb(
+					mac_handle, vdev_id,
+					REASON_DRIVER_ENABLED,
+					RSO_SET_PCL);
+		}
 		qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
 	}
 

+ 6 - 2
components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c

@@ -655,8 +655,8 @@ QDF_STATUS policy_mgr_register_sme_cb(struct wlan_objmgr_psoc *psoc,
 		sme_cbacks->sme_nss_update_request;
 	pm_ctx->sme_cbacks.sme_pdev_set_hw_mode =
 		sme_cbacks->sme_pdev_set_hw_mode;
-	pm_ctx->sme_cbacks.sme_pdev_set_pcl =
-		sme_cbacks->sme_pdev_set_pcl;
+	pm_ctx->sme_cbacks.sme_set_pcl =
+		sme_cbacks->sme_set_pcl;
 	pm_ctx->sme_cbacks.sme_soc_set_dual_mac_config =
 		sme_cbacks->sme_soc_set_dual_mac_config;
 	pm_ctx->sme_cbacks.sme_change_mcc_beacon_interval =
@@ -665,6 +665,10 @@ QDF_STATUS policy_mgr_register_sme_cb(struct wlan_objmgr_psoc *psoc,
 		sme_cbacks->sme_get_ap_channel_from_scan;
 	pm_ctx->sme_cbacks.sme_scan_result_purge =
 		sme_cbacks->sme_scan_result_purge;
+	pm_ctx->sme_cbacks.sme_rso_start_cb =
+		sme_cbacks->sme_rso_start_cb;
+	pm_ctx->sme_cbacks.sme_rso_stop_cb =
+		sme_cbacks->sme_rso_stop_cb;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 36 - 1
components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c

@@ -33,6 +33,7 @@
 #include "wlan_objmgr_global_obj.h"
 #include "wlan_utility.h"
 #include "wlan_mlme_ucfg_api.h"
+#include "csr_neighbor_roam.h"
 
 /**
  * first_connection_pcl_table - table which provides PCL for the
@@ -112,6 +113,9 @@ void policy_mgr_decr_session_set_pcl(struct wlan_objmgr_psoc *psoc,
 {
 	QDF_STATUS qdf_status;
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	mac_handle_t mac_handle = cds_get_context(QDF_MODULE_ID_SME);
+	uint32_t conn_idx = 0;
+	uint8_t vdev_id = WLAN_INVALID_VDEV_ID;
 
 	pm_ctx = policy_mgr_get_context(psoc);
 	if (!pm_ctx) {
@@ -139,7 +143,38 @@ void policy_mgr_decr_session_set_pcl(struct wlan_objmgr_psoc *psoc,
 	 * given to the FW. After setting the PCL, we need to restore
 	 * the entry that we have saved before.
 	 */
-	policy_mgr_set_pcl_for_existing_combo(psoc, PM_STA_MODE);
+
+	if ((policy_mgr_mode_specific_connection_count(
+		psoc, PM_STA_MODE, NULL) > 0) && mode != QDF_STA_MODE) {
+		for (conn_idx = 0; conn_idx < MAX_NUMBER_OF_CONC_CONNECTIONS;
+		     conn_idx++) {
+			qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+			if (!(pm_conc_connection_list[conn_idx].mode ==
+			      PM_STA_MODE &&
+			      pm_conc_connection_list[conn_idx].in_use)) {
+				qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+				continue;
+			}
+
+			vdev_id = pm_conc_connection_list[conn_idx].vdev_id;
+			qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+			/* Send RSO stop before sending set pcl command */
+			pm_ctx->sme_cbacks.sme_rso_stop_cb(
+						mac_handle, session_id,
+						REASON_DRIVER_DISABLED,
+						RSO_SET_PCL);
+
+			policy_mgr_set_pcl_for_existing_combo(psoc, PM_STA_MODE,
+							      session_id);
+
+			pm_ctx->sme_cbacks.sme_rso_start_cb(
+					mac_handle, session_id,
+					REASON_DRIVER_ENABLED,
+					RSO_SET_PCL);
+		}
+	}
+
 	/* do we need to change the HW mode */
 	policy_mgr_check_n_start_opportunistic_timer(psoc);
 	return;

+ 4 - 0
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c

@@ -27,6 +27,7 @@
 #include <include/wlan_mlme_cmn.h>
 #include <../../core/src/vdev_mgr_ops.h>
 #include "wlan_psoc_mlme_api.h"
+#include "target_if_cm_roam_offload.h"
 
 static struct vdev_mlme_ops sta_mlme_ops;
 static struct vdev_mlme_ops ap_mlme_ops;
@@ -941,6 +942,9 @@ QDF_STATUS vdevmgr_mlme_ext_hdl_create(struct vdev_mlme_obj *vdev_mlme)
 		return QDF_STATUS_E_NOMEM;
 	}
 
+	target_if_cm_roam_register_tx_ops(
+			&vdev_mlme->ext_vdev_ptr->cm_roam.tx_ops);
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 2 - 0
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_srtuct.h

@@ -52,11 +52,13 @@ enum wlan_cm_rso_control_requestor {
  * struct set_pcl_req - Request message to set the PCL
  * @vdev_id:   Vdev id
  * @band_mask: Supported band mask
+ * @clear_vdev_pcl: Clear the configured vdev pcl channels
  * @chan_weights: PCL channel weights
  */
 struct set_pcl_req {
 	uint8_t vdev_id;
 	uint32_t band_mask;
+	bool clear_vdev_pcl;
 	struct wmi_pcl_chan_weights chan_weights;
 };
 

+ 1 - 1
components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c

@@ -50,7 +50,7 @@ void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc,
 
 	/* value - true (vdev pcl) false - pdev pcl */
 	mlme_priv->cm_roam.pcl_vdev_cmd_active = pcl_per_vdev;
-	mlme_legacy_debug("CM_ROAM: SET PCL cmd level - [%s]",
+	mlme_legacy_debug("CM_ROAM: vdev[%d] SET PCL cmd level - [%s]", vdev_id,
 			  pcl_per_vdev ? "VDEV" : "PDEV");
 }
 

+ 4 - 1
components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_tgt_if_tx_api.c

@@ -81,6 +81,9 @@ wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc,
 		weights->saved_chan_list[i] = freq_list->freq[i];
 
 	weights->saved_num_chan = freq_list->num_channels;
+	if (pcl_req->clear_vdev_pcl)
+		weights->saved_num_chan = 0;
+
 	status = policy_mgr_get_valid_chan_weights(
 			psoc, (struct policy_mgr_pcl_chan_weights *)weights);
 
@@ -109,7 +112,7 @@ wlan_cm_roam_send_set_vdev_pcl(struct wlan_objmgr_psoc *psoc,
 		goto end;
 	}
 
-	mlme_debug("LFR3: Dump Vdev PCL weights");
+	mlme_debug("LFR3: vdev[%d] Dump Vdev PCL weights", pcl_req->vdev_id);
 	policy_mgr_dump_channel_list(weights->saved_num_chan,
 				     weights->saved_chan_list,
 				     weights->weighed_valid_list);

+ 14 - 1
core/hdd/src/wlan_hdd_assoc.c

@@ -73,6 +73,7 @@
 #include "wlan_hdd_sta_info.h"
 #include "wlan_hdd_ftm_time_sync.h"
 #include "wlan_hdd_periodic_sta_stats.h"
+#include "wlan_cm_roam_api.h"
 
 #include <ol_defines.h>
 #include "wlan_pkt_capture_ucfg_api.h"
@@ -1987,9 +1988,13 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter,
 
 	hdd_print_bss_info(sta_ctx);
 
-	if (policy_mgr_is_sta_active_connection_exists(hdd_ctx->psoc))
+	if (policy_mgr_is_sta_active_connection_exists(hdd_ctx->psoc) &&
+	    QDF_STA_MODE == adapter->device_mode) {
 		sme_enable_roaming_on_connected_sta(mac_handle,
 						    adapter->vdev_id);
+		sme_clear_and_set_pcl_for_connected_vdev(mac_handle,
+							 adapter->vdev_id);
+	}
 
 	return status;
 }
@@ -2824,6 +2829,14 @@ hdd_association_completion_handler(struct hdd_adapter *adapter,
 		    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
 			hdd_debug("p2p cli active keep roam disabled");
 		} else {
+			/*
+			 * On successful association. set the vdev PCL for the
+			 * already existing STA which was connected first
+			 */
+			sme_set_pcl_for_first_connected_vdev(
+					hdd_ctx->mac_handle,
+					adapter->vdev_id);
+
 			/*
 			 * Enable roaming on other STA iface except this one.
 			 * Firmware dosent support connection on one STA iface

+ 13 - 3
core/hdd/src/wlan_hdd_ioctl.c

@@ -3784,9 +3784,19 @@ static int drv_cmd_set_roam_intra_band(struct hdd_adapter *adapter,
 		  val);
 
 	ucfg_mlme_set_roam_intra_band(hdd_ctx->psoc, (bool)val);
-	policy_mgr_set_pcl_for_existing_combo(
-					hdd_ctx->psoc,
-					PM_STA_MODE);
+
+	/* Disable roaming on Vdev before setting PCL */
+	sme_stop_roaming(hdd_ctx->mac_handle, adapter->vdev_id,
+			 REASON_DRIVER_DISABLED,
+			 RSO_SET_PCL);
+
+	policy_mgr_set_pcl_for_existing_combo(hdd_ctx->psoc, PM_STA_MODE,
+					      adapter->vdev_id);
+
+	/* Enable roaming once SET pcl is done */
+	sme_start_roaming(hdd_ctx->mac_handle, adapter->vdev_id,
+			  REASON_DRIVER_ENABLED,
+			  RSO_SET_PCL);
 
 exit:
 	return ret;

+ 1 - 1
core/mac/src/include/sir_params.h

@@ -381,7 +381,7 @@ struct sir_cfg_action_frm_tb_ppdu {
 
 #define SIR_HAL_FLUSH_LOG_TO_FW            (SIR_HAL_ITC_MSG_TYPES_BEGIN + 160)
 
-#define SIR_HAL_PDEV_SET_PCL_TO_FW         (SIR_HAL_ITC_MSG_TYPES_BEGIN + 161)
+#define SIR_HAL_SET_PCL_TO_FW              (SIR_HAL_ITC_MSG_TYPES_BEGIN + 161)
 
 #ifdef WLAN_MWS_INFO_DEBUGFS
 #define SIR_HAL_GET_MWS_COEX_INFO_REQ      (SIR_HAL_ITC_MSG_TYPES_BEGIN + 162)

+ 1 - 1
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -3464,7 +3464,7 @@ static void lim_send_roam_set_pcl(struct mac_context *mac_ctx,
 	struct scheduler_msg wma_msg = {0};
 	QDF_STATUS status;
 
-	wma_msg.type = SIR_HAL_PDEV_SET_PCL_TO_FW;
+	wma_msg.type = SIR_HAL_SET_PCL_TO_FW;
 	wma_msg.bodyptr = msg_buf;
 
 	status = wma_post_ctrl_msg(mac_ctx, &wma_msg);

+ 1 - 1
core/mac/src/sys/legacy/src/utils/src/mac_trace.c

@@ -531,7 +531,7 @@ uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg)
 		CASE_RETURN_STRING(SIR_HAL_CONFIG_GUARD_TIME);
 		CASE_RETURN_STRING(SIR_HAL_START_STOP_LOGGING);
 		CASE_RETURN_STRING(SIR_HAL_FLUSH_LOG_TO_FW);
-		CASE_RETURN_STRING(SIR_HAL_PDEV_SET_PCL_TO_FW);
+		CASE_RETURN_STRING(SIR_HAL_SET_PCL_TO_FW);
 		CASE_RETURN_STRING(SIR_HAL_PDEV_SET_HW_MODE);
 		CASE_RETURN_STRING(SIR_HAL_PDEV_DUAL_MAC_CFG_REQ);
 		CASE_RETURN_STRING(WMA_RADAR_DETECTED_IND);

+ 7 - 5
core/sme/inc/csr_neighbor_roam.h

@@ -354,15 +354,17 @@ csr_roam_update_cfg(struct mac_context *mac, uint8_t vdev_id, uint8_t reason)
  * csr_get_roam_enabled_sta_sessionid() - get the session id of the sta on which
  * roaming is enabled.
  * @mac_ctx:  pointer to global mac structure
+ * @vdev_id: vdev id of the requestor
  *
- * The function check if any sta is present and has roaming enabled and return
- * the session id of the sta with roaming enabled else if roaming is not enabled
- * on any STA return WLAN_UMAC_VDEV_ID_MAX
+ * The function checks if any sta(other than the provided vdev_id) is present
+ * and has roaming enabled and return the session id of the sta with roaming
+ * enabled else if roaming is not enabled on any STA return
+ * WLAN_UMAC_VDEV_ID_MAX.
  *
  * Return: session id of STA on which roaming is enabled
  */
-uint8_t csr_get_roam_enabled_sta_sessionid(
-	struct mac_context *mac_ctx);
+uint8_t csr_get_roam_enabled_sta_sessionid(struct mac_context *mac_ctx,
+					   uint8_t vdev_id);
 
 #if defined(WLAN_FEATURE_FILS_SK)
 /**

+ 51 - 3
core/sme/inc/sme_api.h

@@ -46,6 +46,7 @@
 #include <qca_vendor.h>
 #include "wmi_unified.h"
 #include "wmi_unified_param.h"
+#include "wlan_cm_roam_public_srtuct.h"
 
 /*--------------------------------------------------------------------------
   Preprocessor definitions and constants
@@ -971,10 +972,43 @@ QDF_STATUS sme_config_fast_roaming(mac_handle_t mac_handle, uint8_t session_id,
 				   const bool is_fast_roam_enabled);
 
 QDF_STATUS sme_stop_roaming(mac_handle_t mac_handle, uint8_t sessionId,
-			    uint8_t reason, uint32_t requestor);
+			    uint8_t reason,
+			    enum wlan_cm_rso_control_requestor requestor);
 
 QDF_STATUS sme_start_roaming(mac_handle_t mac_handle, uint8_t sessionId,
-			     uint8_t reason, uint32_t requestor);
+			     uint8_t reason,
+			     enum wlan_cm_rso_control_requestor requestor);
+
+/**
+ * sme_set_pcl_for_first_connected_vdev  - Set the vdev pcl for the connected
+ * STA vdev
+ * @mac_handle: Pointer to opaque mac handle
+ * @vdev_id: vdev id
+ *
+ * This API will be called from the association completion handler of the
+ * 2nd STA to set the vdev pcl for the 1st.
+ *
+ * Return: None
+ */
+void sme_set_pcl_for_first_connected_vdev(mac_handle_t mac_handle,
+					  uint8_t vdev_id);
+
+/**
+ * sme_clear_and_set_pcl_for_connected_vdev  - Clear the vdev pcl for the
+ * current connected VDEV and Set PDEV pcl for that vdev.
+ *
+ * @mac_handle: Pointer to opaque mac handle
+ * @vdev_id: vdev id
+ *
+ * This API will be called from the disconnection handler of the 2nd STA.
+ * In the disconnection path. Clear the existing vdev pcl for the 1st STA
+ * and set the PDEV pcl.
+ *
+ * Return: None
+ */
+void sme_clear_and_set_pcl_for_connected_vdev(mac_handle_t mac_handle,
+					      uint8_t vdev_id);
+
 #ifdef FEATURE_WLAN_ESE
 QDF_STATUS sme_update_is_ese_feature_enabled(mac_handle_t mac_handle,
 					     uint8_t sessionId,
@@ -1808,7 +1842,21 @@ void sme_update_user_configured_nss(mac_handle_t mac_handle, uint8_t nss);
 
 bool sme_is_any_session_in_connected_state(mac_handle_t mac_handle);
 
-QDF_STATUS sme_pdev_set_pcl(struct policy_mgr_pcl_list *msg);
+/**
+ * sme_set_pcl() - Send set pcl command to the WMA via lim
+ * @msg: PCL channel list and length structure
+ * @vdev_id: Vdev id
+ * @clear_vdev_pcl: flag to clear the configured vdev pcl
+ *
+ * Sends the set pcl command to lim->WMA to send WMI_PDEV_SET_PCL_CMDID to FW
+ * if dual sta roaming is disabled. If dual sta roaming is enabled,
+ * WMI_VDEV_SET_PCL_CMDID will be sent.
+ *
+ * Return: QDF_STATUS_SUCCESS on successful posting
+ */
+QDF_STATUS sme_set_pcl(struct policy_mgr_pcl_list *msg, uint8_t vdev_id,
+		       bool clear_vdev_pcl);
+
 QDF_STATUS sme_pdev_set_hw_mode(struct policy_mgr_hw_mode msg);
 QDF_STATUS sme_nss_update_request(uint32_t vdev_id,
 				  uint8_t  new_nss, uint8_t ch_width,

+ 121 - 27
core/sme/src/common/sme_api.c

@@ -64,6 +64,9 @@
 #include "wlan_mlme_ucfg_api.h"
 #include "wlan_psoc_mlme_api.h"
 #include "mac_init_api.h"
+#include "wlan_cm_roam_public_srtuct.h"
+#include "wlan_cm_roam_api.h"
+#include "wlan_cm_tgt_if_tx_api.h"
 
 static QDF_STATUS init_sme_cmd_list(struct mac_context *mac);
 
@@ -1209,7 +1212,7 @@ QDF_STATUS sme_start(mac_handle_t mac_handle)
 		sme_cbacks.sme_get_nss_for_vdev = sme_get_vdev_type_nss;
 		sme_cbacks.sme_nss_update_request = sme_nss_update_request;
 		sme_cbacks.sme_pdev_set_hw_mode = sme_pdev_set_hw_mode;
-		sme_cbacks.sme_pdev_set_pcl = sme_pdev_set_pcl;
+		sme_cbacks.sme_set_pcl = sme_set_pcl;
 		sme_cbacks.sme_soc_set_dual_mac_config =
 			sme_soc_set_dual_mac_config;
 		sme_cbacks.sme_change_mcc_beacon_interval =
@@ -1217,6 +1220,8 @@ QDF_STATUS sme_start(mac_handle_t mac_handle)
 		sme_cbacks.sme_get_ap_channel_from_scan =
 			sme_get_ap_channel_from_scan;
 		sme_cbacks.sme_scan_result_purge = sme_scan_result_purge;
+		sme_cbacks.sme_rso_start_cb = sme_start_roaming;
+		sme_cbacks.sme_rso_stop_cb = sme_stop_roaming;
 		status = policy_mgr_register_sme_cb(mac->psoc, &sme_cbacks);
 		if (!QDF_IS_STATUS_SUCCESS(status)) {
 			sme_err("Failed to register sme cb with Policy Manager: %d",
@@ -6315,7 +6320,8 @@ int sme_add_key_btk(mac_handle_t mac_handle, uint8_t session_id,
  *	   Other status on failure
  */
 QDF_STATUS sme_stop_roaming(mac_handle_t mac_handle, uint8_t session_id,
-			    uint8_t reason, uint32_t requestor)
+			    uint8_t reason,
+			    enum wlan_cm_rso_control_requestor requestor)
 {
 	QDF_STATUS status;
 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
@@ -6349,7 +6355,8 @@ QDF_STATUS sme_stop_roaming(mac_handle_t mac_handle, uint8_t session_id,
  *	Other status on failure
  */
 QDF_STATUS sme_start_roaming(mac_handle_t mac_handle, uint8_t sessionId,
-			     uint8_t reason, uint32_t requestor)
+			     uint8_t reason,
+			     enum wlan_cm_rso_control_requestor requestor)
 {
 	struct mac_context *mac = MAC_CONTEXT(mac_handle);
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -6372,6 +6379,68 @@ QDF_STATUS sme_start_roaming(mac_handle_t mac_handle, uint8_t sessionId,
 	return status;
 }
 
+void sme_set_pcl_for_first_connected_vdev(mac_handle_t mac_handle,
+					  uint8_t vdev_id)
+{
+	struct mac_context *mac = MAC_CONTEXT(mac_handle);
+	uint8_t roam_enabled_vdev_id;
+
+	/*
+	 * Get the vdev id of the STA on which roaming is already
+	 * initialized and set the vdev PCL for that STA vdev if dual
+	 * STA roaming feature is enabled
+	 * If this is the first connected STA vdev, then PDEV pcl will
+	 * be set at csr_roam_switch_to_init.
+	 */
+	roam_enabled_vdev_id = csr_get_roam_enabled_sta_sessionid(mac, vdev_id);
+
+	if (wlan_mlme_get_dual_sta_roaming_enabled(mac->psoc) &&
+	    roam_enabled_vdev_id != WLAN_UMAC_VDEV_ID_MAX) {
+		wlan_cm_roam_activate_pcl_per_vdev(mac->psoc,
+						   roam_enabled_vdev_id,
+						   true);
+		policy_mgr_set_pcl_for_existing_combo(mac->psoc, PM_STA_MODE,
+						      roam_enabled_vdev_id);
+	}
+}
+
+void sme_clear_and_set_pcl_for_connected_vdev(mac_handle_t mac_handle,
+					      uint8_t vdev_id)
+{
+	struct mac_context *mac = MAC_CONTEXT(mac_handle);
+	struct policy_mgr_pcl_list *msg;
+	uint8_t roam_enabled_vdev_id;
+
+	/*
+	 * Clear VDEV PCL for other STA vdev when dual sta roaming
+	 * is enabled on disconnection on one STA.
+	 * This is followed by set PDEV pcl to firmware
+	 */
+	roam_enabled_vdev_id = csr_get_roam_enabled_sta_sessionid(mac, vdev_id);
+
+	if (wlan_mlme_get_dual_sta_roaming_enabled(mac->psoc) &&
+	    roam_enabled_vdev_id != WLAN_UMAC_VDEV_ID_MAX) {
+		msg = qdf_mem_malloc(sizeof(*msg));
+		if (!msg)
+			return;
+
+		/*
+		 * Here the PCL level should be at vdev level already as this
+		 * is invoked from disconnect handler. Clear the vdev pcl
+		 * for the existing connected STA vdev and this is followed
+		 * by set PDEV pcl.
+		 */
+		sme_set_pcl(msg, roam_enabled_vdev_id, true);
+		qdf_mem_free(msg);
+
+		wlan_cm_roam_activate_pcl_per_vdev(mac->psoc,
+						   roam_enabled_vdev_id,
+						   false);
+		policy_mgr_set_pcl_for_existing_combo(mac->psoc, PM_STA_MODE,
+						      roam_enabled_vdev_id);
+	}
+}
+
 /*
  * sme_set_roam_opportunistic_scan_threshold_diff() -
  * Update Opportunistic Scan threshold diff
@@ -12080,40 +12149,52 @@ QDF_STATUS sme_reset_rssi_threshold_breached_cb(mac_handle_t mac_handle)
 
 /**
  * sme_get_connected_roaming_vdev_band_mask() - get connected vdev band mask
+ * @vdev_id: Vdev id
  *
  * Return: reg wifi band mask
  */
-static uint32_t sme_get_connected_roaming_vdev_band_mask(void)
+static uint32_t
+sme_get_connected_roaming_vdev_band_mask(uint8_t vdev_id)
 {
 	uint32_t band_mask = REG_BAND_MASK_ALL;
 	struct mac_context *mac = sme_get_mac_context();
 	struct csr_roam_session *session;
-	uint8_t session_id;
+	bool dual_sta_roam_active;
 
 	if (!mac) {
 		sme_debug("MAC Context is NULL");
 		return band_mask;
 	}
-	session_id = csr_get_roam_enabled_sta_sessionid(mac);
-	if (session_id != WLAN_UMAC_VDEV_ID_MAX) {
-		session = CSR_GET_SESSION(mac, session_id);
-		band_mask = BIT(wlan_reg_freq_to_band(
+
+	session = CSR_GET_SESSION(mac, vdev_id);
+	if (!session) {
+		sme_err("Session not found for vdev:%d", vdev_id);
+		return band_mask;
+	}
+
+	/*
+	 * If PCL command is PDEV level, only one sta is active.
+	 * So fill the band mask if intra band roaming is enabled
+	 */
+	if (!wlan_cm_roam_is_pcl_per_vdev_active(mac->psoc, vdev_id)) {
+		if (CSR_IS_ROAM_INTRA_BAND_ENABLED(mac))
+			band_mask = BIT(wlan_reg_freq_to_band(
 					session->connectedProfile.op_freq));
+
 		return band_mask;
 	}
 
+	dual_sta_roam_active =
+			wlan_mlme_get_dual_sta_roaming_enabled(mac->psoc);
+	if (dual_sta_roam_active)
+		band_mask = BIT(wlan_reg_freq_to_band(
+				session->connectedProfile.op_freq));
+
 	return band_mask;
 }
 
-/*
- * sme_pdev_set_pcl() - Send WMI_PDEV_SET_PCL_CMDID to the WMA
- * @mac_handle: Handle returned by macOpen
- * @msg: PCL channel list and length structure
- *
- * Sends the command to WMA to send WMI_PDEV_SET_PCL_CMDID to FW
- * Return: QDF_STATUS_SUCCESS on successful posting
- */
-QDF_STATUS sme_pdev_set_pcl(struct policy_mgr_pcl_list *msg)
+QDF_STATUS sme_set_pcl(struct policy_mgr_pcl_list *msg, uint8_t vdev_id,
+		       bool clear_vdev_pcl)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	struct mac_context *mac   = sme_get_mac_context();
@@ -12131,21 +12212,34 @@ QDF_STATUS sme_pdev_set_pcl(struct policy_mgr_pcl_list *msg)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (!MLME_IS_ROAM_INITIALIZED(mac->psoc, vdev_id)) {
+		sme_debug("Roam is not initialized on vdev:%d", vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	req_msg = qdf_mem_malloc(sizeof(*req_msg));
 	if (!req_msg)
 		return QDF_STATUS_E_NOMEM;
 
-	req_msg->band_mask = REG_BAND_MASK_ALL;
-	if (CSR_IS_ROAM_INTRA_BAND_ENABLED(mac)) {
-		req_msg->band_mask = sme_get_connected_roaming_vdev_band_mask();
-		sme_debug("Connected STA band mask%d", req_msg->band_mask);
-	}
+	req_msg->band_mask = sme_get_connected_roaming_vdev_band_mask(vdev_id);
+	sme_debug("Connected STA band mask%d", req_msg->band_mask);
+
 	for (i = 0; i < msg->pcl_len; i++) {
 		req_msg->chan_weights.pcl_list[i] =  msg->pcl_list[i];
 		req_msg->chan_weights.weight_list[i] =  msg->weight_list[i];
 	}
 
 	req_msg->chan_weights.pcl_len = msg->pcl_len;
+	req_msg->clear_vdev_pcl = clear_vdev_pcl;
+
+	/*
+	 * Set vdev value as WLAN_UMAC_VDEV_ID_MAX, if PDEV level
+	 * PCL command needs to be sent.
+	 */
+	if (!wlan_cm_roam_is_pcl_per_vdev_active(mac->psoc, vdev_id))
+		vdev_id = WLAN_UMAC_VDEV_ID_MAX;
+
+	req_msg->vdev_id = vdev_id;
 
 	status = sme_acquire_global_lock(&mac->sme);
 	if (status != QDF_STATUS_SUCCESS) {
@@ -12156,11 +12250,11 @@ QDF_STATUS sme_pdev_set_pcl(struct policy_mgr_pcl_list *msg)
 
 	/* Serialize the req through MC thread */
 	message.bodyptr = req_msg;
-	message.type    = SIR_HAL_PDEV_SET_PCL_TO_FW;
+	message.type    = eWNI_SME_ROAM_SEND_SET_PCL_REQ;
 	status = scheduler_post_message(QDF_MODULE_ID_SME,
-					QDF_MODULE_ID_WMA,
-					QDF_MODULE_ID_WMA, &message);
-	if (!QDF_IS_STATUS_SUCCESS(status)) {
+					QDF_MODULE_ID_PE,
+					QDF_MODULE_ID_PE, &message);
+	if (QDF_IS_STATUS_ERROR(status)) {
 		sme_err("scheduler_post_msg failed!(err=%d)", status);
 		qdf_mem_free(req_msg);
 		status = QDF_STATUS_E_FAILURE;

+ 34 - 21
core/sme/src/csr/csr_api_roam.c

@@ -1225,10 +1225,12 @@ QDF_STATUS csr_update_channel_list(struct mac_context *mac)
 	     eCSR_CFG_DOT11_MODE_11AX_ONLY))
 		pChanList->he_en = true;
 
+	pChanList->numChan = num_channel;
+	mlme_store_fw_scan_channels(mac->psoc, pChanList);
+
 	msg.type = WMA_UPDATE_CHAN_LIST_REQ;
 	msg.reserved = 0;
 	msg.bodyptr = pChanList;
-	pChanList->numChan = num_channel;
 	MTRACE(qdf_trace(QDF_MODULE_ID_SME, TRACE_CODE_SME_TX_WMA_MSG,
 			 NO_SESSION, msg.type));
 	if (QDF_STATUS_SUCCESS != scheduler_post_message(QDF_MODULE_ID_SME,
@@ -18413,7 +18415,8 @@ static void csr_update_score_params(struct mac_context *mac_ctx,
 					roam_score_params->min_roam_score_delta;
 }
 
-uint8_t csr_get_roam_enabled_sta_sessionid(struct mac_context *mac_ctx)
+uint8_t
+csr_get_roam_enabled_sta_sessionid(struct mac_context *mac_ctx, uint8_t vdev_id)
 {
 	struct csr_roam_session *session;
 	uint8_t i;
@@ -18426,6 +18429,9 @@ uint8_t csr_get_roam_enabled_sta_sessionid(struct mac_context *mac_ctx)
 		    session->pCurRoamProfile->csrPersona != QDF_STA_MODE)
 			continue;
 
+		if (vdev_id == i)
+			continue;
+
 		if (MLME_IS_ROAM_INITIALIZED(mac_ctx->psoc, i))
 			return i;
 	}
@@ -18512,10 +18518,14 @@ csr_roam_switch_to_init(struct mac_context *mac, uint8_t vdev_id,
 			uint8_t reason)
 {
 	enum roam_offload_state cur_state;
-	uint8_t temp_vdev_id;
+	uint8_t temp_vdev_id, roam_enabled_vdev_id;
 	uint32_t roaming_bitmap;
+	bool dual_sta_roam_active;
 	QDF_STATUS status;
 
+	dual_sta_roam_active =
+		wlan_mlme_get_dual_sta_roaming_enabled(mac->psoc);
+
 	cur_state = mlme_get_roam_state(mac->psoc, vdev_id);
 	switch (cur_state) {
 	case ROAM_DEINIT:
@@ -18527,13 +18537,16 @@ csr_roam_switch_to_init(struct mac_context *mac, uint8_t vdev_id,
 			return QDF_STATUS_E_FAILURE;
 		}
 
+		if (dual_sta_roam_active)
+			break;
+
 		/*
 		 * Disable roaming on the enabled sta if supplicant wants to
 		 * enable roaming on this vdev id
 		 */
-		temp_vdev_id = csr_get_roam_enabled_sta_sessionid(mac);
-		if ((temp_vdev_id != WLAN_UMAC_VDEV_ID_MAX) &&
-		    (vdev_id != temp_vdev_id)) {
+		temp_vdev_id = csr_get_roam_enabled_sta_sessionid(
+							mac, vdev_id);
+		if (temp_vdev_id != WLAN_UMAC_VDEV_ID_MAX) {
 			/*
 			 * Roam init state can be requested as part of
 			 * initial connection or due to enable from
@@ -18564,12 +18577,25 @@ csr_roam_switch_to_init(struct mac_context *mac, uint8_t vdev_id,
 	}
 
 	status = csr_send_roam_offload_init_msg(mac, vdev_id, true);
-
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
 
 	mlme_set_roam_state(mac->psoc, vdev_id, ROAM_INIT);
 
+	roam_enabled_vdev_id =
+		csr_get_roam_enabled_sta_sessionid(mac, vdev_id);
+
+	/* Send PDEV pcl command if only one STA is in connected state
+	 * If there is another STA connection exist, then set the
+	 * PCL type to vdev level
+	 */
+	if (roam_enabled_vdev_id != WLAN_UMAC_VDEV_ID_MAX &&
+	    dual_sta_roam_active)
+		wlan_cm_roam_activate_pcl_per_vdev(mac->psoc, vdev_id, true);
+
+	/* Set PCL before sending RSO start */
+	policy_mgr_set_pcl_for_existing_combo(mac->psoc, PM_STA_MODE, vdev_id);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -18698,7 +18724,6 @@ csr_roam_switch_to_deinit(struct mac_context *mac, uint8_t vdev_id,
 	}
 
 	status = csr_send_roam_offload_init_msg(mac, vdev_id, false);
-
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
 
@@ -18779,7 +18804,6 @@ csr_roam_offload_scan(struct mac_context *mac_ctx, uint8_t session_id,
 		&mac_ctx->roam.neighborRoamInfo[session_id];
 	struct roam_ext_params *roam_params_dst;
 	struct roam_ext_params *roam_params_src;
-	uint8_t temp_session_id;
 	bool prev_roaming_state;
 	enum csr_akm_type roam_profile_akm = eCSR_AUTH_TYPE_UNKNOWN;
 	uint32_t fw_akm_bitmap;
@@ -18803,14 +18827,6 @@ csr_roam_offload_scan(struct mac_context *mac_ctx, uint8_t session_id,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	temp_session_id = csr_get_roam_enabled_sta_sessionid(mac_ctx);
-	if ((temp_session_id != WLAN_UMAC_VDEV_ID_MAX) &&
-	    (session_id != temp_session_id)) {
-		sme_debug("Roam cmd not for session %d on which roaming is enabled",
-			   temp_session_id);
-		return QDF_STATUS_E_FAILURE;
-	}
-
 	if (session->pCurRoamProfile)
 		roam_profile_akm =
 			session->pCurRoamProfile->AuthType.authType[0];
@@ -19026,7 +19042,6 @@ csr_roam_offload_scan(struct mac_context *mac_ctx, uint8_t session_id,
 		csr_update_11k_offload_params(mac_ctx, session, req_buf, FALSE);
 
 	prev_roaming_state = mlme_get_roam_state(mac_ctx->psoc, session_id);
-	policy_mgr_set_pcl_for_existing_combo(mac_ctx->psoc, PM_STA_MODE);
 
 	/* Update PER config to FW. No need to update in case of stop command,
 	 * FW takes care of stopping this internally
@@ -19041,8 +19056,6 @@ csr_roam_offload_scan(struct mac_context *mac_ctx, uint8_t session_id,
 			  __func__);
 		mlme_set_roam_state(mac_ctx->psoc, session_id,
 				    prev_roaming_state);
-		policy_mgr_set_pcl_for_existing_combo(mac_ctx->psoc,
-						      PM_STA_MODE);
 		return QDF_STATUS_E_FAILURE;
 	}
 	/* update the last sent cmd */
@@ -21538,7 +21551,7 @@ csr_enable_roaming_on_connected_sta(struct mac_context *mac, uint8_t vdev_id)
 	uint32_t count;
 	uint32_t idx;
 
-	sta_vdev_id = csr_get_roam_enabled_sta_sessionid(mac);
+	sta_vdev_id = csr_get_roam_enabled_sta_sessionid(mac, vdev_id);
 	if (sta_vdev_id != WLAN_UMAC_VDEV_ID_MAX)
 		return QDF_STATUS_E_FAILURE;
 

+ 2 - 2
core/wma/inc/wma.h

@@ -1484,8 +1484,8 @@ QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma,
  */
 wmi_pcl_chan_weight wma_map_pcl_weights(uint32_t pcl_weight);
 
-QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle,
-				     struct set_pcl_req *msg);
+QDF_STATUS wma_send_set_pcl_cmd(tp_wma_handle wma_handle,
+				struct set_pcl_req *msg);
 
 QDF_STATUS wma_send_pdev_set_hw_mode_cmd(tp_wma_handle wma_handle,
 		struct policy_mgr_hw_mode *msg);

+ 17 - 6
core/wma/src/wma_main.c

@@ -45,6 +45,8 @@
 #include "wma_types.h"
 #include "lim_api.h"
 #include "lim_session_utils.h"
+#include "wlan_cm_tgt_if_tx_api.h"
+#include "wlan_cm_roam_api.h"
 
 #include "cds_utils.h"
 
@@ -8759,9 +8761,9 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg)
 		wma_set_rssi_monitoring(wma_handle, msg->bodyptr);
 		qdf_mem_free(msg->bodyptr);
 		break;
-	case SIR_HAL_PDEV_SET_PCL_TO_FW:
-		wma_send_pdev_set_pcl_cmd(wma_handle,
-				(struct set_pcl_req *)msg->bodyptr);
+	case SIR_HAL_SET_PCL_TO_FW:
+		wma_send_set_pcl_cmd(wma_handle,
+				     (struct set_pcl_req *)msg->bodyptr);
 		qdf_mem_free(msg->bodyptr);
 		break;
 	case SIR_HAL_PDEV_SET_HW_MODE:
@@ -9033,7 +9035,7 @@ wmi_pcl_chan_weight wma_map_pcl_weights(uint32_t pcl_weight)
 }
 
 /**
- * wma_send_pdev_set_pcl_cmd() - Send WMI_SOC_SET_PCL_CMDID to FW
+ * wma_send_set_pcl_cmd() - Send WMI_SOC_SET_PCL_CMDID to FW
  * @wma_handle: WMA handle
  * @msg: PCL structure containing the PCL and the number of channels
  *
@@ -9051,8 +9053,8 @@ wmi_pcl_chan_weight wma_map_pcl_weights(uint32_t pcl_weight)
  *
  * Return: Success if the cmd is sent successfully to the firmware
  */
-QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle,
-				     struct set_pcl_req *msg)
+QDF_STATUS wma_send_set_pcl_cmd(tp_wma_handle wma_handle,
+				struct set_pcl_req *msg)
 {
 	uint32_t i;
 	QDF_STATUS status;
@@ -9063,6 +9065,15 @@ QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle,
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 
+	/*
+	 * if vdev_id is WLAN_UMAC_VDEV_ID_MAX, then roaming is enabled on
+	 * only one sta, so PDEV PCL command needs to be sent.
+	 * If a valid vdev id is present, then vdev pcl command needs to be
+	 * sent.
+	 */
+	if (msg->vdev_id != WLAN_UMAC_VDEV_ID_MAX)
+		return wlan_cm_roam_send_set_vdev_pcl(wma_handle->psoc, msg);
+
 	for (i = 0; i < wma_handle->saved_chan.num_channels; i++) {
 		msg->chan_weights.saved_chan_list[i] =
 					wma_handle->saved_chan.ch_freq_list[i];