1 /* 2 * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. 3 * 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: target_if_dfs_full_offload.c 22 * This file contains dfs target interface for full offload 23 */ 24 25 #include <target_if.h> 26 #include <target_if_dfs.h> 27 #include <wmi_unified_dfs_api.h> 28 #include <init_deinit_lmac.h> 29 #include <wlan_module_ids.h> 30 #include <target_if_dfs_full_offload.h> 31 32 /** 33 * target_if_dfs_cac_complete_event_handler() - CAC complete indication. 34 * @scn: scn handle. 35 * @data: Pointer to data buffer. 36 * @datalen: data length. 37 * 38 * Return: 0 on successful indication. 39 */ 40 static int target_if_dfs_cac_complete_event_handler( 41 ol_scn_t scn, uint8_t *data, uint32_t datalen) 42 { 43 struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops; 44 struct wlan_objmgr_psoc *psoc; 45 struct wlan_objmgr_vdev *vdev; 46 struct wlan_objmgr_pdev *pdev; 47 int ret = 0; 48 uint32_t vdev_id = 0; 49 50 if (!scn || !data) { 51 target_if_err("scn: %pK, data: %pK", scn, data); 52 return -EINVAL; 53 } 54 55 psoc = target_if_get_psoc_from_scn_hdl(scn); 56 if (!psoc) { 57 target_if_err("null psoc"); 58 return -EINVAL; 59 } 60 61 dfs_rx_ops = target_if_dfs_get_rx_ops(psoc); 62 if (!dfs_rx_ops || !dfs_rx_ops->dfs_dfs_cac_complete_ind) { 63 target_if_err("Invalid dfs_rx_ops: %pK", dfs_rx_ops); 64 return -EINVAL; 65 } 66 67 if (wmi_extract_dfs_cac_complete_event(GET_WMI_HDL_FROM_PSOC(psoc), 68 data, &vdev_id, datalen) != QDF_STATUS_SUCCESS) { 69 target_if_err("failed to extract cac complete event"); 70 return -EFAULT; 71 } 72 73 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_DFS_ID); 74 if (!vdev) { 75 target_if_err("null vdev"); 76 return -EINVAL; 77 } 78 79 pdev = wlan_vdev_get_pdev(vdev); 80 if (!pdev) { 81 target_if_err("null pdev"); 82 ret = -EINVAL; 83 } 84 85 if (!ret && (QDF_STATUS_SUCCESS != 86 dfs_rx_ops->dfs_dfs_cac_complete_ind(pdev, vdev_id))) { 87 target_if_err("dfs_dfs_cac_complete_ind failed"); 88 ret = -EINVAL; 89 } 90 wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID); 91 92 return ret; 93 } 94 95 /** 96 * target_if_dfs_radar_detection_event_handler() - Indicate RADAR detection and 97 * process RADAR detection. 98 * @scn: scn handle. 99 * @data: pointer to data buffer. 100 * @datalen: data length. 101 * 102 * Return: 0 on successful indication. 103 */ 104 static int target_if_dfs_radar_detection_event_handler( 105 ol_scn_t scn, uint8_t *data, uint32_t datalen) 106 { 107 struct radar_found_info radar; 108 struct wlan_objmgr_psoc *psoc = NULL; 109 struct wlan_objmgr_pdev *pdev = NULL; 110 struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops; 111 int ret = 0; 112 113 if (!scn || !data) { 114 target_if_err("scn: %pK, data: %pK", scn, data); 115 return -EINVAL; 116 } 117 118 psoc = target_if_get_psoc_from_scn_hdl(scn); 119 if (!psoc) { 120 target_if_err("null psoc"); 121 return -EINVAL; 122 } 123 124 dfs_rx_ops = target_if_dfs_get_rx_ops(psoc); 125 if (!dfs_rx_ops || !dfs_rx_ops->dfs_process_radar_ind) { 126 target_if_err("Invalid dfs_rx_ops: %pK", dfs_rx_ops); 127 return -EINVAL; 128 } 129 130 if (wmi_extract_dfs_radar_detection_event(GET_WMI_HDL_FROM_PSOC(psoc), 131 data, &radar, datalen) != QDF_STATUS_SUCCESS) { 132 target_if_err("failed to extract cac complete event"); 133 return -EFAULT; 134 } 135 136 pdev = wlan_objmgr_get_pdev_by_id(psoc, radar.pdev_id, WLAN_DFS_ID); 137 if (!pdev) { 138 target_if_err("null pdev"); 139 return -EINVAL; 140 } 141 142 if (dfs_rx_ops->dfs_process_radar_ind(pdev, 143 &radar) != QDF_STATUS_SUCCESS) { 144 target_if_err("dfs_process_radar_ind failed pdev_id=%d", 145 radar.pdev_id); 146 ret = -EINVAL; 147 } 148 149 wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID); 150 151 return ret; 152 } 153 154 QDF_STATUS target_if_dfs_reg_offload_events( 155 struct wlan_objmgr_psoc *psoc) 156 { 157 int ret1, ret2; 158 159 ret1 = wmi_unified_register_event( 160 get_wmi_unified_hdl_from_psoc(psoc), 161 wmi_dfs_radar_detection_event_id, 162 target_if_dfs_radar_detection_event_handler); 163 target_if_debug("wmi_dfs_radar_detection_event_id ret=%d", ret1); 164 165 ret2 = wmi_unified_register_event( 166 get_wmi_unified_hdl_from_psoc(psoc), 167 wmi_dfs_cac_complete_id, 168 target_if_dfs_cac_complete_event_handler); 169 target_if_debug("wmi_dfs_cac_complete_id ret=%d", ret2); 170 171 if (ret1 || ret2) 172 return QDF_STATUS_E_FAILURE; 173 else 174 return QDF_STATUS_SUCCESS; 175 } 176 177 #if (defined(CONFIG_MCL) || (QCA_WIFI_QCA8074)) 178 QDF_STATUS target_process_bang_radar_cmd( 179 struct wlan_objmgr_pdev *pdev, 180 struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test) 181 { 182 QDF_STATUS status; 183 struct wmi_unit_test_cmd wmi_utest; 184 int i; 185 wmi_unified_t wmi_handle; 186 187 if (!pdev) { 188 target_if_err("null pdev"); 189 return QDF_STATUS_E_FAILURE; 190 } 191 192 wmi_handle = get_wmi_unified_hdl_from_pdev(pdev); 193 if (!wmi_handle) { 194 target_if_err("null wmi_handle"); 195 return QDF_STATUS_E_FAILURE; 196 } 197 198 wmi_utest.vdev_id = dfs_unit_test->vdev_id; 199 wmi_utest.module_id = WLAN_MODULE_PHYERR_DFS; 200 wmi_utest.num_args = dfs_unit_test->num_args; 201 202 for (i = 0; i < dfs_unit_test->num_args; i++) 203 wmi_utest.args[i] = dfs_unit_test->args[i]; 204 /* 205 * Host to Target conversion for pdev id required 206 * before we send a wmi unit test command 207 */ 208 wmi_utest.args[IDX_PDEV_ID] = wmi_handle->ops-> 209 convert_pdev_id_host_to_target(pdev->pdev_objmgr.wlan_pdev_id); 210 211 status = wmi_unified_unit_test_cmd(wmi_handle, &wmi_utest); 212 if (QDF_IS_STATUS_ERROR(status)) 213 target_if_err("dfs: unit_test_cmd send failed %d", status); 214 return status; 215 } 216 #else 217 static QDF_STATUS target_process_bang_radar_cmd( 218 struct wlan_objmgr_pdev *pdev, 219 struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test) 220 { 221 return QDF_STATUS_SUCCESS; 222 } 223 #endif 224