Browse Source

qcacld-3.0: Add initial checks for TDLS concurrencies

Check if TDLS is allowed for the current existing concurrency
combination. In below combinations, TDLS is not allowed:
1. MCC on STA vdev
2. STA + STA
3. Total connection count > 3
4. No STA vdev exists

If existing TDLS connection exists when 4th port is coming up,
then teardown the TDLS connection and disable off channel.

Change-Id: Iabe174bedecfa6147bd9de3cb2a3716b63145456
CRs-Fixed: 3435864
Pragaspathi Thilagaraj 2 years ago
parent
commit
37a1c90ea3

+ 2 - 7
components/tdls/core/src/wlan_tdls_cmds_process.c

@@ -1966,10 +1966,7 @@ static QDF_STATUS tdls_config_force_peer(
 			       req->op_class, req->min_bandwidth);
 
 	tdls_set_callback(peer, req->callback);
-
-	tdls_set_ct_mode(soc_obj->soc);
-	if (soc_obj->enable_tdls_connection_tracker)
-		tdls_implicit_enable(vdev_obj);
+	tdls_set_ct_mode(soc_obj->soc, vdev);
 
 	return status;
 error:
@@ -2146,9 +2143,7 @@ QDF_STATUS tdls_process_remove_force_peer(struct tdls_oper_request *req)
 		qdf_mem_free(peer_update_param);
 		goto error;
 	}
-	tdls_set_ct_mode(soc_obj->soc);
-	if (!soc_obj->enable_tdls_connection_tracker)
-		tdls_implicit_disable(vdev_obj);
+	tdls_set_ct_mode(soc_obj->soc, vdev);
 
 error:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);

+ 104 - 75
components/tdls/core/src/wlan_tdls_main.c

@@ -958,6 +958,7 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
 	bool state = false;
 	qdf_freq_t ch_freq;
 	QDF_STATUS status;
+	uint32_t connection_count;
 
 	status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
 	if (QDF_IS_STATUS_ERROR(status))
@@ -979,14 +980,22 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
 		goto exit;
 	}
 
-	if (policy_mgr_get_connection_count(tdls_soc_obj->soc) == 1)
+	connection_count = policy_mgr_get_connection_count(tdls_soc_obj->soc);
+	if (connection_count == 1 ||
+	    (connection_count > 1 &&
+	     tdls_is_concurrency_allowed(tdls_soc_obj->soc))) {
 		state = true;
-	else
+	} else {
 		tdls_warn("Concurrent sessions exist disable TDLS");
+		goto exit;
+	}
 
 	ch_freq = wlan_get_operation_chan_freq(vdev);
-	if (wlan_reg_is_6ghz_chan_freq(ch_freq))
-		state &= tdls_is_6g_freq_allowed(vdev, ch_freq);
+	if (wlan_reg_is_6ghz_chan_freq(ch_freq) &&
+	    !tdls_is_6g_freq_allowed(vdev, ch_freq)) {
+		tdls_debug("6GHz freq:%d not allowed for TDLS", ch_freq);
+		state = false;
+	}
 
 exit:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
@@ -994,72 +1003,105 @@ exit:
 	return state;
 }
 
