Browse Source

qcacld-3.0: Restart SAP / GO before STA

In STA + SAP / GO DFS SCC concurrency, switch SAP / GO's operating
channel before STA's switch upon received very first CSA on STA
interface from peer AP.

Once STA moves to new channel, enforce SCC with existing SAP / GO
if its in MCC. This is done to allow traffic on SAP / GO side
during CSA period.

Change-Id: Icb4a15ad21ae96faff1fe338985aa734a4398cd2
CRs-Fixed: 3431386
Rachit Kankane 2 years ago
parent
commit
4eec1b8e78

+ 36 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -850,6 +850,42 @@ policy_mgr_change_sap_channel_with_csa(struct wlan_objmgr_psoc *psoc,
 }
 #endif
 
+/**
+ * policy_mgr_sta_sap_dfs_scc_conc_check() - validate and Move SAP channel
+ * using (E)CSA
+ *
+ * @psoc: PSOC object information
+ * @vdev_id: Vdev id
+ * @csa_event: Pointer to CSA IE Received event data
+ *
+ * Invoke the function to change SAP channel using (E)CSA for STA+GO / SAP
+ * SCC scenario only. This function will move P2P-GO / SAP first and then STA
+ * will follow.
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+QDF_STATUS
+policy_mgr_sta_sap_dfs_scc_conc_check(struct wlan_objmgr_psoc *psoc,
+				      uint8_t vdev_id,
+				      struct csa_offload_params *csa_event);
+
+/**
+ * policy_mgr_sta_sap_dfs_enforce_scc() - validate and enforce SCC
+ * using (E)CSA upon receiving 1st beacon
+ *
+ * @psoc: PSOC object information
+ * @vdev_id: Vdev id
+ *
+ * Invoke the function to enforce SCC upon receiving 1st beacon. SAP / GO
+ * movement will be triggered using (E)CSA for STA+GO / SAP DFS scenario only.
+ * The pre-requisite for this function is SAP / GO shall already moved to new
+ * channel by policy_mgr_sta_sap_dfs_scc_conc_check() function.
+ *
+ * Return: void
+ */
+void policy_mgr_sta_sap_dfs_enforce_scc(struct wlan_objmgr_psoc *psoc,
+					uint8_t vdev_id);
+
 #ifdef WLAN_FEATURE_P2P_P2P_STA
 /**
  * policy_mgr_is_p2p_p2p_conc_supported() - p2p concurrency support

+ 170 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c

@@ -2879,6 +2879,176 @@ policy_mgr_change_sap_channel_with_csa(struct wlan_objmgr_psoc *psoc,
 }
 #endif /* FEATURE_WLAN_MCC_TO_SCC_SWITCH */
 
