|
@@ -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*/
|