-/**
- * tdls_set_ct_mode() - Set the tdls connection tracker mode
- * @psoc: psoc context
- *
- * This routine is called to set the tdls connection tracker operation status
- *
- * Return: NONE
- */
-void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc)
+#ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
+bool tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
+{
+	if (!wlan_psoc_nif_fw_ext2_cap_get(psoc,
+					   WLAN_TDLS_CONCURRENCIES_SUPPORT))
+		return false;
+
+	if (policy_mgr_get_connection_count(psoc) >
+	    WLAN_TDLS_MAX_CONCURRENT_VDEV_SUPPORTED)
+		return false;
+
+	if (policy_mgr_mode_specific_connection_count(psoc, PM_STA_MODE,
+						      NULL) > 1) {
+		tdls_debug("More than one STA exist. Don't allow TDLS");
+		return false;
+	}
+
+	if (policy_mgr_current_concurrency_is_mcc(psoc)) {
+		tdls_debug("Base channel MCC. Don't allow TDLS");
+		return false;
+	}
+
+	/*
+	 * Don't enable TDLS for P2P_CLI in concurrency cases
+	 */
+	if (policy_mgr_get_connection_count(psoc) > 1 &&
+	    !policy_mgr_mode_specific_connection_count(psoc, PM_STA_MODE,
+						       NULL))
+		return false;
+
+	return true;
+}
+#endif
+
+void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc,
+		      struct wlan_objmgr_vdev *vdev)
 {
-	bool state = false;
 	struct tdls_soc_priv_obj *tdls_soc_obj;
+	struct tdls_vdev_priv_obj *tdls_vdev_obj;
+	uint32_t tdls_feature_flags = 0, sta_count, p2p_count;
+	bool state = false;
+	QDF_STATUS status;
 
-	tdls_soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
-	if (!tdls_soc_obj)
+	if (!tdls_check_is_tdls_allowed(vdev))
 		return;
 
-	/* If any concurrency is detected, skip tdls pkt tracker */
-	if (policy_mgr_get_connection_count(psoc) > 1) {
+	status = tdls_get_vdev_objects(vdev, &tdls_vdev_obj, &tdls_soc_obj);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		tdls_err("Failed to get TDLS objects");
 		state = false;
 		goto set_state;
 	}
 
+	tdls_feature_flags = tdls_soc_obj->tdls_configs.tdls_feature_flags;
 	if (TDLS_SUPPORT_DISABLED == tdls_soc_obj->tdls_current_mode ||
 	    TDLS_SUPPORT_SUSPENDED == tdls_soc_obj->tdls_current_mode ||
-	    !TDLS_IS_IMPLICIT_TRIG_ENABLED(
-			tdls_soc_obj->tdls_configs.tdls_feature_flags)) {
-		state = false;
-		goto set_state;
-	} else if (policy_mgr_mode_specific_connection_count(psoc,
-							     PM_STA_MODE,
-							     NULL) == 1) {
-		state = true;
-	} else if (policy_mgr_mode_specific_connection_count(psoc,
-							     PM_P2P_CLIENT_MODE,
-							     NULL) == 1){
-		state = true;
-	} else {
+	    !TDLS_IS_IMPLICIT_TRIG_ENABLED(tdls_feature_flags)) {
 		state = false;
 		goto set_state;
 	}
 
-	/* In case of TDLS external control, peer should be added
-	 * by the user space to start connection tracker.
-	 */
-	if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(
-			tdls_soc_obj->tdls_configs.tdls_feature_flags)) {
-		if (tdls_soc_obj->tdls_external_peer_count)
-			state = true;
-		else
+	sta_count = policy_mgr_mode_specific_connection_count(psoc, PM_STA_MODE,
+							      NULL);
+	p2p_count =
+		policy_mgr_mode_specific_connection_count(psoc,
+							  PM_P2P_CLIENT_MODE,
+							  NULL);
+	if (sta_count == 1 ||
+	    (policy_mgr_get_connection_count(psoc) == 1 && p2p_count == 1)) {
+		state = true;
+		/*
+		 * In case of TDLS external control, peer should be added
+		 * by the user space to start connection tracker.
+		 */
+		if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(tdls_feature_flags) &&
+		    !tdls_soc_obj->tdls_external_peer_count)
 			state = false;
+
+		goto set_state;
 	}
 
+	state = false;
+
 set_state:
 	tdls_soc_obj->enable_tdls_connection_tracker = state;
+	if (tdls_soc_obj->enable_tdls_connection_tracker)
+		tdls_implicit_enable(tdls_vdev_obj);
+	else
+		tdls_implicit_disable(tdls_vdev_obj);
 
-	tdls_debug("enable_tdls_connection_tracker %d",
-		 tdls_soc_obj->enable_tdls_connection_tracker);
+	tdls_debug("enable_tdls_connection_tracker %d current_mode:%d feature_flags:0x%x",
+		   tdls_soc_obj->enable_tdls_connection_tracker,
+		   tdls_soc_obj->tdls_current_mode, tdls_feature_flags);
 }
 
 QDF_STATUS
 tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
 {
-	struct tdls_vdev_priv_obj *tdls_priv_vdev;
 	struct wlan_objmgr_vdev *tdls_obj_vdev;
-	struct tdls_soc_priv_obj *tdls_priv_soc;
 
 	if (!psoc) {
 		tdls_err("psoc: %pK", psoc);
@@ -1078,11 +1120,7 @@ tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
 	}
 
 	tdls_debug("enter ");
-	tdls_set_ct_mode(psoc);
-	if (tdls_get_vdev_objects(tdls_obj_vdev, &tdls_priv_vdev,
-				  &tdls_priv_soc) == QDF_STATUS_SUCCESS &&
-	    tdls_priv_soc->enable_tdls_connection_tracker)
-		tdls_implicit_enable(tdls_priv_vdev);
+	tdls_set_ct_mode(psoc, tdls_obj_vdev);
 
 	wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
 
@@ -1137,21 +1175,23 @@ struct wlan_objmgr_vdev *tdls_get_vdev(struct wlan_objmgr_psoc *psoc,
 {
 	uint32_t vdev_id;
 
-	if (policy_mgr_get_connection_count(psoc) > 1)
+	if (policy_mgr_get_connection_count(psoc) > 1 &&
+	    !tdls_is_concurrency_allowed(psoc))
 		return NULL;
 
 	vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_STA_MODE);
-
 	if (WLAN_INVALID_VDEV_ID != vdev_id)
-		return wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
-							    vdev_id,
+		return wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
 							    dbg_id);
-
+	/*
+	 * For P2P_Client mode, TDLS is not supported on concurrency
+	 * so return P2P_client vdev only if P2P client mode exists without
+	 * any concurreny
+	 */
 	vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_P2P_CLIENT_MODE);
