Browse Source

qcacmn: MLO Teardown sequence

Trigger MLO teardown and wait for response before proceeding with soc
power down.

Change-Id: Ie1d00408862459b0e5240ef3151a0d969ab65e80
CRs-Fixed: 3102143
Kiran Venkatappa 3 năm trước cách đây
mục cha
commit
9d402b668b

+ 12 - 1
target_if/core/inc/target_if.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 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
@@ -2789,6 +2789,17 @@ QDF_STATUS target_if_mlo_setup_req(struct wlan_objmgr_pdev **pdev,
  */
 QDF_STATUS target_if_mlo_ready(struct wlan_objmgr_pdev **pdev,
 			       uint8_t num_pdevs);
+
+/**
+ * target_if_mlo_teardown_req - API to trigger MLO teardown sequence
+ * @pdev: Array of pointers to pdev object that are part of ML group
+ * @num_pdevs: Number of pdevs in above array
+ * @reason: Reason for triggering teardown
+ *
+ * Return: QDF_STATUS codes
+ */
+QDF_STATUS target_if_mlo_teardown_req(struct wlan_objmgr_pdev **pdev,
+				      uint8_t num_pdevs, uint32_t reason);
 #endif /*WLAN_FEATURE_11BE_MLO && WLAN_MLO_MULTI_CHIP*/
 
 #endif

+ 29 - 0
target_if/core/src/target_if_main.c

@@ -1016,4 +1016,33 @@ QDF_STATUS target_if_mlo_ready(struct wlan_objmgr_pdev **pdev,
 
 	return QDF_STATUS_SUCCESS;
 }
+
+static QDF_STATUS
+target_if_mlo_teardown_send(struct wlan_objmgr_pdev *pdev,
+			    enum wmi_mlo_teardown_reason reason)
+{
+	wmi_unified_t wmi_handle;
+	struct wmi_mlo_teardown_params params = {0};
+
+	wmi_handle = lmac_get_pdev_wmi_handle(pdev);
+	if (!wmi_handle)
+		return QDF_STATUS_E_INVAL;
+
+	params.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
+	params.reason = reason;
+
+	return wmi_mlo_teardown_cmd_send(wmi_handle, &params);
+}
+
+QDF_STATUS target_if_mlo_teardown_req(struct wlan_objmgr_pdev **pdev,
+				      uint8_t num_pdevs,
+				      enum wmi_mlo_teardown_reason reason)
+{
+	uint8_t idx;
+
+	for (idx = 0; idx < num_pdevs; idx++)
+		target_if_mlo_teardown_send(pdev[idx], reason);
+
+	return QDF_STATUS_SUCCESS;
+}
 #endif /*WLAN_FEATURE_11BE_MLO && WLAN_MLO_MULTI_CHIP*/

+ 3 - 0
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -498,6 +498,9 @@ struct wlan_lmac_if_mlme_tx_ops {
 					      uint8_t grp_id);
 	QDF_STATUS (*target_if_mlo_ready)(struct wlan_objmgr_pdev **pdev,
 					  uint8_t num_pdevs);
+	QDF_STATUS (*target_if_mlo_teardown_req)(struct wlan_objmgr_pdev **pdev,
+						 uint8_t num_pdevs,
+						 uint32_t grp_id);
 #endif
 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE
 QDF_STATUS (*vdev_send_set_mac_addr)(struct qdf_mac_addr mac_addr,

+ 6 - 1
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 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
@@ -28,6 +28,9 @@
 #include <wlan_cmn_ieee80211.h>
 #include <wlan_cmn.h>
 #include <wlan_objmgr_global_obj.h>
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
+#include <qdf_event.h>
+#endif
 
 /* MAX MLO dev support */
 #define WLAN_UMAC_MLO_MAX_VDEVS 2
@@ -85,6 +88,7 @@ enum MLO_LINK_STATE {
  * @soc_list[MAX_MLO_CHIPS]: psoc pointers belonging to this group
  * @state[MAX_MLO_LINKS]: MLO link state
  * @state_lock: lock to protect access to link state
+ * @qdf_event_t: event for tearodwn completion
  */
 #define MAX_MLO_LINKS 6
 #define MAX_MLO_CHIPS 3
@@ -98,6 +102,7 @@ struct mlo_setup_info {
 	struct wlan_objmgr_psoc *soc_list[MAX_MLO_CHIPS];
 	enum MLO_LINK_STATE state[MAX_MLO_LINKS];
 	qdf_spinlock_t state_lock;
+	qdf_event_t event;
 };
 
 #define MAX_MLO_GROUP 1

+ 11 - 1
umac/mlo_mgr/inc/wlan_mlo_mgr_setup.h

@@ -1,4 +1,4 @@
-/* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+/* Copyright (c) 2021-2022 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
@@ -67,4 +67,14 @@ void mlo_link_setup_complete(struct wlan_objmgr_pdev *pdev);
  * Return: None.
  */
 void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * mlo_link_teardown_link() - API to trigger teardown
+ * @psoc: Pointer to psoc object
+ * @reason: Reason code for MLO tear down
+ *
+ * Return: QDF_STATUS - success / failure.
+ */
+QDF_STATUS mlo_link_teardown_link(struct wlan_objmgr_psoc *psoc,
+				  uint32_t reason);
 #endif

+ 95 - 1
umac/mlo_mgr/src/wlan_mlo_mgr_setup.c

@@ -1,4 +1,4 @@
-/* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+/* Copyright (c) 2021-2022 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
@@ -152,13 +152,107 @@ void mlo_link_setup_complete(struct wlan_objmgr_pdev *pdev)
 
 qdf_export_symbol(mlo_link_setup_complete);
 
+static QDF_STATUS mlo_find_pdev_idx(struct wlan_objmgr_pdev *pdev,
+				    uint8_t *link_idx)
+{
+	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	uint8_t idx;
+
+	if (!mlo_ctx)
+		return QDF_STATUS_E_FAILURE;
+
+	if (!link_idx)
+		return QDF_STATUS_E_FAILURE;
+
+	for (idx = 0; idx < mlo_ctx->setup_info.tot_links; idx++) {
+		if (mlo_ctx->setup_info.pdev_list[idx] == pdev) {
+			*link_idx = idx;
+			return QDF_STATUS_SUCCESS;
+		}
+	}
+
+	return QDF_STATUS_E_FAILURE;
+}
+
 void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	uint8_t link_idx;
 
 	if (!mlo_ctx)
 		return;
+
+	if (!mlo_ctx->setup_info.num_links) {
+		qdf_err("Delayed response ignore");
+		return;
+	}
+
+	if (mlo_find_pdev_idx(pdev, &link_idx) != QDF_STATUS_SUCCESS) {
+		qdf_info("Failed to find pdev");
+		return;
+	}
+
+	qdf_debug("link idx = %d", link_idx);
+	mlo_ctx->setup_info.pdev_list[link_idx] = NULL;
+	mlo_ctx->setup_info.state[link_idx] = MLO_LINK_TEARDOWN;
+	mlo_ctx->setup_info.num_links--;
+
+	if (!mlo_ctx->setup_info.num_links) {
+		qdf_info("Teardown complete");
+		qdf_event_set(&mlo_ctx->setup_info.event);
+	}
 }
 
 qdf_export_symbol(mlo_link_teardown_complete);
+
+#define MLO_MGR_TEARDOWN_TIMEOUT 3000
+QDF_STATUS mlo_link_teardown_link(struct wlan_objmgr_psoc *psoc,
+				  uint32_t reason)
+{
+	struct wlan_lmac_if_tx_ops *tx_ops;
+	QDF_STATUS status;
+	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+
+	qdf_debug(" %d %d ",
+		  mlo_ctx->setup_info.num_soc,
+		  mlo_ctx->setup_info.num_links);
+
+	if (!mlo_ctx)
+		return QDF_STATUS_E_FAILURE;
+
+	if (!mlo_ctx->setup_info.num_soc)
+		return QDF_STATUS_SUCCESS;
+
+	if (!mlo_ctx->setup_info.num_links) {
+		mlo_ctx->setup_info.num_soc--;
+		return QDF_STATUS_SUCCESS;
+	}
+
+	if (qdf_event_create(&mlo_ctx->setup_info.event) != QDF_STATUS_SUCCESS)
+		return QDF_STATUS_E_FAULT;
+
+	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
+	/* Trigger MLO teardown */
+	if (tx_ops && tx_ops->mops.target_if_mlo_teardown_req) {
+		tx_ops->mops.target_if_mlo_teardown_req(
+				mlo_ctx->setup_info.pdev_list,
+				mlo_ctx->setup_info.num_links,
+				reason);
+	}
+
+	status = qdf_wait_for_event_completion(&mlo_ctx->setup_info.event,
+					       MLO_MGR_TEARDOWN_TIMEOUT);
+	if (status != QDF_STATUS_SUCCESS) {
+		qdf_info("Teardown timeout");
+		mlo_ctx->setup_info.num_links = 0;
+	}
+
+	qdf_event_destroy(&mlo_ctx->setup_info.event);
+
+	mlo_ctx->setup_info.num_soc--;
+
+	return status;
+}
+
+qdf_export_symbol(mlo_link_teardown_link);
 #endif /*WLAN_MLO_MULTI_CHIP*/