Browse Source

qcacld-3.0: Handle link removal flag on vdev

Add APIs to set/clear link removal flag on vdev object.
If link is removed, drop the disassoc or deauth frame for
the vdev.
If disconnect start is indicated, stop the reconfig timer.
Clear the link removal flag on disconnect complete.

Change-Id: I729621aec36b82de6e88970675b020a2c5721e68
CRs-Fixed: 3352779
Liangwei Dong 2 năm trước cách đây
mục cha
commit
7af7c4e45a

+ 75 - 1
components/mlme/core/inc/wlan_mlme_main.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-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
@@ -465,6 +465,7 @@ struct mlme_ap_config {
  * @connect_info: mlme connect information
  * @wait_key_timer: wait key timer
  * @eht_config: Eht capability configuration
+ * @is_mlo_sta_link_removed: link on vdev has been removed by AP
  * @last_delba_sent_time: Last delba sent time to handle back to back delba
  *			  requests from some IOT APs
  * @ba_2k_jump_iot_ap: This is set to true if connected to the ba 2k jump IOT AP
@@ -519,6 +520,9 @@ struct mlme_legacy_priv {
 	struct wait_for_key_timer wait_key_timer;
 #ifdef WLAN_FEATURE_11BE
 	tDot11fIEeht_cap eht_config;
+#endif
+#if defined(WLAN_FEATURE_11BE_MLO)
+	bool is_mlo_sta_link_removed;
 #endif
 	qdf_time_t last_delba_sent_time;
 	bool ba_2k_jump_iot_ap;
@@ -1236,6 +1240,76 @@ QDF_STATUS
 wlan_set_sap_user_config_freq(struct wlan_objmgr_vdev *vdev,
 			      qdf_freq_t freq);
 
+#if defined(WLAN_FEATURE_11BE_MLO)
+/**
+ * wlan_clear_mlo_sta_link_removed_flag() - Clear link removal flag on all
+ * vdev of same ml dev
+ * @vdev: pointer to vdev
+ *
+ * Return: void
+ */
+void wlan_clear_mlo_sta_link_removed_flag(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_set_vdev_link_removed_flag_by_vdev_id() - Set link removal flag
+ * on vdev
+ * @psoc: psoc object
+ * @vdev_id: vdev id
+ * @removed: link removal flag
+ *
+ * Return: QDF_STATUS_SUCCESS if success, otherwise error code
+ */
+QDF_STATUS
+wlan_set_vdev_link_removed_flag_by_vdev_id(struct wlan_objmgr_psoc *psoc,
+					   uint8_t vdev_id, bool removed);
+
+/**
+ * wlan_get_vdev_link_removed_flag_by_vdev_id() - Get link removal flag
+ * of vdev
+ * @psoc: psoc object
+ * @vdev_id: vdev id
+ *
+ * Return: true if link is removed on vdev, otherwise false.
+ */
+bool
+wlan_get_vdev_link_removed_flag_by_vdev_id(struct wlan_objmgr_psoc *psoc,
+					   uint8_t vdev_id);
+
+/**
+ * wlan_drop_mgmt_frame_on_link_removal() - Check mgmt frame
+ * allow dropped due to link removal
+ * @vdev: pointer to vdev
+ *
+ * Return: true if frame can be dropped.
+ */
+bool wlan_drop_mgmt_frame_on_link_removal(struct wlan_objmgr_vdev *vdev);
+#else
+static inline void
+wlan_clear_mlo_sta_link_removed_flag(struct wlan_objmgr_vdev *vdev)
+{
+}
+
+static inline QDF_STATUS
+wlan_set_vdev_link_removed_flag_by_vdev_id(struct wlan_objmgr_psoc *psoc,
+					   uint8_t vdev_id, bool removed)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline bool
+wlan_get_vdev_link_removed_flag_by_vdev_id(struct wlan_objmgr_psoc *psoc,
+					   uint8_t vdev_id)
+{
+	return false;
+}
+
+static inline bool
+wlan_drop_mgmt_frame_on_link_removal(struct wlan_objmgr_vdev *vdev)
+{
+	return false;
+}
+#endif
+
 #ifdef CONFIG_BAND_6GHZ
 /**
  * wlan_get_tpc_update_required_for_sta() - Get the tpc update required config

+ 143 - 0
components/mlme/core/src/wlan_mlme_main.c

@@ -32,6 +32,7 @@
 #include <wlan_mlo_mgr_cmn.h>
 #include "wlan_mlme_ucfg_api.h"
 #include "wifi_pos_ucfg_i.h"
+#include "wlan_mlo_mgr_sta.h"
 
 #define NUM_OF_SOUNDING_DIMENSIONS     1 /*Nss - 1, (Nss = 2 for 2x2)*/
 
@@ -1768,6 +1769,148 @@ static void mlme_init_sta_mlo_cfg(struct wlan_objmgr_psoc *psoc,
 	sta->mlo_max_simultaneous_links =
 		cfg_default(CFG_MLO_MAX_SIMULTANEOUS_LINKS);
 }
+
+static bool
+wlan_get_vdev_link_removed_flag(struct wlan_objmgr_vdev *vdev)
+{
+	struct mlme_legacy_priv *mlme_priv;
+	bool is_mlo_link_removed;
+
+	if (!mlo_is_mld_sta(vdev))
+		return false;
+
+	wlan_vdev_obj_lock(vdev);
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv) {
+		wlan_vdev_obj_unlock(vdev);
+		mlme_legacy_err("vdev legacy private object is NULL");
+		return false;
+	}
+
+	is_mlo_link_removed = mlme_priv->is_mlo_sta_link_removed;
+	wlan_vdev_obj_unlock(vdev);
+
+	return is_mlo_link_removed;
+}
+
+bool wlan_get_vdev_link_removed_flag_by_vdev_id(struct wlan_objmgr_psoc *psoc,
+						uint8_t vdev_id)
+{
+	struct wlan_objmgr_vdev *vdev;
+	bool is_mlo_link_removed;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_MLME_OBJMGR_ID);
+	if (!vdev) {
+		mlme_legacy_err("get vdev failed for id %d", vdev_id);
+		return false;
+	}
+
+	is_mlo_link_removed = wlan_get_vdev_link_removed_flag(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
+
+	return is_mlo_link_removed;
+}
+
+static QDF_STATUS
+wlan_set_vdev_link_removed_flag(struct wlan_objmgr_vdev *vdev, bool removed)
+{
+	struct mlme_legacy_priv *mlme_priv;
+
+	if (!vdev) {
+		mlme_legacy_err("vdev NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (!mlo_is_mld_sta(vdev)) {
+		mlme_legacy_debug("vdev not mld sta");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	wlan_vdev_obj_lock(vdev);
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv) {
+		wlan_vdev_obj_unlock(vdev);
+		mlme_legacy_err("vdev legacy private object is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (removed == mlme_priv->is_mlo_sta_link_removed) {
+		wlan_vdev_obj_unlock(vdev);
+		return QDF_STATUS_SUCCESS;
+	}
+
+	mlme_legacy_debug("mlo sta vdev %d link removed flag %d",
+			  wlan_vdev_get_id(vdev), removed);
+	mlme_priv->is_mlo_sta_link_removed = removed;
+	wlan_vdev_obj_unlock(vdev);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_set_vdev_link_removed_flag_by_vdev_id(struct wlan_objmgr_psoc *psoc,
+					   uint8_t vdev_id, bool removed)
+{
+	struct wlan_objmgr_vdev *vdev;
+	QDF_STATUS status;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_MLME_OBJMGR_ID);
+	if (!vdev) {
+		mlme_legacy_err("vdev null for id %d", vdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (!mlo_is_mld_sta(vdev)) {
+		mlme_legacy_debug("vdev %d not mld sta", vdev_id);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	status = wlan_set_vdev_link_removed_flag(vdev, removed);
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
+
+	return status;
+}
+
+void wlan_clear_mlo_sta_link_removed_flag(struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0};
+	uint16_t vdev_count = 0;
+	uint8_t i;
+
+	if (!vdev || !mlo_is_mld_sta(vdev))
+		return;
+
+	mlo_get_ml_vdev_list(vdev, &vdev_count, wlan_vdev_list);
+	if (!vdev_count) {
+		mlme_legacy_err("vdev num 0 in mld dev");
+		return;
+	}
+
+	for (i = 0; i < vdev_count; i++) {
+		if (!wlan_vdev_list[i]) {
+			mlme_legacy_err("vdev is null in mld");
+			goto release_ref;
+		}
+
+		wlan_set_vdev_link_removed_flag(wlan_vdev_list[i], false);
+	}
+
+release_ref:
+	for (i = 0; i < vdev_count; i++)
+		mlo_release_vdev_ref(wlan_vdev_list[i]);
+}
+
+bool wlan_drop_mgmt_frame_on_link_removal(struct wlan_objmgr_vdev *vdev)
+{
+	if (!vdev || !mlo_is_mld_sta(vdev))
+		return false;
+
+	return wlan_get_vdev_link_removed_flag(vdev);
+}
 #else
 static void mlme_init_sta_mlo_cfg(struct wlan_objmgr_psoc *psoc,
 				  struct wlan_mlme_sta_cfg *sta)

+ 2 - 0
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c

@@ -71,6 +71,8 @@ QDF_STATUS cm_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
 		return cm_roam_stop_req(psoc, vdev_id,
 					REASON_ROAM_SYNCH_FAILED, NULL, false);
 	}
+	mlo_sta_stop_reconfig_timer(vdev);
+	wlan_clear_mlo_sta_link_removed_flag(vdev);
 
 	status = cm_sm_deliver_event(vdev, WLAN_CM_SM_EV_ROAM_SYNC,
 				     event_data_len, event);

+ 3 - 2
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_disconnect.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 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 above
@@ -71,7 +71,7 @@ QDF_STATUS cm_disconnect_start_ind(struct wlan_objmgr_vdev *vdev,
 		mlme_err("vdev_id: %d psoc not found", req->vdev_id);
 		return QDF_STATUS_E_INVAL;
 	}
-
+	mlo_sta_stop_reconfig_timer(vdev);
 	if (cm_csr_is_ss_wait_for_key(req->vdev_id)) {
 		mlme_debug("Stop Wait for key timer");
 		cm_stop_wait_for_key_timer(psoc, req->vdev_id);
@@ -242,6 +242,7 @@ cm_disconnect_complete_ind(struct wlan_objmgr_vdev *vdev,
 	cm_disconnect_diag_event(vdev, rsp);
 	wlan_tdls_notify_sta_disconnect(vdev_id, false, false, vdev);
 	policy_mgr_decr_session_set_pcl(psoc, op_mode, vdev_id);
+	wlan_clear_mlo_sta_link_removed_flag(vdev);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 8 - 1
core/mac/src/pe/lim/lim_process_deauth_frame.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-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
@@ -82,6 +82,13 @@ lim_process_deauth_frame(struct mac_context *mac, uint8_t *pRxPacketInfo,
 		return ;
 	}
 
+	if (LIM_IS_STA_ROLE(pe_session) &&
+	    wlan_drop_mgmt_frame_on_link_removal(pe_session->vdev)) {
+		pe_debug("Received deauth Frame when link removed on vdev %d",
+			 wlan_vdev_get_id(pe_session->vdev));
+		return;
+	}
+
 	if (LIM_IS_STA_ROLE(pe_session) &&
 	    !(lim_is_sb_disconnect_allowed(pe_session) ||
 	      (pe_session->limMlmState == eLIM_MLM_WT_SAE_AUTH_STATE &&

+ 8 - 1
core/mac/src/pe/lim/lim_process_disassoc_frame.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-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
@@ -100,6 +100,13 @@ lim_process_disassoc_frame(struct mac_context *mac, uint8_t *pRxPacketInfo,
 		return;
 	}
 
+	if (LIM_IS_STA_ROLE(pe_session) &&
+	    wlan_drop_mgmt_frame_on_link_removal(pe_session->vdev)) {
+		pe_debug("Received Disassoc Frame when link removed on vdev %d",
+			 wlan_vdev_get_id(pe_session->vdev));
+		return;
+	}
+
 	if (LIM_IS_STA_ROLE(pe_session) &&
 	    !lim_is_sb_disconnect_allowed(pe_session)) {
 		if (!(mac->lim.disassocMsgCnt & 0xF)) {