-
-	if (WLAN_INVALID_VDEV_ID != vdev_id)
-		return wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
-							    vdev_id,
+	if (WLAN_INVALID_VDEV_ID != vdev_id &&
+	    policy_mgr_get_connection_count(psoc) == 1)
+		return wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
 							    dbg_id);
 
 	return NULL;
@@ -1369,9 +1409,7 @@ tdls_process_sta_connect(struct tdls_sta_notify_params *notify)
 				       notify->session_id);
 
 	/* check and set the connection tracker */
-	tdls_set_ct_mode(tdls_soc_obj->soc);
-	if (tdls_soc_obj->enable_tdls_connection_tracker)
-		tdls_implicit_enable(tdls_vdev_obj);
+	tdls_set_ct_mode(tdls_soc_obj->soc, notify->vdev);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -1458,16 +1496,11 @@ tdls_process_sta_disconnect(struct tdls_sta_notify_params *notify)
 	}
 
 	/* Check and set the connection tracker and implicit timers */
-	tdls_set_ct_mode(curr_tdls_soc->soc);
-	if (curr_tdls_soc->enable_tdls_connection_tracker)
-		tdls_implicit_enable(curr_tdls_vdev);
-	else
-		tdls_implicit_disable(curr_tdls_vdev);
-
-	/* release the vdev ref , if temp vdev was acquired */
-	if (temp_vdev)
+	if (temp_vdev) {
+		tdls_set_ct_mode(curr_tdls_soc->soc, temp_vdev);
 		wlan_objmgr_vdev_release_ref(temp_vdev,
 					     WLAN_TDLS_NB_ID);
+	}
 
 	return status;
 }
@@ -1657,18 +1690,15 @@ static void tdls_set_mode_in_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
 		/* If tdls implicit mode is disabled, then
 		 * stop the connection tracker.
 		 */
-		tdls_soc->enable_tdls_connection_tracker =
-			false;
-	} else if (TDLS_SUPPORT_EXP_TRIG_ONLY ==
-		   tdls_mode) {
+		tdls_soc->enable_tdls_connection_tracker = false;
+	} else if (TDLS_SUPPORT_EXP_TRIG_ONLY == tdls_mode) {
 		clear_bit((unsigned long)source,
 			  &tdls_soc->tdls_source_bitmap);
 		tdls_implicit_disable(tdls_vdev);
 		/* If tdls implicit mode is disabled, then
 		 * stop the connection tracker.
 		 */
-		tdls_soc->enable_tdls_connection_tracker =
-			false;
+		tdls_soc->enable_tdls_connection_tracker = false;
 
 		/*
 		 * Check if any TDLS source bit is set and if
@@ -1679,7 +1709,6 @@ static void tdls_set_mode_in_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
 			return;
 	}
 	tdls_debug("exit ");
-
 }
 
 /**

+ 20 - 2
components/tdls/core/src/wlan_tdls_main.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -566,12 +566,14 @@ QDF_STATUS tdls_get_vdev_objects(struct wlan_objmgr_vdev *vdev,
 /**
  * tdls_set_ct_mode() - Set the tdls connection tracker mode
  * @psoc: objmgr psoc object
+ * @vdev: Pointer to vdev object
  *
  * This routine is called to set the tdls connection tracker operation status
  *
  * Return: NONE
  */
-void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc);
+void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc,
+		      struct wlan_objmgr_vdev *vdev);
 
 /**
  * tdls_set_operation_mode() - set tdls operating mode
@@ -825,4 +827,20 @@ QDF_STATUS tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
 uint8_t tdls_get_opclass_from_bandwidth(struct wlan_objmgr_vdev *vdev,
 					qdf_freq_t freq, uint8_t bw_offset,
 					uint8_t *reg_bw_offset);
+
+#ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
+/**
+ * tdls_is_concurrency_allowed() - Is TDLS allowed with the current concurrency
+ * @psoc: Pointer to PSOC
+ *
+ * Return: True or False
+ */
+bool tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc);
+#else
+static inline bool
+tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
+#endif /* WLAN_FEATURE_TDLS_CONCURRENCIES */
 #endif

+ 1 - 1
components/tdls/dispatcher/inc/wlan_tdls_public_structs.h

@@ -54,7 +54,7 @@
 #define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX      165
 #define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEF      36
 #define WLAN_TDLS_PREFERRED_OFF_CHANNEL_FRQ_DEF     5180
-
+#define WLAN_TDLS_MAX_CONCURRENT_VDEV_SUPPORTED      3
 
 #define AC_PRIORITY_NUM                 4