diff --git a/target_if/core/src/target_if_main.c b/target_if/core/src/target_if_main.c index 7d68a3014ed3..6c1623548f98 100644 --- a/target_if/core/src/target_if_main.c +++ b/target_if/core/src/target_if_main.c @@ -76,6 +76,10 @@ #include #endif +#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE +#include +#endif + static struct target_if_ctx *g_target_if_ctx; struct target_if_ctx *target_if_get_ctx() @@ -369,6 +373,20 @@ target_if_cp_stats_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) return target_if_cp_stats_register_tx_ops(tx_ops); } +#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE +static QDF_STATUS +target_if_vdev_mgr_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) +{ + return target_if_vdev_mgr_register_tx_ops(tx_ops); +} +#else +static QDF_STATUS +target_if_vdev_mgr_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) +{ + return QDF_STATUS_SUCCESS; +} +#endif + #ifdef QCA_WIFI_FTM static void target_if_ftm_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) @@ -419,6 +437,8 @@ QDF_STATUS target_if_register_umac_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) target_if_crypto_tx_ops_register(tx_ops); + target_if_vdev_mgr_tx_ops_register(tx_ops); + /* Converged UMAC components to register their TX-ops here */ return QDF_STATUS_SUCCESS; } diff --git a/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_rx_ops.h b/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_rx_ops.h new file mode 100644 index 000000000000..70958c7161ee --- /dev/null +++ b/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_rx_ops.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019 The Linux Foundation. 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: target_if_vdev_mgr_rx_ops.h + * + * This file provides declarations for APIs registered for wmi events + */ + +#ifndef __TARGET_IF_VDEV_MGR_RX_OPS_H__ +#define __TARGET_IF_VDEV_MGR_RX_OPS_H__ + +#include +#include +#include + +/** + * target_if_vdev_mgr_get_rx_ops() - get rx ops + * @psoc: pointer to psoc object + * + * Return: pointer to rx ops + */ +static inline struct wlan_lmac_if_mlme_rx_ops * +target_if_vdev_mgr_get_rx_ops(struct wlan_objmgr_psoc *psoc) +{ + return &psoc->soc_cb.rx_ops.mops; +} + +/** + * target_if_vdev_mgr_rsp_timer_mgmt_cb() - function to handle response timer + * @arg: pointer to argument + * + * Callback timer triggered when response timer expires which pass + * vdev as argument + * + * Return: status of operation. + */ +void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg); + +/** + * target_if_vdev_mgr_wmi_event_register() - function to handle register + * events from WMI + * @psoc: pointer to psoc object + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS target_if_vdev_mgr_wmi_event_register( + struct wlan_objmgr_psoc *psoc); + +/** + * target_if_vdev_mgr_wmi_event_unregister() - function to handle unregister + * events from WMI + * @psoc: pointer to psoc object + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS target_if_vdev_mgr_wmi_event_unregister( + struct wlan_objmgr_psoc *psoc); + +#endif /* __TARGET_IF_VDEV_MGR_RX_OPS_H__ */ diff --git a/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h b/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h new file mode 100644 index 000000000000..56f71e11f0c3 --- /dev/null +++ b/target_if/mlme/vdev_mgr/inc/target_if_vdev_mgr_tx_ops.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019 The Linux Foundation. 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: target_if_vdev_mgmt_tx_ops.h + * + * This file provides declaration for APIs to send WMI commands + */ + +#ifndef __TARGET_IF_VDEV_MGR_TX_OPS_H__ +#define __TARGET_IF_VDEV_MGR_TX_OPS_H__ + +#ifdef CMN_VDEV_MGR_TGT_IF_ENABLE +#include +#include +#include +#include + +/** + * target_if_vdev_mgr_get_tx_ops() - get tx ops + * @psoc: pointer to psoc obj + * + * Return: pointer to tx ops + */ +static inline struct wlan_lmac_if_mlme_tx_ops * +target_if_vdev_mgr_get_tx_ops(struct wlan_objmgr_psoc *psoc) +{ + return &psoc->soc_cb.tx_ops.mops; +} + +/** + * target_if_rsp_timer_mgmt() - function to handle response timer + * @vdev: pointer to vdev object + * @rsp_timer: pointer to response timer + * @init: timer init status + * + * Return: status of operation. + */ +QDF_STATUS target_if_vdev_mgr_rsp_timer_mgmt( + struct wlan_objmgr_vdev *vdev, + qdf_timer_t *rsp_timer, + bool init); + +/** + * target_if_vdev_mgr_vdev_mlme_register_tx_ops() - define mlme lmac + * tx ops functions + * @tx_ops: pointer to lmac tx ops + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_** on error + */ +QDF_STATUS +target_if_vdev_mgr_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); + +#else + +static inline QDF_STATUS +target_if_vdev_mgr_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + return QDF_STATUS_SUCCESS; +} + +#endif /* CMN_VDEV_MGR_TGT_IF_ENABLE */ +#endif /* __TARGET_IF_VDEV_MGR_TX_OPS_H__ */ diff --git a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c new file mode 100644 index 000000000000..f7bfee0b0c49 --- /dev/null +++ b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_rx_ops.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2019 The Linux Foundation. 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: target_if_vdev_mgr_rx_ops.c + * + * This file provide definition for APIs registered through events received + * from FW + */ +#include +#include +#include +#include +#include +#include +#include + +void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) +{ + struct wlan_objmgr_vdev *vdev = arg; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct vdev_response_timer *vdev_rsp; + + mlme_debug("Response timer expired for VDEV %d", + wlan_vdev_get_id(vdev)); + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + QDF_ASSERT(0); + return; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_get_response_timer_info) { + mlme_err("No Rx Ops"); + return; + } + + if (qdf_is_recovering()) { + mlme_debug("Recovery in progress"); + return; + } + + vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev); + qdf_atomic_clear_bit(START_RESPONSE_BIT, &vdev_rsp->rsp_status); + qdf_atomic_clear_bit(STOP_RESPONSE_BIT, &vdev_rsp->rsp_status); + qdf_atomic_clear_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status); + + if (rx_ops->vdev_mgr_response_timeout_cb) + rx_ops->vdev_mgr_response_timeout_cb(vdev); + + /* Implementation need to be done based on build type */ + QDF_ASSERT(0); +} + +static int target_if_vdev_mgr_start_response_handler( + ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct vdev_start_response rsp = {0}; + wmi_host_vdev_start_resp vdev_start_resp; + + if (!scn || !data) { + mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + QDF_ASSERT(0); + return -EINVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_start_response) { + mlme_err("No Rx Ops"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + if (wmi_extract_vdev_start_resp(wmi_handle, data, &vdev_start_resp)) { + mlme_err("WMI extract failed"); + return -EINVAL; + } + + rsp.vdev_id = vdev_start_resp.vdev_id; + rsp.requestor_id = vdev_start_resp.requestor_id; + rsp.status = vdev_start_resp.status; + rsp.resp_type = vdev_start_resp.resp_type; + rsp.chain_mask = vdev_start_resp.chain_mask; + rsp.smps_mode = vdev_start_resp.smps_mode; + rsp.mac_id = vdev_start_resp.mac_id; + rsp.cfgd_tx_streams = vdev_start_resp.cfgd_tx_streams; + rsp.cfgd_rx_streams = vdev_start_resp.cfgd_rx_streams; + + status = rx_ops->vdev_mgr_start_response(psoc, &rsp); + + return qdf_status_to_os_return(status); +} + +static int target_if_vdev_mgr_stop_response_handler( + ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct vdev_stop_response rsp = {0}; + uint32_t vdev_id; + + if (!scn || !data) { + mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + QDF_ASSERT(0); + return -EINVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_stop_response) { + mlme_err("No Rx Ops"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + if (wmi_extract_vdev_stopped_param(wmi_handle, data, &vdev_id)) { + mlme_err("WMI extract failed"); + return -EINVAL; + } + + rsp.vdev_id = vdev_id; + status = rx_ops->vdev_mgr_stop_response(psoc, &rsp); + + return qdf_status_to_os_return(status); +} + +static int target_if_vdev_mgr_delete_response_handler( + ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct vdev_delete_response rsp = {0}; + struct wmi_host_vdev_delete_resp vdev_del_resp; + struct vdev_response_timer *vdev_rsp; + + if (!scn || !data) { + mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + QDF_ASSERT(0); + return -EINVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_stop_response || + !rx_ops->vdev_mgr_get_response_timer_info) { + mlme_err("No Rx Ops"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + if (wmi_extract_vdev_delete_resp(wmi_handle, data, &vdev_del_resp)) { + mlme_err("WMI extract failed"); + return -EINVAL; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, + vdev_del_resp.vdev_id, + WLAN_MLME_SB_ID); + if (!vdev) { + QDF_ASSERT(0); + return -EINVAL; + } + + rsp.vdev_id = vdev_del_resp.vdev_id; + status = rx_ops->vdev_mgr_delete_response(psoc, &rsp); + + vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev); + if (vdev_rsp && QDF_IS_STATUS_SUCCESS(status)) + target_if_vdev_mgr_rsp_timer_mgmt(vdev, &vdev_rsp->rsp_timer, + false); + + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); + return qdf_status_to_os_return(status); +} + +static int target_if_vdev_mgr_offload_bcn_tx_status_handler( + ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + uint32_t vdev_id, tx_status; + + if (!scn || !data) { + mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + QDF_ASSERT(0); + return -EINVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle) { + mlme_err("No Rx Ops"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + if (wmi_extract_offload_bcn_tx_status_evt(wmi_handle, data, + &vdev_id, &tx_status)) { + mlme_err("WMI extract failed"); + return -EINVAL; + } + + status = rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle( + vdev_id, + tx_status); + + return qdf_status_to_os_return(status); +} + +static int target_if_vdev_mgr_tbttoffset_update_handler( + ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + uint32_t num_vdevs = 0; + + if (!scn || !data) { + mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + QDF_ASSERT(0); + return -EINVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { + mlme_err("No Rx Ops"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + if (wmi_extract_tbttoffset_num_vdevs(wmi_handle, data, &num_vdevs)) { + mlme_err("WMI extract failed"); + return -EINVAL; + } + + status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, false); + + return qdf_status_to_os_return(status); +} + +static int target_if_vdev_mgr_ext_tbttoffset_update_handler( + ol_scn_t scn, + uint8_t *data, + uint32_t datalen) +{ + QDF_STATUS status; + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + uint32_t num_vdevs = 0; + + if (!scn || !data) { + mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); + return -EINVAL; + } + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + QDF_ASSERT(0); + return -EINVAL; + } + + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { + mlme_err("No Rx Ops"); + return -EINVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return -EINVAL; + } + + if (wmi_extract_ext_tbttoffset_num_vdevs(wmi_handle, data, + &num_vdevs)) { + mlme_err("WMI extract failed"); + return -EINVAL; + } + + status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, true); + + return qdf_status_to_os_return(status); +} + +QDF_STATUS target_if_vdev_mgr_wmi_event_register( + struct wlan_objmgr_psoc *psoc) +{ + int retval = 0; + struct wmi_unified *wmi_handle; + + if (!psoc) { + QDF_ASSERT(0); + return QDF_STATUS_E_NULL_VALUE; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return QDF_STATUS_E_INVAL; + } + +#if CMN_VDEV_MGR_TGT_IF_ENABLE_PHASE /* to be implemented in next phase */ + retval = wmi_unified_register_event_handler( + wmi_handle, + wmi_vdev_stopped_event_id, + target_if_vdev_mgr_stop_response_handler, + WMI_RX_UMAC_CTX); + if (retval) + mlme_err("failed to register for stop response"); + + retval = wmi_unified_register_event_handler( + wmi_handle, + wmi_vdev_delete_resp_event_id, + target_if_vdev_mgr_delete_response_handler, + WMI_RX_UMAC_CTX); + if (retval) + mlme_err("failed to register for delete response"); + + retval = wmi_unified_register_event_handler( + wmi_handle, + wmi_vdev_start_resp_event_id, + target_if_vdev_mgr_start_response_handler, + WMI_RX_UMAC_CTX); + if (retval) + mlme_err("failed to register for start response"); + + retval = wmi_unified_register_event_handler( + wmi_handle, + wmi_offload_bcn_tx_status_event_id, + target_if_vdev_mgr_offload_bcn_tx_status_handler, + WMI_RX_UMAC_CTX); + if (retval) + mlme_err("failed to register for bcn tx status response"); + + retval = wmi_unified_register_event_handler( + wmi_handle, + wmi_tbttoffset_update_event_id, + target_if_vdev_mgr_tbttoffset_update_handler, + WMI_RX_UMAC_CTX); + if (retval) + mlme_err("failed to register for tbttoffset update"); + + retval = wmi_unified_register_event_handler( + wmi_handle, + wmi_ext_tbttoffset_update_event_id, + target_if_vdev_mgr_ext_tbttoffset_update_handler, + WMI_RX_UMAC_CTX); + if (retval) + mlme_err("failed to register for ext tbttoffset update"); +#endif + + return qdf_status_from_os_return(retval); +} + +QDF_STATUS target_if_vdev_mgr_wmi_event_unregister( + struct wlan_objmgr_psoc *psoc) +{ + struct wmi_unified *wmi_handle; + + if (!psoc) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return QDF_STATUS_E_INVAL; + } + +#if CMN_VDEV_MGR_TGT_IF_ENABLE_PHASE + wmi_unified_unregister_event_handler(wmi_handle, + wmi_vdev_stopped_event_id); + + wmi_unified_unregister_event_handler(wmi_handle, + wmi_vdev_delete_resp_event_id); + + wmi_unified_unregister_event_handler(wmi_handle, + wmi_vdev_start_resp_event_id); + + wmi_unified_unregister_event_handler(wmi_handle, + wmi_tbttoffset_update_event_id); + + wmi_unified_unregister_event_handler( + wmi_handle, + wmi_ext_tbttoffset_update_event_id); + + wmi_unified_unregister_event_handler( + wmi_handle, + wmi_offload_bcn_tx_status_event_id); +#endif + + return QDF_STATUS_SUCCESS; +} diff --git a/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c new file mode 100644 index 000000000000..83192cc27935 --- /dev/null +++ b/target_if/mlme/vdev_mgr/src/target_if_vdev_mgr_tx_ops.c @@ -0,0 +1,845 @@ +/* + * Copyright (c) 2019 The Linux Foundation. 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: target_if_vdev_mgr_tx_ops.c + * + * This file provide definition for APIs registered through lmac Tx Ops + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static QDF_STATUS target_if_vdev_mgr_register_event_handler( + struct wlan_objmgr_psoc *psoc) +{ + return target_if_vdev_mgr_wmi_event_register(psoc); +} + +static QDF_STATUS target_if_vdev_mgr_unregister_event_handler( + struct wlan_objmgr_psoc *psoc) +{ + return target_if_vdev_mgr_wmi_event_unregister(psoc); +} + +QDF_STATUS target_if_vdev_mgr_rsp_timer_mgmt( + struct wlan_objmgr_vdev *vdev, + qdf_timer_t *rsp_timer, + bool init) +{ + if (init) { + qdf_timer_init(NULL, rsp_timer, + target_if_vdev_mgr_rsp_timer_mgmt_cb, + (void *)vdev, QDF_TIMER_TYPE_WAKE_APPS); + wlan_objmgr_vdev_get_ref(vdev, WLAN_MLME_SB_ID); + } else { + qdf_timer_free(rsp_timer); + wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); + } + + return QDF_STATUS_SUCCESS; +} + +struct wmi_unified +*target_if_vdev_mgr_wmi_handle_get(struct wlan_objmgr_vdev *vdev) +{ + struct wlan_objmgr_psoc *psoc; + struct wmi_unified *wmi_handle; + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + QDF_ASSERT(0); + return NULL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("wmi_handle is null"); + return NULL; + } + + return wmi_handle; +} + +static QDF_STATUS target_if_check_is_pre_lithium( + struct wlan_objmgr_psoc *psoc) +{ + if (lmac_get_tgt_type(psoc) < TARGET_TYPE_QCA8074) + return QDF_STATUS_SUCCESS; + else + return QDF_STATUS_E_INVAL; +} + +static inline uint32_t +target_if_vdev_mlme_id_2_wmi(uint32_t cfg_id) +{ + int wmi_id; + + switch (cfg_id) { + case WLAN_MLME_CFG_DTIM_PERIOD: + wmi_id = wmi_vdev_param_dtim_period; + break; + case WLAN_MLME_CFG_SLOT_TIME: + wmi_id = wmi_vdev_param_slot_time; + break; + case WLAN_MLME_CFG_PROTECTION_MODE: + wmi_id = wmi_vdev_param_protection_mode; + break; + case WLAN_MLME_CFG_BEACON_INTERVAL: + wmi_id = wmi_vdev_param_beacon_interval; + break; + case WLAN_MLME_CFG_LDPC: + wmi_id = wmi_vdev_param_ldpc; + break; + case WLAN_MLME_CFG_NSS: + wmi_id = wmi_vdev_param_nss; + break; + case WLAN_MLME_CFG_SUBFER: + case WLAN_MLME_CFG_MUBFER: + case WLAN_MLME_CFG_SUBFEE: + case WLAN_MLME_CFG_MUBFEE: + case WLAN_MLME_CFG_IMLICIT_BF: + case WLAN_MLME_CFG_SOUNDING_DIM: + wmi_id = wmi_vdev_param_txbf; + break; + case WLAN_MLME_CFG_HE_OPS: + wmi_id = wmi_vdev_param_set_heop; + break; + case WLAN_MLME_CFG_RTS_THRESHOLD: + wmi_id = wmi_vdev_param_rts_threshold; + break; + case WLAN_MLME_CFG_FRAG_THRESHOLD: + wmi_id = wmi_vdev_param_fragmentation_threshold; + break; + case WLAN_MLME_CFG_DROP_UNENCRY: + wmi_id = wmi_vdev_param_drop_unencry; + break; + case WLAN_MLME_CFG_TX_POWER: + wmi_id = wmi_vdev_param_tx_power; + break; + case WLAN_MLME_CFG_AMPDU: + wmi_id = wmi_vdev_param_amsdu_subframe_size_per_ac; + break; + case WLAN_MLME_CFG_AMSDU: + wmi_id = wmi_vdev_param_amsdu_subframe_size_per_ac; + break; + case WLAN_MLME_CFG_MIN_IDLE_INACTIVE_TIME: + wmi_id = + wmi_vdev_param_ap_keepalive_min_idle_inactive_time_secs; + break; + case WLAN_MLME_CFG_MAX_IDLE_INACTIVE_TIME: + wmi_id = + wmi_vdev_param_ap_keepalive_max_idle_inactive_time_secs; + break; + case WLAN_MLME_CFG_MAX_UNRESPONSIVE_INACTIVE_TIME: + wmi_id = + wmi_vdev_param_ap_keepalive_max_unresponsive_time_secs; + break; + case WLAN_MLME_CFG_UAPSD: + wmi_id = WMI_HOST_STA_PS_PARAM_UAPSD; + break; + default: + wmi_id = cfg_id; + break; + } + + return wmi_id; +} + +static enum wlan_phymode +target_if_wmi_phymode_from_wlan_phymode(struct wlan_objmgr_vdev *vdev, + uint32_t phy_mode, + bool is_2gvht_en, + bool is_11ax_stub_enabled) +{ + static uint32_t phy_2_wmi[WLAN_PHYMODE_11AXA_HE80_80 + 1] = { + [WLAN_PHYMODE_AUTO] = WMI_HOST_MODE_UNKNOWN, + [WLAN_PHYMODE_11A] = WMI_HOST_MODE_11A, + [WLAN_PHYMODE_11B] = WMI_HOST_MODE_11B, + [WLAN_PHYMODE_11G] = WMI_HOST_MODE_11G, + [WLAN_PHYMODE_11NA_HT20] = WMI_HOST_MODE_11NA_HT20, + [WLAN_PHYMODE_11NG_HT20] = WMI_HOST_MODE_11NG_HT20, + [WLAN_PHYMODE_11NA_HT40PLUS] = WMI_HOST_MODE_11NA_HT40, + [WLAN_PHYMODE_11NA_HT40MINUS] = WMI_HOST_MODE_11NA_HT40, + [WLAN_PHYMODE_11NG_HT40PLUS] = WMI_HOST_MODE_11NG_HT40, + [WLAN_PHYMODE_11NG_HT40MINUS] = WMI_HOST_MODE_11NG_HT40, + [WLAN_PHYMODE_11NG_HT40] = WMI_HOST_MODE_11NG_HT40, + [WLAN_PHYMODE_11NA_HT40] = WMI_HOST_MODE_11NA_HT40, + [WLAN_PHYMODE_11AC_VHT20] = WMI_HOST_MODE_11AC_VHT20, + [WLAN_PHYMODE_11AC_VHT40PLUS] = WMI_HOST_MODE_11AC_VHT40, + [WLAN_PHYMODE_11AC_VHT40MINUS] = WMI_HOST_MODE_11AC_VHT40, + [WLAN_PHYMODE_11AC_VHT40] = WMI_HOST_MODE_11AC_VHT40, + [WLAN_PHYMODE_11AC_VHT80] = WMI_HOST_MODE_11AC_VHT80, + [WLAN_PHYMODE_11AC_VHT160] = WMI_HOST_MODE_11AC_VHT160, + [WLAN_PHYMODE_11AC_VHT80_80] = WMI_HOST_MODE_11AC_VHT80_80, + [WLAN_PHYMODE_11AXA_HE20] = WMI_HOST_MODE_11AX_HE20, + [WLAN_PHYMODE_11AXG_HE20] = WMI_HOST_MODE_11AX_HE20_2G, + [WLAN_PHYMODE_11AXA_HE40PLUS] = WMI_HOST_MODE_11AX_HE40, + [WLAN_PHYMODE_11AXA_HE40MINUS] = WMI_HOST_MODE_11AX_HE40, + [WLAN_PHYMODE_11AXG_HE40PLUS] = WMI_HOST_MODE_11AX_HE40_2G, + [WLAN_PHYMODE_11AXG_HE40MINUS] = WMI_HOST_MODE_11AX_HE40_2G, + [WLAN_PHYMODE_11AXA_HE40] = WMI_HOST_MODE_11AX_HE40, + [WLAN_PHYMODE_11AXG_HE40] = WMI_HOST_MODE_11AX_HE40_2G, + [WLAN_PHYMODE_11AXA_HE80] = WMI_HOST_MODE_11AX_HE80, + [WLAN_PHYMODE_11AXA_HE160] = WMI_HOST_MODE_11AX_HE160, + [WLAN_PHYMODE_11AXA_HE80_80] = WMI_HOST_MODE_11AX_HE80_80, + }; + uint32_t temp_phymode; + enum wmi_target_type target; + struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev); + uint32_t target_type; + + if (phy_mode < WLAN_PHYMODE_11A || + phy_mode > WLAN_PHYMODE_11AXA_HE80_80) { + temp_phymode = WMI_HOST_MODE_UNKNOWN; + return temp_phymode; + } + + target_type = lmac_get_tgt_type(psoc); + + /* + * 802.11ax stubbing is enabled only if the enable_11ax_stub module + * parameter is set to 1, and only for QCA9984. + */ + if (is_11ax_stub_enabled && (target_type == TARGET_TYPE_QCA9984)) { + /* re-map 802.11ax modes to equivalent 802.11n/ac modes. */ + phy_2_wmi[WLAN_PHYMODE_11AXA_HE20] = + WMI_HOST_MODE_11AC_VHT20; + phy_2_wmi[WLAN_PHYMODE_11AXG_HE20] = + WMI_HOST_MODE_11NG_HT20; + phy_2_wmi[WLAN_PHYMODE_11AXA_HE40PLUS] = + WMI_HOST_MODE_11AC_VHT40; + phy_2_wmi[WLAN_PHYMODE_11AXA_HE40MINUS] = + WMI_HOST_MODE_11AC_VHT40; + phy_2_wmi[WLAN_PHYMODE_11AXG_HE40PLUS] = + WMI_HOST_MODE_11NG_HT40; + phy_2_wmi[WLAN_PHYMODE_11AXG_HE40MINUS] = + WMI_HOST_MODE_11NG_HT40; + phy_2_wmi[WLAN_PHYMODE_11AXA_HE40] = + WMI_HOST_MODE_11AC_VHT40; + phy_2_wmi[WLAN_PHYMODE_11AXG_HE40] = + WMI_HOST_MODE_11NG_HT40; + phy_2_wmi[WLAN_PHYMODE_11AXA_HE80] = + WMI_HOST_MODE_11AC_VHT80; + phy_2_wmi[WLAN_PHYMODE_11AXA_HE160] = + WMI_HOST_MODE_11AC_VHT160; + phy_2_wmi[WLAN_PHYMODE_11AXA_HE80_80] = + WMI_HOST_MODE_11AC_VHT80_80; + } + + switch (target_type) { + case TARGET_TYPE_AR6002: + case TARGET_TYPE_AR6003: + case TARGET_TYPE_AR6004: + case TARGET_TYPE_AR6006: + case TARGET_TYPE_AR9888: + case TARGET_TYPE_AR6320: + case TARGET_TYPE_AR900B: + case TARGET_TYPE_QCA9984: + case TARGET_TYPE_QCA9888: + case TARGET_TYPE_IPQ4019: + target = WMI_NON_TLV_TARGET; + break; + case TARGET_TYPE_QCA8074: + case TARGET_TYPE_QCA8074V2: + target = WMI_TLV_TARGET; + break; + case TARGET_TYPE_QCA6290: + target = WMI_TLV_TARGET; + break; + case TARGET_TYPE_QCA6018: + target = WMI_TLV_TARGET; + break; + default: + temp_phymode = WMI_HOST_MODE_UNKNOWN; + return temp_phymode; + } + + temp_phymode = phy_2_wmi[phy_mode]; + + if ((target == WMI_TLV_TARGET) && (is_2gvht_en == true)) { + switch (phy_mode) { + case WLAN_PHYMODE_11NG_HT20: + temp_phymode = WMI_HOST_MODE_11AC_VHT20_2G; + break; + + case WLAN_PHYMODE_11NG_HT40PLUS: + case WLAN_PHYMODE_11NG_HT40MINUS: + case WLAN_PHYMODE_11NG_HT40: + temp_phymode = WMI_HOST_MODE_11AC_VHT40_2G; + break; + } + } + + return temp_phymode; +} + +static QDF_STATUS target_if_vdev_mgr_set_param_send( + struct wlan_objmgr_vdev *vdev, + struct vdev_set_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + int param_id; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + param_id = target_if_vdev_mlme_id_2_wmi(param->param_id); + param->param_id = param_id; + + status = wmi_unified_vdev_set_param_send(wmi_handle, param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_create_send( + struct wlan_objmgr_vdev *vdev, + struct vdev_create_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + uint8_t vap_addr[QDF_MAC_ADDR_SIZE] = {0}; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + WLAN_ADDR_COPY(vap_addr, wlan_vdev_mlme_get_macaddr(vdev)); + status = wmi_unified_vdev_create_send(wmi_handle, vap_addr, + param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_start_send( + struct wlan_objmgr_vdev *vdev, + struct vdev_start_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + enum wlan_phymode phy_mode; + uint32_t is_2gvht; + uint32_t is_11ax_stub_enabled; + struct vdev_response_timer *vdev_rsp; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + if (!rx_ops && !rx_ops->vdev_mgr_get_response_timer_info) { + mlme_err("No Rx Ops"); + return QDF_STATUS_E_INVAL; + } + + vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev); + if (vdev_rsp) + qdf_timer_start(&vdev_rsp->rsp_timer, START_RESPONSE_TIMER); + + wlan_util_vdev_get_param(vdev, WLAN_MLME_CFG_2G_VHT, &is_2gvht); + wlan_util_vdev_get_param(vdev, WLAN_MLME_CFG_11AX_STUB, + &is_11ax_stub_enabled); + + phy_mode = target_if_wmi_phymode_from_wlan_phymode( + vdev, + param->channel.phy_mode, + is_2gvht, + is_11ax_stub_enabled); + param->channel.phy_mode = phy_mode; + status = wmi_unified_vdev_start_send(wmi_handle, param); + if (QDF_IS_STATUS_SUCCESS(status)) { + if (qdf_atomic_test_and_set_bit(START_RESPONSE_BIT, + &vdev_rsp->rsp_status)) + mlme_debug("Response bit already set"); + } else { + qdf_timer_stop(&vdev_rsp->rsp_timer); + } + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_delete_send( + struct wlan_objmgr_vdev *vdev, + struct vdev_delete_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_vdev_delete_send(wmi_handle, param->vdev_id); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_stop_send( + struct wlan_objmgr_vdev *vdev, + struct vdev_stop_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + struct wlan_lmac_if_mlme_rx_ops *rx_ops; + struct wlan_objmgr_psoc *psoc; + struct vdev_response_timer *vdev_rsp; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); + + if (!rx_ops && !rx_ops->vdev_mgr_get_response_timer_info) { + mlme_err("No Rx Ops"); + return QDF_STATUS_E_INVAL; + } + + vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev); + if (vdev_rsp) + qdf_timer_start(&vdev_rsp->rsp_timer, STOP_RESPONSE_TIMER); + + status = wmi_unified_vdev_stop_send(wmi_handle, param->vdev_id); + if (QDF_IS_STATUS_SUCCESS(status)) { + if (qdf_atomic_test_and_set_bit(STOP_RESPONSE_BIT, + &vdev_rsp->rsp_status)) + mlme_debug("Response bit already set"); + } else { + qdf_timer_stop(&vdev_rsp->rsp_timer); + } + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_down_send( + struct wlan_objmgr_vdev *vdev, + struct vdev_down_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_vdev_down_send(wmi_handle, param->vdev_id); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_up_send( + struct wlan_objmgr_vdev *vdev, + struct vdev_up_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + struct vdev_set_params sparam = {0}; + uint8_t bssid_null[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; + uint8_t *bssid = wlan_vdev_mlme_get_macaddr(vdev); + uint8_t *bssid_send; + enum QDF_OPMODE opmode; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + sparam.vdev_id = wlan_vdev_get_id(vdev); + + sparam.param_id = WLAN_MLME_CFG_BEACON_INTERVAL; + wlan_util_vdev_get_param(vdev, WLAN_MLME_CFG_BEACON_INTERVAL, + &sparam.param_value); + status = target_if_vdev_mgr_set_param_send(vdev, &sparam); + if (QDF_IS_STATUS_ERROR(status)) + mlme_err("Failed to set beacon interval!"); + + sparam.param_id = WLAN_MLME_CFG_SUBFEE; + wlan_util_vdev_get_param(vdev, WLAN_MLME_CFG_SUBFEE, + &sparam.param_value); + status = target_if_vdev_mgr_set_param_send(vdev, &sparam); + if (QDF_IS_STATUS_ERROR(status)) + mlme_err("Failed to set SU beam formee!"); + + bssid_send = (opmode == QDF_MONITOR_MODE) ? bssid_null : bssid; + status = wmi_unified_vdev_up_send(wmi_handle, bssid_send, param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_beacon_tmpl_send( + struct wlan_objmgr_vdev *vdev, + struct beacon_tmpl_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_beacon_tmpl_send_cmd(wmi_handle, param); + return status; +} + +static QDF_STATUS target_if_vdev_mgr_set_nac_rssi_send( + struct wlan_objmgr_vdev *vdev, + struct vdev_scan_nac_rssi_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_vdev_set_nac_rssi_send(wmi_handle, param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_set_neighbour_rx_cmd_send( + struct wlan_objmgr_vdev *vdev, + struct set_neighbour_rx_params *param, + uint8_t *mac) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_vdev_set_neighbour_rx_cmd_send(wmi_handle, + mac, param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_sifs_trigger_send( + struct wlan_objmgr_vdev *vdev, + struct sifs_trigger_param *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_sifs_trigger_send(wmi_handle, param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_set_custom_aggr_size_cmd_send( + struct wlan_objmgr_vdev *vdev, + struct set_custom_aggr_size_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_vdev_set_custom_aggr_size_cmd_send(wmi_handle, + param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_config_ratemask_cmd_send( + struct wlan_objmgr_vdev *vdev, + struct config_ratemask_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_vdev_config_ratemask_cmd_send(wmi_handle, + param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_peer_flush_tids_send( + struct wlan_objmgr_vdev *vdev, + struct peer_flush_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_peer_flush_tids_send(wmi_handle, param->peer_mac, + param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_multiple_vdev_restart_req_cmd( + struct wlan_objmgr_pdev *pdev, + struct multiple_vdev_restart_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + struct wlan_objmgr_psoc *psoc; + + if (!pdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); + if (!wmi_handle) { + mlme_err("PDEV WMI Handle is NULL!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_send_multiple_vdev_restart_req_cmd(wmi_handle, + param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_beacon_send( + struct wlan_objmgr_vdev *vdev, + struct beacon_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_beacon_send_cmd(wmi_handle, param); + + return status; +} + +static QDF_STATUS target_if_vdev_mgr_sta_ps_param_send( + struct wlan_objmgr_vdev *vdev, + struct sta_ps_params *param) +{ + QDF_STATUS status; + struct wmi_unified *wmi_handle; + int param_id; + + if (!vdev || !param) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); + if (!wmi_handle) { + mlme_err("Failed to get WMI handle!"); + return QDF_STATUS_E_INVAL; + } + + param_id = target_if_vdev_mlme_id_2_wmi(param->param); + param->param = param_id; + + status = wmi_unified_sta_ps_cmd_send(wmi_handle, param); + + return status; +} + +QDF_STATUS +target_if_vdev_mgr_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + struct wlan_lmac_if_mlme_tx_ops *mlme_tx_ops; + + if (!tx_ops) { + QDF_ASSERT(0); + return QDF_STATUS_E_INVAL; + } + + mlme_tx_ops = &tx_ops->mops; + if (!mlme_tx_ops) { + mlme_err("No Tx Ops"); + return QDF_STATUS_E_FAILURE; + } + + mlme_tx_ops->vdev_mlme_attach = + target_if_vdev_mgr_register_event_handler; + mlme_tx_ops->vdev_mlme_detach = + target_if_vdev_mgr_unregister_event_handler; + mlme_tx_ops->vdev_create_send = target_if_vdev_mgr_create_send; + mlme_tx_ops->vdev_start_send = target_if_vdev_mgr_start_send; + mlme_tx_ops->vdev_up_send = target_if_vdev_mgr_up_send; + mlme_tx_ops->vdev_delete_send = target_if_vdev_mgr_delete_send; + mlme_tx_ops->vdev_stop_send = target_if_vdev_mgr_stop_send; + mlme_tx_ops->vdev_down_send = target_if_vdev_mgr_down_send; + mlme_tx_ops->vdev_set_nac_rssi_send = + target_if_vdev_mgr_set_nac_rssi_send; + mlme_tx_ops->vdev_set_neighbour_rx_cmd_send = + target_if_vdev_mgr_set_neighbour_rx_cmd_send; + mlme_tx_ops->vdev_sifs_trigger_send = + target_if_vdev_mgr_sifs_trigger_send; + mlme_tx_ops->vdev_set_custom_aggr_size_cmd_send = + target_if_vdev_mgr_set_custom_aggr_size_cmd_send; + mlme_tx_ops->vdev_config_ratemask_cmd_send = + target_if_vdev_mgr_config_ratemask_cmd_send; + mlme_tx_ops->peer_flush_tids_send = + target_if_vdev_mgr_peer_flush_tids_send; + mlme_tx_ops->multiple_vdev_restart_req_cmd = + target_if_vdev_mgr_multiple_vdev_restart_req_cmd; + mlme_tx_ops->beacon_cmd_send = target_if_vdev_mgr_beacon_send; + mlme_tx_ops->beacon_tmpl_send = target_if_vdev_mgr_beacon_tmpl_send; + mlme_tx_ops->vdev_set_param_send = + target_if_vdev_mgr_set_param_send; + mlme_tx_ops->vdev_sta_ps_param_send = + target_if_vdev_mgr_sta_ps_param_send; + mlme_tx_ops->target_is_pre_lithium = + target_if_check_is_pre_lithium; + mlme_tx_ops->vdev_mgr_resp_timer_mgmt = + target_if_vdev_mgr_rsp_timer_mgmt; + + return QDF_STATUS_SUCCESS; +}