diff --git a/target_if/core/inc/target_if.h b/target_if/core/inc/target_if.h index 0b1a87eb41..f56cceecbd 100644 --- a/target_if/core/inc/target_if.h +++ b/target_if/core/inc/target_if.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -2764,6 +2765,27 @@ uint16_t target_if_pdev_get_hw_link_id */ void target_pdev_set_hw_link_id (struct wlan_objmgr_pdev *pdev, uint16_t hw_link_id); + +/** + * target_if_mlo_setup_req - API to trigger MLO setup sequence + * @pdev: Array of pointers to pdev object that are part of ML group + * @num_pdevs: Number of pdevs in above array + * @grp_id: ML Group ID + * + * Return: QDF_STATUS codes + */ +QDF_STATUS target_if_mlo_setup_req(struct wlan_objmgr_pdev **pdev, + uint8_t num_pdevs, uint8_t grp_id); + +/** + * target_if_mlo_ready - API to send MLO ready + * @pdev: Array of pointers to pdev object that are part of ML group + * @num_pdevs: Number of pdevs in above array + * + * Return: QDF_STATUS codes + */ +QDF_STATUS target_if_mlo_ready(struct wlan_objmgr_pdev **pdev, + uint8_t num_pdevs); #endif /*WLAN_FEATURE_11BE_MLO && WLAN_MLO_MULTI_CHIP*/ #endif diff --git a/target_if/core/src/target_if_main.c b/target_if/core/src/target_if_main.c index d8f49c6c43..7e1e6c4da2 100644 --- a/target_if/core/src/target_if_main.c +++ b/target_if/core/src/target_if_main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2021 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 @@ -99,6 +100,8 @@ #include #endif /* WLAN_MGMT_RX_REO_SUPPORT */ +#include "wmi_unified_api.h" + static struct target_if_ctx *g_target_if_ctx; struct target_if_ctx *target_if_get_ctx() @@ -915,4 +918,68 @@ void target_pdev_set_hw_link_id(struct wlan_objmgr_pdev *pdev, tgt_pdev_info->hw_link_id = hw_link_id; } + +static QDF_STATUS target_if_mlo_setup_send(struct wlan_objmgr_pdev *pdev, + struct wlan_objmgr_pdev **pdev_list, + uint8_t num_links, uint8_t grp_id) +{ + wmi_unified_t wmi_handle; + struct wmi_mlo_setup_params params = {0}; + uint8_t idx, num_valid_links = 0; + + wmi_handle = lmac_get_pdev_wmi_handle(pdev); + if (!wmi_handle) + return QDF_STATUS_E_INVAL; + + params.mld_grp_id = grp_id; + params.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + + for (idx = 0; idx < num_links; idx++) { + if (pdev == pdev_list[idx]) + continue; + + params.partner_links[num_valid_links] = + target_if_pdev_get_hw_link_id(pdev_list[idx]); + num_valid_links++; + } + params.num_valid_hw_links = num_valid_links; + + return wmi_mlo_setup_cmd_send(wmi_handle, ¶ms); +} + +QDF_STATUS target_if_mlo_setup_req(struct wlan_objmgr_pdev **pdev, + uint8_t num_pdevs, uint8_t grp_id) +{ + uint8_t idx; + + for (idx = 0; idx < num_pdevs; idx++) + target_if_mlo_setup_send(pdev[idx], pdev, num_pdevs, grp_id); + + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_mlo_ready_send(struct wlan_objmgr_pdev *pdev) +{ + wmi_unified_t wmi_handle; + struct wmi_mlo_ready_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); + + return wmi_mlo_ready_cmd_send(wmi_handle, ¶ms); +} + +QDF_STATUS target_if_mlo_ready(struct wlan_objmgr_pdev **pdev, + uint8_t num_pdevs) +{ + uint8_t idx; + + for (idx = 0; idx < num_pdevs; idx++) + target_if_mlo_ready_send(pdev[idx]); + + return QDF_STATUS_SUCCESS; +} #endif /*WLAN_FEATURE_11BE_MLO && WLAN_MLO_MULTI_CHIP*/ diff --git a/target_if/init_deinit/src/init_event_handler.c b/target_if/init_deinit/src/init_event_handler.c index 29b604e045..ff4869efe5 100644 --- a/target_if/init_deinit/src/init_event_handler.c +++ b/target_if/init_deinit/src/init_event_handler.c @@ -34,6 +34,10 @@ #include #include #include +#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) +#include +#include +#endif static void init_deinit_set_send_init_cmd(struct wlan_objmgr_psoc *psoc, struct target_psoc_info *tgt_hdl) @@ -531,6 +535,38 @@ static int init_deinit_service_available_handler(ol_scn_t scn_handle, return 0; } +#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) +static void init_deinit_mlo_update_soc_ready(struct wlan_objmgr_psoc *psoc) +{ + mlo_setup_update_soc_ready(wlan_psoc_get_id(psoc)); +} + +static void init_deinit_send_ml_link_ready(struct wlan_objmgr_psoc *psoc, + void *object, void *arg) +{ + struct wlan_objmgr_pdev *pdev = object; + + qdf_assert_always(psoc); + qdf_assert_always(pdev); + + mlo_setup_link_ready(pdev); +} + +static void init_deinit_mlo_update_pdev_ready(struct wlan_objmgr_psoc *psoc, + uint8_t num_radios) +{ + wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, + init_deinit_send_ml_link_ready, + NULL, 0, WLAN_INIT_DEINIT_ID); +} +#else +static void init_deinit_mlo_update_soc_ready(struct wlan_objmgr_psoc *psoc) +{} +static void init_deinit_mlo_update_pdev_ready(struct wlan_objmgr_psoc *psoc, + uint8_t num_radios) +{} +#endif /*WLAN_FEATURE_11BE_MLO && WLAN_MLO_MULTI_CHIP*/ + /* MAC address fourth byte index */ #define MAC_BYTE_4 4 @@ -609,6 +645,8 @@ static int init_deinit_ready_event_handler(ol_scn_t scn_handle, goto exit; } + init_deinit_mlo_update_soc_ready(psoc); + num_radios = target_psoc_get_num_radios(tgt_hdl); if ((ready_ev.num_total_peer != 0) && @@ -726,6 +764,7 @@ static int init_deinit_ready_event_handler(ol_scn_t scn_handle, wlan_psoc_set_hw_macaddr(psoc, myaddr); } + init_deinit_mlo_update_pdev_ready(psoc, num_radios); out: target_if_btcoex_cfg_enable(psoc, tgt_hdl, event); tgt_hdl->info.wmi_ready = TRUE; @@ -735,6 +774,108 @@ exit: return 0; } +#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) +static int init_deinit_mlo_setup_comp_event_handler(ol_scn_t scn_handle, + uint8_t *event, + uint32_t data_len) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + struct target_psoc_info *tgt_hdl; + struct wmi_unified *wmi_handle; + struct wmi_mlo_setup_complete_params params; + + if (!scn_handle) { + target_if_err("scn handle NULL"); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn_handle); + if (!psoc) { + target_if_err("psoc is null"); + return -EINVAL; + } + + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_hdl) { + target_if_err("target_psoc_info is null"); + return -EINVAL; + } + wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); + + if (wmi_extract_mlo_setup_cmpl_event(wmi_handle, event, ¶ms) != + QDF_STATUS_SUCCESS) + return -EINVAL; + + pdev = wlan_objmgr_get_pdev_by_id(psoc, params.pdev_id, + WLAN_INIT_DEINIT_ID); + if (pdev) { + mlo_link_setup_complete(pdev); + wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID); + } + + return 0; +} + +static int init_deinit_mlo_teardown_comp_event_handler(ol_scn_t scn_handle, + uint8_t *event, + uint32_t data_len) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + struct target_psoc_info *tgt_hdl; + struct wmi_unified *wmi_handle; + struct wmi_mlo_teardown_cmpl_params params; + + if (!scn_handle) { + target_if_err("scn handle NULL"); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn_handle); + if (!psoc) { + target_if_err("psoc is null"); + return -EINVAL; + } + + tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); + if (!tgt_hdl) { + target_if_err("target_psoc_info is null"); + return -EINVAL; + } + wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); + + if (wmi_extract_mlo_teardown_cmpl_event(wmi_handle, event, ¶ms) != + QDF_STATUS_SUCCESS) + return -EINVAL; + + pdev = wlan_objmgr_get_pdev_by_id(psoc, params.pdev_id, + WLAN_INIT_DEINIT_ID); + if (pdev) { + mlo_link_teardown_complete(pdev); + wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID); + } + + return 0; +} + +static QDF_STATUS init_deinit_register_mlo_ev_handlers(wmi_unified_t wmi_handle) +{ + wmi_unified_register_event(wmi_handle, + wmi_mlo_setup_complete_event_id, + init_deinit_mlo_setup_comp_event_handler); + wmi_unified_register_event(wmi_handle, + wmi_mlo_teardown_complete_event_id, + init_deinit_mlo_teardown_comp_event_handler); + + return QDF_STATUS_SUCCESS; +} +#else +static QDF_STATUS init_deinit_register_mlo_ev_handlers(wmi_unified_t wmi_handle) +{ + return QDF_STATUS_SUCCESS; +} +#endif /*WLAN_FEATURE_11BE_MLO && WLAN_MLO_MULTI_CHIP*/ QDF_STATUS init_deinit_register_tgt_psoc_ev_handlers( struct wlan_objmgr_psoc *psoc) @@ -777,6 +918,7 @@ QDF_STATUS init_deinit_register_tgt_psoc_ev_handlers( wmi_service_ready_ext2_event_id, init_deinit_service_ext2_ready_event_handler, WMI_RX_WORK_CTX); + retval = init_deinit_register_mlo_ev_handlers(wmi_handle); return retval; diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index 7c0f74e7c3..e152b5bd93 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -484,6 +484,11 @@ struct wlan_lmac_if_mlme_tx_ops { enum wlan_vdev_mgr_tgt_if_rsp_bit clear_bit); #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) uint16_t (*get_hw_link_id)(struct wlan_objmgr_pdev *pdev); + QDF_STATUS (*target_if_mlo_setup_req)(struct wlan_objmgr_pdev **pdev, + uint8_t num_pdevs, + uint8_t grp_id); + QDF_STATUS (*target_if_mlo_ready)(struct wlan_objmgr_pdev **pdev, + uint8_t num_pdevs); #endif }; diff --git a/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h b/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h index 2cc315e298..dd61dbbaa5 100644 --- a/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h +++ b/umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h @@ -59,13 +59,47 @@ struct vdev_mlme_obj; #define STA_PROFILE_SUB_ELEM_ID 0 #define PER_STA_PROF_MAC_ADDR_START 4 +#ifdef WLAN_MLO_MULTI_CHIP /* - * struct mlo_setup_info - * To store the MLO setup related information + * enum MLO_LINK_STATE – MLO link state enums + * @MLO_LINK_SETUP_INIT - MLO link SETUP exchange not yet done + * @MLO_LINK_SETUP_DONE - MLO link SETUP exchange started + * @MLO_LINK_READY - MLO link SETUP done and READY sent + * @MLO_LINK_TEARDOWN - MLO teardown done. */ -struct mlo_setup_info { +enum MLO_LINK_STATE { + MLO_LINK_SETUP_INIT, + MLO_LINK_SETUP_DONE, + MLO_LINK_READY, + MLO_LINK_TEARDOWN }; +/** + * struct mlo_setup_info: MLO setup status per link + * @ml_grp_id: Unique id for ML grouping of Pdevs/links + * @tot_socs: Total number of soc participating in ML group + * @num_soc: Number of soc ready or probed + * @tot_links: Total links in ML group + * @num_links: Number of links probed in ML group + * @pdev_list[MAX_MLO_LINKS]: pdev pointers belonging to this group + * @state[MAX_MLO_LINKS]: MLO link state + * @state_lock: lock to protect access to link state + */ +#define MAX_MLO_LINKS 6 +struct mlo_setup_info { + uint8_t ml_grp_id; + uint8_t tot_socs; + uint8_t num_soc; + uint8_t tot_links; + uint8_t num_links; + struct wlan_objmgr_pdev *pdev_list[MAX_MLO_LINKS]; + enum MLO_LINK_STATE state[MAX_MLO_LINKS]; + qdf_spinlock_t state_lock; +}; + +#define MAX_MLO_GROUP 1 +#endif + /* * struct mlo_mgr_context - MLO manager context * @ml_dev_list_lock: ML DEV list lock @@ -94,7 +128,9 @@ struct mlo_mgr_context { qdf_list_t ml_dev_list; qdf_bitmap(mlo_peer_id_bmap, MAX_MLO_PEER_ID); uint16_t max_mlo_peer_id; - struct mlo_setup_info info; +#ifdef WLAN_MLO_MULTI_CHIP + struct mlo_setup_info setup_info; +#endif struct mlo_mlme_ext_ops *mlme_ops; struct ctxt_switch_mgr *msgq_ctx; bool mlo_is_force_primary_umac; @@ -344,4 +380,5 @@ struct mlo_mlme_ext_ops { uint8_t link_ix); void (*mlo_mlme_ext_deauth)(struct wlan_objmgr_peer *peer); }; + #endif diff --git a/umac/mlo_mgr/inc/wlan_mlo_mgr_setup.h b/umac/mlo_mgr/inc/wlan_mlo_mgr_setup.h new file mode 100644 index 0000000000..8a2aa37361 --- /dev/null +++ b/umac/mlo_mgr/inc/wlan_mlo_mgr_setup.h @@ -0,0 +1,69 @@ +/* Copyright (c) 2021 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * DOC: contains MLO manager public file containing setup/teardown functionality + */ + +#ifdef WLAN_MLO_MULTI_CHIP +/** + * mlo_setup_update_total_socs() - API to update total socs for mlo + * @tot_socs: Total socs + * + * Return: None. + */ +void mlo_setup_update_total_socs(uint8_t tot_socs); + +/** + * mlo_setup_update_num_links() - API to update num links in soc for mlo + * @soc_id: soc id of SoC corresponding to num_link + * @num_links: Number of links in that soc + * + * Return: None. + */ +void mlo_setup_update_num_links(uint8_t soc_id, uint8_t num_links); + +/** + * mlo_setup_update_soc_ready() - API to notify when FW init done + * @soc_id: soc id of SoC ready + * + * Return: None. + */ +void mlo_setup_update_soc_ready(uint8_t soc_id); + +/** + * mlo_setup_link_ready() - API to notify link ready + * @pdev: Pointer to pdev object + * + * Return: None. + */ +void mlo_setup_link_ready(struct wlan_objmgr_pdev *pdev); + +/** + * mlo_link_setup_complete() - API to notify setup complete + * @pdev: Pointer to pdev object + * + * Return: None. + */ +void mlo_link_setup_complete(struct wlan_objmgr_pdev *pdev); + +/** + * mlo_link_teardown_complete() - API to notify teardown complete + * @pdev: Pointer to pdev object + * + * Return: None. + */ +void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev); +#endif diff --git a/umac/mlo_mgr/src/wlan_mlo_mgr_setup.c b/umac/mlo_mgr/src/wlan_mlo_mgr_setup.c new file mode 100644 index 0000000000..dcd611607c --- /dev/null +++ b/umac/mlo_mgr/src/wlan_mlo_mgr_setup.c @@ -0,0 +1,142 @@ +/* Copyright (c) 2021 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 + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * DOC: contains MLO manager ap related functionality + */ +#include "wlan_mlo_mgr_cmn.h" +#include "wlan_mlo_mgr_main.h" +#ifdef WLAN_MLO_MULTI_CHIP +#include "wlan_lmac_if_def.h" +#endif + +#ifdef WLAN_MLO_MULTI_CHIP +void mlo_setup_update_total_socs(uint8_t tot_socs) +{ + struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); + + if (!mlo_ctx) + return; + + mlo_ctx->setup_info.tot_socs = tot_socs; +} + +qdf_export_symbol(mlo_setup_update_total_socs); + +void mlo_setup_update_num_links(uint8_t soc_id, uint8_t num_links) +{ + struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); + + if (!mlo_ctx) + return; + + mlo_ctx->setup_info.tot_links += num_links; +} + +qdf_export_symbol(mlo_setup_update_num_links); + +void mlo_setup_update_soc_ready(uint8_t soc_id) +{ + struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); + + if (!mlo_ctx) + return; + + mlo_ctx->setup_info.num_soc++; +} + +qdf_export_symbol(mlo_setup_update_soc_ready); + +void mlo_setup_link_ready(struct wlan_objmgr_pdev *pdev) +{ + struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); + uint8_t link_idx; + + if (!mlo_ctx) + return; + + link_idx = mlo_ctx->setup_info.num_links; + /* TODO: Get reference to PDEV */ + mlo_ctx->setup_info.pdev_list[link_idx] = pdev; + mlo_ctx->setup_info.state[link_idx] = MLO_LINK_SETUP_INIT; + mlo_ctx->setup_info.num_links++; + + if (mlo_ctx->setup_info.num_links == mlo_ctx->setup_info.tot_links && + mlo_ctx->setup_info.num_soc == mlo_ctx->setup_info.tot_socs) { + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_tx_ops *tx_ops; + + psoc = wlan_pdev_get_psoc(pdev); + tx_ops = wlan_psoc_get_lmac_if_txops(psoc); + /* Trigger MLO setup */ + if (tx_ops && tx_ops->mops.target_if_mlo_setup_req) { + tx_ops->mops.target_if_mlo_setup_req( + mlo_ctx->setup_info.pdev_list, + mlo_ctx->setup_info.num_links, + mlo_ctx->setup_info.ml_grp_id); + } + } +} + +qdf_export_symbol(mlo_setup_link_ready); + +void mlo_link_setup_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; + + for (link_idx = 0; link_idx < mlo_ctx->setup_info.tot_links; link_idx++) + if (mlo_ctx->setup_info.pdev_list[link_idx] == pdev) { + mlo_ctx->setup_info.state[link_idx] = + MLO_LINK_SETUP_DONE; + break; + } + + for (link_idx = 0; link_idx < mlo_ctx->setup_info.tot_links; link_idx++) + if (mlo_ctx->setup_info.state[link_idx] == MLO_LINK_SETUP_DONE) + continue; + else + break; + + if (link_idx == mlo_ctx->setup_info.tot_links) { + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_tx_ops *tx_ops; + + psoc = wlan_pdev_get_psoc(pdev); + tx_ops = wlan_psoc_get_lmac_if_txops(psoc); + /* Trigger MLO ready */ + if (tx_ops && tx_ops->mops.target_if_mlo_ready) { + tx_ops->mops.target_if_mlo_ready( + mlo_ctx->setup_info.pdev_list, + mlo_ctx->setup_info.num_links); + } + } +} + +qdf_export_symbol(mlo_link_setup_complete); + +void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev) +{ + struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); + + if (!mlo_ctx) + return; +} + +qdf_export_symbol(mlo_link_teardown_complete); +#endif /*WLAN_MLO_MULTI_CHIP*/