From 948ddd56e79dd2a58c877e44c4fc24d511cfea2b Mon Sep 17 00:00:00 2001 From: Arif Hussain Date: Mon, 6 Mar 2017 14:58:06 -0800 Subject: [PATCH] qcacmn: DFS component target interface support Add support to handle WMI commands and events related to DFS component. Change-Id: Ie21cd8cfbe35dfea31ca608d47a5dfe937d753f4 CRs-Fixed: 2017481 --- target_if/dfs/inc/target_if_dfs.h | 33 +++++ target_if/dfs/src/target_if_dfs.c | 215 ++++++++++++++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 target_if/dfs/inc/target_if_dfs.h create mode 100644 target_if/dfs/src/target_if_dfs.c diff --git a/target_if/dfs/inc/target_if_dfs.h b/target_if/dfs/inc/target_if_dfs.h new file mode 100644 index 0000000000..bbc0608cfe --- /dev/null +++ b/target_if/dfs/inc/target_if_dfs.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017 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_dfs.h + * This file contains dfs target interface + */ + +/** + * target_if_register_dfs_tx_ops() - register dfs tx ops + * @dfs_tx_ops: tx ops pointer + * + * Register dfs tx ops + * + * Return: QDF_STATUS + */ +QDF_STATUS target_if_register_dfs_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops); diff --git a/target_if/dfs/src/target_if_dfs.c b/target_if/dfs/src/target_if_dfs.c new file mode 100644 index 0000000000..8652c3c116 --- /dev/null +++ b/target_if/dfs/src/target_if_dfs.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2017 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_dfs.c + * This file contains dfs target interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline struct wlan_lmac_if_dfs_rx_ops * +target_if_dfs_get_rx_ops(struct wlan_objmgr_psoc *psoc) +{ + return &psoc->soc_cb.rx_ops.dfs_rx_ops; +} + +static int target_if_dfs_cac_complete_event_handler( + ol_scn_t scn, uint8_t *data, uint32_t datalen) +{ + struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops; + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_pdev *pdev; + int ret = 0; + uint32_t vdev_id = 0; + + if (!scn || !data) { + target_if_err("scn: %p, data: %p", scn, data); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + target_if_err("null psoc"); + return -EINVAL; + } + + dfs_rx_ops = target_if_dfs_get_rx_ops(psoc); + if (!dfs_rx_ops || !dfs_rx_ops->dfs_dfs_cac_complete_ind) { + target_if_err("Invalid dfs_rx_ops: %p", dfs_rx_ops); + return -EINVAL; + } + + if (wmi_extract_dfs_cac_complete_event(GET_WMI_HDL_FROM_PSOC(psoc), + data, &vdev_id, datalen) != QDF_STATUS_SUCCESS) { + target_if_err("failed to extract cac complete event"); + return -EFAULT; + } + + vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_DFS_ID); + if (!vdev) { + target_if_err("null vdev"); + return -EINVAL; + } + + wlan_vdev_obj_lock(vdev); + pdev = wlan_vdev_get_pdev(vdev); + wlan_vdev_obj_unlock(vdev); + if (!pdev) { + target_if_err("null pdev"); + ret = -EINVAL; + } + + if (!ret && (QDF_STATUS_SUCCESS != + dfs_rx_ops->dfs_dfs_cac_complete_ind(pdev, vdev_id))) { + target_if_err("dfs_dfs_cac_complete_ind failed"); + ret = -EINVAL; + } + wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID); + + return ret; +} + +static int target_if_dfs_radar_detection_event_handler( + ol_scn_t scn, uint8_t *data, uint32_t datalen) +{ + struct radar_found_info radar; + struct wlan_objmgr_psoc *psoc = NULL; + struct wlan_objmgr_pdev *pdev = NULL; + struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops; + int ret = 0; + + if (!scn || !data) { + target_if_err("scn: %p, data: %p", scn, data); + return -EINVAL; + } + + psoc = target_if_get_psoc_from_scn_hdl(scn); + if (!psoc) { + target_if_err("null psoc"); + return -EINVAL; + } + + dfs_rx_ops = target_if_dfs_get_rx_ops(psoc); + if (!dfs_rx_ops || !dfs_rx_ops->dfs_process_radar_ind) { + target_if_err("Invalid dfs_rx_ops: %p", dfs_rx_ops); + return -EINVAL; + } + + if (wmi_extract_dfs_radar_detection_event(GET_WMI_HDL_FROM_PSOC(psoc), + data, &radar, datalen) != QDF_STATUS_SUCCESS) { + target_if_err("failed to extract cac complete event"); + return -EFAULT; + } + + pdev = wlan_objmgr_get_pdev_by_id(psoc, radar.pdev_id, WLAN_DFS_ID); + if (!pdev) { + target_if_err("null pdev"); + return -EINVAL; + } + + if (QDF_STATUS_SUCCESS != dfs_rx_ops->dfs_process_radar_ind(pdev, + &radar)) { + target_if_err("dfs_process_radar_ind failed pdev_id=%d", + radar.pdev_id); + ret = -EINVAL; + } + + wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID); + + return ret; +} + +static QDF_STATUS target_if_dfs_reg_offload_events( + struct wlan_objmgr_psoc *psoc) +{ + int ret1, ret2; + + ret1 = wmi_unified_register_event(psoc->tgt_if_handle, + wmi_dfs_radar_detection_event_id, + target_if_dfs_radar_detection_event_handler); + target_if_debug("wmi_dfs_radar_detection_event_id ret=%d", ret1); + + ret2 = wmi_unified_register_event(psoc->tgt_if_handle, + wmi_dfs_cac_complete_id, + target_if_dfs_cac_complete_event_handler); + target_if_debug("wmi_dfs_cac_complete_id ret=%d", ret2); + + if (ret1 || ret2) + return QDF_STATUS_E_FAILURE; + else + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_dfs_reg_phyerr_events(struct wlan_objmgr_psoc *psoc) +{ + /* TODO: dfs non-offload case */ + return QDF_STATUS_SUCCESS; +} + +static QDF_STATUS target_if_dfs_register_event_handler( + struct wlan_objmgr_pdev *pdev, + bool dfs_offload) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + struct wlan_objmgr_psoc *psoc = NULL; + + wlan_pdev_obj_lock(pdev); + psoc = wlan_pdev_get_psoc(pdev); + wlan_pdev_obj_unlock(pdev); + if (!psoc) { + target_if_err("null psoc"); + return QDF_STATUS_E_FAILURE; + } + + if (!dfs_offload) + return target_if_dfs_reg_phyerr_events(psoc); + + /* dfs offload case, send offload enable command first */ + status = wmi_unified_dfs_phyerr_offload_en_cmd(pdev->tgt_if_handle, 0); + if (QDF_IS_STATUS_SUCCESS(status)) + status = target_if_dfs_reg_offload_events(psoc); + + return status; +} + +QDF_STATUS target_if_register_dfs_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) +{ + struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; + + if (!tx_ops) { + target_if_err("invalid tx_ops"); + return QDF_STATUS_E_FAILURE; + } + + dfs_tx_ops = &tx_ops->dfs_tx_ops; + dfs_tx_ops->dfs_reg_ev_handler = &target_if_dfs_register_event_handler; + + return QDF_STATUS_SUCCESS; +}