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 struct wmi_unified *wmi_handle; 50 51 if (!scn || !data) { 52 target_if_err("scn: %pK, data: %pK", scn, data); 53 return -EINVAL; 54 } 55 56 psoc = target_if_get_psoc_from_scn_hdl(scn); 57 if (!psoc) { 58 target_if_err("null psoc"); 59 return -EINVAL; 60 } 61 62 dfs_rx_ops = target_if_dfs_get_rx_ops(psoc); 63 if (!dfs_rx_ops || !dfs_rx_ops->dfs_dfs_cac_complete_ind) { 64 target_if_err("Invalid dfs_rx_ops: %pK", dfs_rx_ops); 65 return -EINVAL; 66 } 67 68 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 69 if (!wmi_handle) { 70 target_if_err("Invalid WMI handle"); 71 return -EINVAL; 72 } 73 74 if (wmi_extract_dfs_cac_complete_event(wmi_handle, data, &vdev_id, 75 datalen) != QDF_STATUS_SUCCESS) { 76 target_if_err("failed to extract cac complete event"); 77 return -EFAULT; 78 } 79 80 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, WLAN_DFS_ID); 81 if (!vdev) { 82 target_if_err("null vdev"); 83 return -EINVAL; 84 } 85 86 pdev = wlan_vdev_get_pdev(vdev); 87 if (!pdev) { 88 target_if_err("null pdev"); 89 ret = -EINVAL; 90 } 91 92 if (!ret && (QDF_STATUS_SUCCESS != 93 dfs_rx_ops->dfs_dfs_cac_complete_ind(pdev, vdev_id))) { 94 target_if_err("dfs_dfs_cac_complete_ind failed"); 95 ret = -EINVAL; 96 } 97 wlan_objmgr_vdev_release_ref(vdev, WLAN_DFS_ID); 98 99 return ret; 100 } 101 102 /** 103 * target_if_dfs_radar_detection_event_handler() - Indicate RADAR detection and 104 * process RADAR detection. 105 * @scn: scn handle. 106 * @data: pointer to data buffer. 107 * @datalen: data length. 108 * 109 * Return: 0 on successful indication. 110 */ 111 static int target_if_dfs_radar_detection_event_handler( 112 ol_scn_t scn, uint8_t *data, uint32_t datalen) 113 { 114 struct radar_found_info radar; 115 struct wlan_objmgr_psoc *psoc = NULL; 116 struct wlan_objmgr_pdev *pdev = NULL; 117 struct wlan_lmac_if_dfs_rx_ops *dfs_rx_ops; 118 int ret = 0; 119 struct wmi_unified *wmi_handle; 120 121 if (!scn || !data) { 122 target_if_err("scn: %pK, data: %pK", scn, data); 123 return -EINVAL; 124 } 125 126 psoc = target_if_get_psoc_from_scn_hdl(scn); 127 if (!psoc) { 128 target_if_err("null psoc"); 129 return -EINVAL; 130 } 131 132 dfs_rx_ops = target_if_dfs_get_rx_ops(psoc); 133 if (!dfs_rx_ops || !dfs_rx_ops->dfs_process_radar_ind) { 134 target_if_err("Invalid dfs_rx_ops: %pK", dfs_rx_ops); 135 return -EINVAL; 136 } 137 138 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 139 if (!wmi_handle) { 140 target_if_err("Invalid WMI handle"); 141 return -EINVAL; 142 } 143 144 if (wmi_extract_dfs_radar_detection_event(wmi_handle, data, &radar, 145 datalen) 146 != QDF_STATUS_SUCCESS) { 147 target_if_err("failed to extract cac complete event"); 148 return -EFAULT; 149 } 150 151 pdev = wlan_objmgr_get_pdev_by_id(psoc, radar.pdev_id, WLAN_DFS_ID); 152 if (!pdev) { 153 target_if_err("null pdev"); 154 return -EINVAL; 155 } 156 157 if (dfs_rx_ops->dfs_process_radar_ind(pdev, 158 &radar) != QDF_STATUS_SUCCESS) { 159 target_if_err("dfs_process_radar_ind failed pdev_id=%d", 160 radar.pdev_id); 161 ret = -EINVAL; 162 } 163 164 wlan_objmgr_pdev_release_ref(pdev, WLAN_DFS_ID); 165 166 return ret; 167 } 168 169 QDF_STATUS target_if_dfs_reg_offload_events( 170 struct wlan_objmgr_psoc *psoc) 171 { 172 int ret1, ret2; 173 174 ret1 = wmi_unified_register_event( 175 get_wmi_unified_hdl_from_psoc(psoc), 176 wmi_dfs_radar_detection_event_id, 177 target_if_dfs_radar_detection_event_handler); 178 target_if_debug("wmi_dfs_radar_detection_event_id ret=%d", ret1); 179 180 ret2 = wmi_unified_register_event( 181 get_wmi_unified_hdl_from_psoc(psoc), 182 wmi_dfs_cac_complete_id, 183 target_if_dfs_cac_complete_event_handler); 184 target_if_debug("wmi_dfs_cac_complete_id ret=%d", ret2); 185 186 if (ret1 || ret2) 187 return QDF_STATUS_E_FAILURE; 188 else 189 return QDF_STATUS_SUCCESS; 190 } 191 192 #if (defined(CONFIG_MCL) || (QCA_WIFI_QCA8074)) 193 QDF_STATUS target_process_bang_radar_cmd( 194 struct wlan_objmgr_pdev *pdev, 195 struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test) 196 { 197 QDF_STATUS status; 198 struct wmi_unit_test_cmd wmi_utest; 199 int i; 200 wmi_unified_t wmi_handle; 201 uint32_t target_pdev_id = 0; 202 203 if (!pdev) { 204 target_if_err("null pdev"); 205 return QDF_STATUS_E_FAILURE; 206 } 207 208 wmi_handle = get_wmi_unified_hdl_from_pdev(pdev); 209 if (!wmi_handle) { 210 target_if_err("null wmi_handle"); 211 return QDF_STATUS_E_FAILURE; 212 } 213 214 wmi_utest.vdev_id = dfs_unit_test->vdev_id; 215 wmi_utest.module_id = WLAN_MODULE_PHYERR_DFS; 216 wmi_utest.num_args = dfs_unit_test->num_args; 217 218 for (i = 0; i < dfs_unit_test->num_args; i++) 219 wmi_utest.args[i] = dfs_unit_test->args[i]; 220 /* 221 * Host to Target conversion for pdev id required 222 * before we send a wmi unit test command 223 */ 224 if (wmi_convert_pdev_id_host_to_target( 225 wmi_handle, pdev->pdev_objmgr.wlan_pdev_id, 226 &target_pdev_id) != QDF_STATUS_SUCCESS) { 227 target_if_err("failed to convert host pdev id to target"); 228 return QDF_STATUS_E_FAILURE; 229 } 230 231 wmi_utest.args[IDX_PDEV_ID] = target_pdev_id; 232 233 status = wmi_unified_unit_test_cmd(wmi_handle, &wmi_utest); 234 if (QDF_IS_STATUS_ERROR(status)) 235 target_if_err("dfs: unit_test_cmd send failed %d", status); 236 return status; 237 } 238 #else 239 static QDF_STATUS target_process_bang_radar_cmd( 240 struct wlan_objmgr_pdev *pdev, 241 struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test) 242 { 243 return QDF_STATUS_SUCCESS; 244 } 245 #endif 246