+QDF_STATUS
+policy_mgr_sta_sap_dfs_scc_conc_check(struct wlan_objmgr_psoc *psoc,
+				      uint8_t vdev_id,
+				      struct csa_offload_params *csa_event)
+{
+	uint8_t concur_vdev_id, i;
+	bool move_sap_go_first;
+	enum hw_mode_bandwidth bw;
+	qdf_freq_t cur_freq, new_freq;
+	struct wlan_objmgr_vdev *vdev, *conc_vdev;
+	struct wlan_objmgr_pdev *pdev;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	enum policy_mgr_con_mode cur_mode;
+	enum policy_mgr_con_mode concur_mode = PM_MAX_NUM_OF_MODE;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid context");
+		return QDF_STATUS_E_INVAL;
+	}
+	if (!csa_event) {
+		policy_mgr_err("CSA IE Received event is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	policy_mgr_get_dfs_sta_sap_go_scc_movement(psoc, &move_sap_go_first);
+	if (!move_sap_go_first) {
+		policy_mgr_err("g_move_sap_go_1st_on_dfs_sta_csa is disabled");
+		return QDF_STATUS_E_NOSUPPORT;
+	}
+
+	cur_mode = policy_mgr_get_mode_by_vdev_id(psoc, vdev_id);
+	if (cur_mode != PM_STA_MODE) {
+		policy_mgr_err("CSA received on non-STA connection");
+		return QDF_STATUS_E_INVAL;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_POLICY_MGR_ID);
+	if (!vdev) {
+		policy_mgr_err("vdev is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+	pdev = wlan_vdev_get_pdev(vdev);
+	cur_freq = wlan_get_operation_chan_freq_vdev_id(pdev, vdev_id);
+
+	if (!wlan_reg_is_dfs_for_freq(pdev, cur_freq) &&
+	    !wlan_reg_is_freq_indoor(pdev, cur_freq)) {
+		policy_mgr_err("SAP / GO operating channel is non-DFS");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/* Check if there is any SAP / GO operating on the same channel or not
+	 * If yes, then get the current bandwidth and vdev_id of concurrent SAP
+	 * or GO and trigger channel switch to new channel received in CSA on
+	 * STA interface. If this new channel is DFS then trigger channel
+	 * switch to non-DFS channel. Once STA moves to this new channel and
+	 * when it receives very first beacon, it will then enforce SCC again
+	 */
+	for (i = 0; i < MAX_NUMBER_OF_CONC_CONNECTIONS; i++) {
+		if (pm_conc_connection_list[i].in_use &&
+		    pm_conc_connection_list[i].freq == cur_freq &&
+		    pm_conc_connection_list[i].vdev_id != vdev_id &&
+		    (pm_conc_connection_list[i].mode == PM_P2P_GO_MODE ||
+		     pm_conc_connection_list[i].mode == PM_SAP_MODE)) {
+			concur_mode = pm_conc_connection_list[i].mode;
+			bw = pm_conc_connection_list[i].bw;
+			concur_vdev_id = pm_conc_connection_list[i].vdev_id;
+			break;
+		}
+	}
+
+	/* If there is no concurrent SAP / GO, then return */
+	if (concur_mode == PM_MAX_NUM_OF_MODE) {
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	conc_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, concur_vdev_id,
+							 WLAN_POLICY_MGR_ID);
+	if (!conc_vdev) {
+		policy_mgr_err("conc_vdev is NULL");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
+		return QDF_STATUS_E_INVAL;
+	}
+	wlan_vdev_mlme_set_sap_go_move_before_sta(conc_vdev, true);
+	wlan_vdev_mlme_set_sap_go_move_before_sta(vdev, true);
+	wlan_objmgr_vdev_release_ref(conc_vdev, WLAN_POLICY_MGR_ID);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
+
+	/*Change the CSA count*/
+	if (pm_ctx->sme_cbacks.sme_change_sap_csa_count)
+		/* Total 4 CSA frames are allowed so that GO / SAP
+		 * will move to new channel within 500ms
+		 */
+		pm_ctx->sme_cbacks.sme_change_sap_csa_count(4);
+	new_freq = csa_event->csa_chan_freq;
+
+	/* If the new channel is DFS or indoor, then select another channel
+	 * and switch the SAP / GO to avoid CAC. This will resume traffic on
+	 * SAP / GO interface immediately. Once STA moves to this new channel
+	 * and receives the very first beacon, then it will enforece SCC
+	 */
+	if (wlan_reg_is_dfs_for_freq(pdev, new_freq) ||
+	    wlan_reg_is_freq_indoor(pdev, new_freq)) {
+		if (wlan_reg_is_24ghz_ch_freq(new_freq)) {
+			new_freq = wlan_reg_min_24ghz_chan_freq();
+		} else if (wlan_reg_is_5ghz_ch_freq(new_freq)) {
+			new_freq = wlan_reg_min_5ghz_chan_freq();
+			/* if none of the 5G channel is non-DFS */
+			if (wlan_reg_is_dfs_for_freq(pdev, new_freq) ||
+			    wlan_reg_is_freq_indoor(pdev, new_freq))
+				new_freq = policy_mgr_get_nondfs_preferred_channel(psoc,
+										   concur_mode,
+										   true,
+										   concur_vdev_id);
+		} else {
+			new_freq = wlan_reg_min_6ghz_chan_freq();
+		}
+	}
+	policy_mgr_debug("Restart vdev: %u on freq: %u",
+			 concur_vdev_id, new_freq);
+
+	return policy_mgr_change_sap_channel_with_csa(psoc, concur_vdev_id,
+						      new_freq, bw, true);
+}
+
+void policy_mgr_sta_sap_dfs_enforce_scc(struct wlan_objmgr_psoc *psoc,
+					uint8_t vdev_id)
+{
+	bool is_sap_go_moved_before_sta, move_sap_go_first;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_pdev *pdev;
+	enum policy_mgr_con_mode cur_mode;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid context");
+		return;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_POLICY_MGR_ID);
+	if (!vdev) {
+		policy_mgr_err("vdev is NULL");
+		return;
+	}
+	is_sap_go_moved_before_sta =
+			wlan_vdev_mlme_is_sap_go_move_before_sta(vdev);
+	pdev = wlan_vdev_get_pdev(vdev);
+	wlan_vdev_mlme_set_sap_go_move_before_sta(vdev, false);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
+
+	policy_mgr_get_dfs_sta_sap_go_scc_movement(psoc, &move_sap_go_first);
+	if (!is_sap_go_moved_before_sta || !move_sap_go_first) {
+		policy_mgr_debug("SAP / GO moved before STA: %u INI g_move_sap_go_1st_on_dfs_sta_csa: %u",
+				 is_sap_go_moved_before_sta, move_sap_go_first);
+		return;
+	}
+
+	cur_mode = policy_mgr_get_mode_by_vdev_id(psoc, vdev_id);
+	if (cur_mode != PM_STA_MODE) {
+		policy_mgr_err("CSA received on non-STA connection");
+		return;
+	}
+
+	policy_mgr_debug("Enforce SCC");
+	policy_mgr_check_concurrent_intf_and_restart_sap(psoc, false);
+}
+
 #ifdef WLAN_FEATURE_P2P_P2P_STA
 void policy_mgr_do_go_plus_go_force_scc(struct wlan_objmgr_psoc *psoc,
 					uint8_t vdev_id, uint32_t ch_freq,

+ 16 - 4
core/mac/src/pe/lim/lim_send_sme_rsp_messages.c

@@ -2537,7 +2537,8 @@ lim_process_beacon_tx_success_ind(struct mac_context *mac_ctx, uint16_t msgType,
 				  void *event)
 {
 	struct pe_session *session;
-	bool csa_tx_offload;
+	struct wlan_objmgr_vdev *vdev;
+	bool csa_tx_offload, is_sap_go_moved_before_sta = false;
 	tpSirFirstBeaconTxCompleteInd bcn_ind =
 		(tSirFirstBeaconTxCompleteInd *) event;
 
@@ -2547,11 +2548,21 @@ lim_process_beacon_tx_success_ind(struct mac_context *mac_ctx, uint16_t msgType,
 		return;
 	}
 
-	pe_debug("role: %d swIe: %d opIe: %d switch cnt:%d",
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc,
+						    session->vdev_id,
+						    WLAN_LEGACY_MAC_ID);
+	if (vdev) {
+		is_sap_go_moved_before_sta =
+			wlan_vdev_mlme_is_sap_go_move_before_sta(vdev);
+		wlan_vdev_mlme_set_sap_go_move_before_sta(vdev, false);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
+	}
+	pe_debug("role: %d swIe: %d opIe: %d switch cnt:%d Is SAP / GO Moved before STA: %d",
 		 GET_LIM_SYSTEM_ROLE(session),
 		 session->dfsIncludeChanSwIe,
 		 session->gLimOperatingMode.present,
-		 session->gLimChannelSwitch.switchCount);
+		 session->gLimChannelSwitch.switchCount,
+		 is_sap_go_moved_before_sta);
 
 	if (!LIM_IS_AP_ROLE(session))
 		return;
@@ -2560,7 +2571,8 @@ lim_process_beacon_tx_success_ind(struct mac_context *mac_ctx, uint16_t msgType,
 	if (session->dfsIncludeChanSwIe && !csa_tx_offload &&
 	    ((session->gLimChannelSwitch.switchCount ==
 	      mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt) ||
-	     (session->gLimChannelSwitch.switchCount == 1)))
+	     (session->gLimChannelSwitch.switchCount == 1) ||
+	     is_sap_go_moved_before_sta))
 		lim_process_ap_ecsa_timeout(session);
 
 

+ 6 - 1
core/mac/src/pe/sch/sch_beacon_process.c

@@ -669,7 +669,7 @@ static void __sch_beacon_process_for_session(struct mac_context *mac_ctx,
 	bool ap_constraint_change = false, tpe_change = false;
 	int8_t regMax = 0, maxTxPower = 0;
 	QDF_STATUS status;
-	bool skip_tpe = false;
+	bool skip_tpe = false, is_sap_go_switched_ch;
 	uint8_t programmed_country[REG_ALPHA2_LEN + 1];
 	enum reg_6g_ap_type pwr_type_6g = REG_INDOOR_AP;
 	bool ctry_code_match = false;
@@ -691,6 +691,11 @@ static void __sch_beacon_process_for_session(struct mac_context *mac_ctx,
 	beaconParams.paramChangeBitmap = 0;
 
 	if (LIM_IS_STA_ROLE(session)) {
+		is_sap_go_switched_ch =
+			wlan_vdev_mlme_is_sap_go_move_before_sta(session->vdev);
+		if (is_sap_go_switched_ch)
+			policy_mgr_sta_sap_dfs_enforce_scc(mac_ctx->psoc,
+							   session->vdev_id);
 		if (false == sch_bcn_process_sta(mac_ctx, bcn, rx_pkt_info,
 						 session, &beaconParams,
 						 &sendProbeReq, pMh))