Procházet zdrojové kódy

qcacld-3.0: Avoid duplicated force link command for TDLS

At present, the tdls_handle_link_unforce may be invoked multiple
times even though the link is unforced previously. That causes
sending set link command unnecessarily.
Fix by checking the current link force state to avoid setting link
again.

Change-Id: I1e75fb713b17e6efd8143ebbc5ce59aed0409061
CRs-Fixed: 3640207
Liangwei Dong před 1 rokem
rodič
revize
afa0635590

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

@@ -6356,8 +6356,7 @@ policy_mgr_mlo_sta_set_link_ext(struct wlan_objmgr_psoc *psoc,
 		req->param.link_num[0].num_of_link = num_mlo_vdev - 1;
 	}
 
-	if (ml_is_nlink_service_supported(psoc) &&
-	    reason != MLO_LINK_FORCE_REASON_TDLS) {
+	if (ml_is_nlink_service_supported(psoc)) {
 		status =
 		policy_mgr_mlo_sta_set_link_by_linkid(psoc, vdev, reason,
 						      mode,

+ 5 - 0
components/tdls/core/src/wlan_tdls_main.c

@@ -1026,6 +1026,11 @@ exit:
 #ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
 bool tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
 {
+	if (policy_mgr_is_mlo_in_mode_emlsr(psoc, NULL, NULL)) {
+		tdls_debug("eMLSR STA present. Don't allow TDLS");
+		return false;
+	}
+
 	if (!wlan_psoc_nif_fw_ext2_cap_get(psoc,
 					   WLAN_TDLS_CONCURRENCIES_SUPPORT)) {
 		tdls_debug("fw cap is not advertised");

+ 47 - 23
components/tdls/core/src/wlan_tdls_mgmt.c

@@ -33,6 +33,7 @@
 #include "wlan_policy_mgr_api.h"
 #include <wlan_reg_services_api.h>
 #include <wlan_mlo_mgr_sta.h>
+#include "wlan_mlo_link_force.h"
 
 static
 const char *const tdls_action_frames_type[] = { "TDLS Setup Request",
@@ -403,12 +404,13 @@ exit:
 
 void tdls_set_no_force_vdev(struct wlan_objmgr_vdev *vdev, bool flag)
 {
-	uint8_t i, count = 0;
+	uint8_t i;
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_objmgr_vdev *mlo_vdev;
 	struct wlan_mlo_dev_context *mlo_dev_ctx;
-	uint8_t mlo_vdev_lst[WLAN_UMAC_MLO_MAX_VDEVS];
 	bool is_mlo_vdev;
+	struct ml_nlink_change_event data;
+	QDF_STATUS status;
 
 	if (!vdev)
 		return;
@@ -421,22 +423,32 @@ void tdls_set_no_force_vdev(struct wlan_objmgr_vdev *vdev, bool flag)
 	if (!psoc)
 		return;
 
+	qdf_mem_zero(&data, sizeof(data));
+
 	mlo_dev_ctx = vdev->mlo_dev_ctx;
 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
 		mlo_vdev = mlo_dev_ctx->wlan_vdev_list[i];
+		if (!mlo_vdev)
+			continue;
 
 		/* flag: true means no force all vdevs,
 		 * false means except the current one
 		 */
 		if (!flag && (mlo_vdev == vdev))
 			continue;
-		mlo_vdev_lst[count] = wlan_vdev_get_id(mlo_vdev);
-		count++;
+		data.evt.tdls.link_bitmap |=
+				1 << wlan_vdev_get_link_id(mlo_vdev);
+		data.evt.tdls.mlo_vdev_lst[data.evt.tdls.vdev_count] =
+				wlan_vdev_get_id(mlo_vdev);
+		data.evt.tdls.vdev_count++;
 	}
 
-	policy_mgr_mlo_sta_set_link(psoc, MLO_LINK_FORCE_REASON_TDLS,
-				    MLO_LINK_FORCE_MODE_NO_FORCE,
-				    count, mlo_vdev_lst);
+	data.evt.tdls.mode = MLO_LINK_FORCE_MODE_NO_FORCE;
+	data.evt.tdls.reason = MLO_LINK_FORCE_REASON_TDLS;
+	status = ml_nlink_conn_change_notify(psoc,
+					     wlan_vdev_get_id(vdev),
+					     ml_nlink_tdls_request_evt,
+					     &data);
 }
 #else
 struct wlan_objmgr_vdev *
@@ -879,12 +891,11 @@ tdls_send_mgmt_serialize_callback(struct wlan_serialization_command *cmd,
 #ifdef WLAN_FEATURE_11BE_MLO
 QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
 {
-	uint8_t mlo_vdev_lst[WLAN_UMAC_MLO_MAX_VDEVS] = {-1};
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_objmgr_vdev *mlo_tdls_vdev;
-	uint8_t vdev_count = 0;
 	bool is_mlo_vdev;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct ml_nlink_change_event data;
 
 	is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(req->vdev);
 	if (!is_mlo_vdev)
@@ -902,24 +913,37 @@ QDF_STATUS tdls_set_link_mode(struct tdls_action_frame_request *req)
 		if (mlo_tdls_vdev)
 			return status;
 
-		mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
-		vdev_count = 1;
-
-		status = policy_mgr_mlo_sta_set_link(psoc,
-						     MLO_LINK_FORCE_REASON_TDLS,
-						     MLO_LINK_FORCE_MODE_ACTIVE,
-						     vdev_count, mlo_vdev_lst);
-		if (status == QDF_STATUS_SUCCESS)
+		qdf_mem_zero(&data, sizeof(data));
+		data.evt.tdls.link_bitmap =
+				1 << wlan_vdev_get_link_id(req->vdev);
+		data.evt.tdls.mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
+		data.evt.tdls.vdev_count = 1;
+		data.evt.tdls.mode = MLO_LINK_FORCE_MODE_ACTIVE;
+		data.evt.tdls.reason = MLO_LINK_FORCE_REASON_TDLS;
+		status =
+		ml_nlink_conn_change_notify(psoc,
+					    wlan_vdev_get_id(req->vdev),
+					    ml_nlink_tdls_request_evt,
+					    &data);
+		if (status == QDF_STATUS_SUCCESS ||
+		    status == QDF_STATUS_E_PENDING)
 			req->link_active = true;
 	} else if (req->tdls_mgmt.frame_type == TDLS_MAX_ACTION_CODE) {
-		mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
-		vdev_count = 1;
+		qdf_mem_zero(&data, sizeof(data));
+		data.evt.tdls.link_bitmap =
+				1 << wlan_vdev_get_link_id(req->vdev);
+		data.evt.tdls.mlo_vdev_lst[0] = wlan_vdev_get_id(req->vdev);
+		data.evt.tdls.vdev_count = 1;
+		data.evt.tdls.mode = MLO_LINK_FORCE_MODE_NO_FORCE;
+		data.evt.tdls.reason = MLO_LINK_FORCE_REASON_TDLS;
 		status =
-		    policy_mgr_mlo_sta_set_link(psoc,
-						MLO_LINK_FORCE_REASON_TDLS,
-						MLO_LINK_FORCE_MODE_NO_FORCE,
-						vdev_count, mlo_vdev_lst);
+		ml_nlink_conn_change_notify(psoc,
+					    wlan_vdev_get_id(req->vdev),
+					    ml_nlink_tdls_request_evt,
+					    &data);
 	}
+	if (status == QDF_STATUS_E_PENDING)
+		status = QDF_STATUS_SUCCESS;
 
 	return status;
 }

+ 11 - 0
components/umac/mlme/mlo_mgr/inc/wlan_mlo_link_force.h

@@ -37,6 +37,7 @@
  * @ml_nlink_ap_started_evt: SAP/GO bss started
  * @ml_nlink_ap_stopped_evt: SAP/GO bss stopped
  * @ml_nlink_connection_updated_evt: connection home channel changed
+ * @ml_nlink_tdls_request_evt: tdls request link enable/disable
  */
 enum ml_nlink_change_event_type {
 	ml_nlink_link_switch_start_evt,
@@ -50,12 +51,14 @@ enum ml_nlink_change_event_type {
 	ml_nlink_ap_started_evt,
 	ml_nlink_ap_stopped_evt,
 	ml_nlink_connection_updated_evt,
+	ml_nlink_tdls_request_evt,
 };
 
 /**
  * struct ml_nlink_change_event - connection change event data struct
  * @evt: event parameters
  * @link_switch: link switch start parameters
+ * @tdls: tdls parameters
  */
 struct ml_nlink_change_event {
 	union {
@@ -65,6 +68,13 @@ struct ml_nlink_change_event {
 			uint32_t new_primary_freq;
 			enum wlan_mlo_link_switch_reason reason;
 		} link_switch;
+		struct {
+			uint32_t link_bitmap;
+			uint8_t vdev_count;
+			uint8_t mlo_vdev_lst[WLAN_UMAC_MLO_MAX_VDEVS];
+			enum mlo_link_force_mode mode;
+			enum mlo_link_force_reason reason;
+		} tdls;
 	} evt;
 };
 
@@ -108,6 +118,7 @@ static inline const char *link_evt_to_string(uint32_t evt)
 	CASE_RETURN_STRING(ml_nlink_ap_started_evt);
 	CASE_RETURN_STRING(ml_nlink_ap_stopped_evt);
 	CASE_RETURN_STRING(ml_nlink_connection_updated_evt);
+	CASE_RETURN_STRING(ml_nlink_tdls_request_evt);
 	default:
 		return "Unknown";
 	}

+ 78 - 0
components/umac/mlme/mlo_mgr/src/wlan_mlo_link_force.c

@@ -1976,6 +1976,80 @@ ml_nlink_state_change_handler(struct wlan_objmgr_psoc *psoc,
 	return status;
 }
 
+static QDF_STATUS
+ml_nlink_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
+			    struct wlan_objmgr_vdev *vdev,
+			    enum ml_nlink_change_event_type evt,
+			    struct ml_nlink_change_event *data)
+{
+	struct ml_link_force_state curr_force_state = {0};
+	QDF_STATUS status;
+
+	ml_nlink_get_curr_force_state(psoc, vdev, &curr_force_state);
+
+	switch (data->evt.tdls.mode) {
+	case MLO_LINK_FORCE_MODE_ACTIVE:
+		if ((data->evt.tdls.link_bitmap &
+		    curr_force_state.force_active_bitmap) ==
+		    data->evt.tdls.link_bitmap) {
+			mlo_debug("link_bitmap 0x%x already active, 0x%x",
+				  data->evt.tdls.link_bitmap,
+				  curr_force_state.force_active_bitmap);
+			return QDF_STATUS_SUCCESS;
+		}
+		if (data->evt.tdls.link_bitmap &
+		    (curr_force_state.force_inactive_bitmap |
+		     curr_force_state.curr_dynamic_inactive_bitmap)) {
+			mlo_debug("link_bitmap 0x%x can't be active due to concurrency, 0x%x 0x%x",
+				  data->evt.tdls.link_bitmap,
+				  curr_force_state.force_inactive_bitmap,
+				  curr_force_state.
+				  curr_dynamic_inactive_bitmap);
+			return QDF_STATUS_E_INVAL;
+		}
+		break;
+	case MLO_LINK_FORCE_MODE_NO_FORCE:
+		if (data->evt.tdls.link_bitmap &
+		    curr_force_state.force_inactive_bitmap) {
+			mlo_debug("link_bitmap 0x%x can't be no_force due to concurrency, 0x%x",
+				  data->evt.tdls.link_bitmap,
+				  curr_force_state.force_inactive_bitmap);
+			return QDF_STATUS_E_INVAL;
+		}
+		if (!(data->evt.tdls.link_bitmap &
+			curr_force_state.force_active_bitmap)) {
+			mlo_debug("link_bitmap 0x%x already no force, 0x%x",
+				  data->evt.tdls.link_bitmap,
+				  curr_force_state.force_active_bitmap);
+			return QDF_STATUS_SUCCESS;
+		}
+		break;
+	default:
+		mlo_err("unhandled for tdls force mode %d",
+			data->evt.tdls.mode);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (ml_is_nlink_service_supported(psoc))
+		status = policy_mgr_mlo_sta_set_nlink(
+				psoc, wlan_vdev_get_id(vdev),
+				data->evt.tdls.reason,
+				data->evt.tdls.mode,
+				0,
+				data->evt.tdls.link_bitmap,
+				0,
+				0);
+	else
+		status =
+		policy_mgr_mlo_sta_set_link(psoc,
+					    data->evt.tdls.reason,
+					    data->evt.tdls.mode,
+					    data->evt.tdls.vdev_count,
+					    data->evt.tdls.mlo_vdev_lst);
+
+	return status;
+}
+
 static QDF_STATUS
 ml_nlink_swtich_dynamic_inactive_link(struct wlan_objmgr_psoc *psoc,
 				      struct wlan_objmgr_vdev *vdev)
@@ -2145,6 +2219,10 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 			psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT,
 			evt, data);
 		break;
+	case ml_nlink_tdls_request_evt:
+		status = ml_nlink_tdls_event_handler(
+			psoc, vdev, evt, data);
+		break;
 	default:
 		break;
 	}