1 /* 2 * Copyright (c) 2016-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: This file has the DFS dispatcher API implementation which is exposed 22 * to outside of DFS component. 23 */ 24 #include <wlan_objmgr_pdev_obj.h> 25 #include "wlan_dfs_tgt_api.h" 26 #include "wlan_lmac_if_def.h" 27 #include "wlan_lmac_if_api.h" 28 #include "wlan_dfs_mlme_api.h" 29 #include "../../core/src/dfs.h" 30 #include "../../core/src/dfs_zero_cac.h" 31 #include "../../core/src/dfs_process_radar_found_ind.h" 32 #include <qdf_module.h> 33 34 struct wlan_lmac_if_dfs_tx_ops * 35 wlan_psoc_get_dfs_txops(struct wlan_objmgr_psoc *psoc) 36 { 37 return &((psoc->soc_cb.tx_ops.dfs_tx_ops)); 38 } 39 40 QDF_STATUS tgt_dfs_set_current_channel(struct wlan_objmgr_pdev *pdev, 41 uint16_t dfs_ch_freq, 42 uint64_t dfs_ch_flags, 43 uint16_t dfs_ch_flagext, 44 uint8_t dfs_ch_ieee, 45 uint8_t dfs_ch_vhtop_ch_freq_seg1, 46 uint8_t dfs_ch_vhtop_ch_freq_seg2) 47 { 48 struct wlan_dfs *dfs; 49 50 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 51 if (!dfs) { 52 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 53 return QDF_STATUS_E_FAILURE; 54 } 55 56 dfs_set_current_channel(dfs, 57 dfs_ch_freq, 58 dfs_ch_flags, 59 dfs_ch_flagext, 60 dfs_ch_ieee, 61 dfs_ch_vhtop_ch_freq_seg1, 62 dfs_ch_vhtop_ch_freq_seg2); 63 64 return QDF_STATUS_SUCCESS; 65 } 66 qdf_export_symbol(tgt_dfs_set_current_channel); 67 68 QDF_STATUS tgt_dfs_radar_enable(struct wlan_objmgr_pdev *pdev, 69 int no_cac, uint32_t opmode) 70 { 71 struct wlan_dfs *dfs; 72 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 73 struct wlan_objmgr_psoc *psoc; 74 QDF_STATUS status; 75 76 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 77 if (!dfs) { 78 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 79 return QDF_STATUS_E_FAILURE; 80 } 81 82 if (!dfs->dfs_is_offload_enabled) { 83 dfs_radar_enable(dfs, no_cac, opmode); 84 return QDF_STATUS_SUCCESS; 85 } 86 87 psoc = wlan_pdev_get_psoc(pdev); 88 if (!psoc) { 89 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 90 return QDF_STATUS_E_FAILURE; 91 } 92 93 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 94 if (!dfs_tx_ops) { 95 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_tx_ops is null"); 96 return QDF_STATUS_E_FAILURE; 97 } 98 99 status = dfs_tx_ops->dfs_send_offload_enable_cmd(pdev, true); 100 if (QDF_IS_STATUS_ERROR(status)) 101 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 102 "Failed to enable dfs offload, pdev_id: %d", 103 wlan_objmgr_pdev_get_pdev_id(pdev)); 104 105 return status; 106 } 107 qdf_export_symbol(tgt_dfs_radar_enable); 108 109 QDF_STATUS tgt_dfs_process_phyerr(struct wlan_objmgr_pdev *pdev, 110 void *buf, 111 uint16_t datalen, 112 uint8_t r_rssi, 113 uint8_t r_ext_rssi, 114 uint32_t r_rs_tstamp, 115 uint64_t r_fulltsf) 116 { 117 struct wlan_dfs *dfs; 118 119 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 120 if (!dfs) { 121 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 122 return QDF_STATUS_E_FAILURE; 123 } 124 125 if (!dfs->dfs_is_offload_enabled) 126 dfs_process_phyerr(dfs, buf, datalen, r_rssi, 127 r_ext_rssi, r_rs_tstamp, r_fulltsf); 128 else 129 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 130 "Unexpect phyerror as DFS is offloaded, pdev_id: %d", 131 wlan_objmgr_pdev_get_pdev_id(pdev)); 132 133 return QDF_STATUS_SUCCESS; 134 } 135 qdf_export_symbol(tgt_dfs_process_phyerr); 136 137 #ifdef QCA_MCL_DFS_SUPPORT 138 QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev, 139 struct radar_event_info 140 *wlan_radar_event) 141 { 142 struct wlan_dfs *dfs; 143 144 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 145 if (!dfs) { 146 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 147 return QDF_STATUS_E_FAILURE; 148 } 149 if (!dfs->dfs_is_offload_enabled) 150 dfs_process_phyerr_filter_offload(dfs, wlan_radar_event); 151 else 152 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 153 "Unexpect phyerror as DFS is offloaded, pdev_id: %d", 154 wlan_objmgr_pdev_get_pdev_id(pdev)); 155 156 return QDF_STATUS_SUCCESS; 157 } 158 qdf_export_symbol(tgt_dfs_process_phyerr_filter_offload); 159 160 QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_psoc *psoc, 161 bool *is_phyerr_filter_offload) 162 { 163 struct dfs_soc_priv_obj *soc_obj; 164 165 if (!psoc) { 166 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 167 return QDF_STATUS_E_FAILURE; 168 } 169 170 soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 171 WLAN_UMAC_COMP_DFS); 172 if (!soc_obj) { 173 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 174 "Failed to get dfs psoc component"); 175 return QDF_STATUS_E_FAILURE; 176 } 177 178 *is_phyerr_filter_offload = soc_obj->dfs_is_phyerr_filter_offload; 179 180 return QDF_STATUS_SUCCESS; 181 } 182 qdf_export_symbol(tgt_dfs_is_phyerr_filter_offload); 183 #else 184 QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev, 185 struct radar_event_info 186 *wlan_radar_event) 187 { 188 return QDF_STATUS_SUCCESS; 189 } 190 191 QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_psoc *psoc, 192 bool *is_phyerr_filter_offload) 193 { 194 return QDF_STATUS_SUCCESS; 195 } 196 #endif 197 198 QDF_STATUS tgt_dfs_is_precac_timer_running(struct wlan_objmgr_pdev *pdev, 199 bool *is_precac_timer_running) 200 { 201 struct wlan_dfs *dfs; 202 203 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 204 if (!dfs) { 205 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 206 return QDF_STATUS_E_FAILURE; 207 } 208 209 *is_precac_timer_running = dfs_is_precac_timer_running(dfs); 210 211 return QDF_STATUS_SUCCESS; 212 } 213 qdf_export_symbol(tgt_dfs_is_precac_timer_running); 214 215 QDF_STATUS tgt_dfs_get_radars(struct wlan_objmgr_pdev *pdev) 216 { 217 struct wlan_dfs *dfs; 218 219 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 220 if (!dfs) { 221 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 222 return QDF_STATUS_E_FAILURE; 223 } 224 225 if (!dfs->dfs_is_offload_enabled) 226 dfs_get_radars(dfs); 227 228 return QDF_STATUS_SUCCESS; 229 } 230 qdf_export_symbol(tgt_dfs_get_radars); 231 232 QDF_STATUS tgt_dfs_destroy_object(struct wlan_objmgr_pdev *pdev) 233 { 234 struct wlan_dfs *dfs; 235 236 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 237 if (!dfs) { 238 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 239 return QDF_STATUS_E_FAILURE; 240 } 241 242 dfs_destroy_object(dfs); 243 244 return QDF_STATUS_SUCCESS; 245 } 246 qdf_export_symbol(tgt_dfs_destroy_object); 247 248 #ifdef QCA_MCL_DFS_SUPPORT 249 QDF_STATUS tgt_dfs_set_tx_leakage_threshold(struct wlan_objmgr_pdev *pdev, 250 uint16_t tx_leakage_threshold) 251 { 252 struct wlan_dfs *dfs; 253 254 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 255 if (!dfs) { 256 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 257 return QDF_STATUS_E_FAILURE; 258 } 259 260 dfs->tx_leakage_threshold = tx_leakage_threshold; 261 262 return QDF_STATUS_SUCCESS; 263 } 264 qdf_export_symbol(tgt_dfs_set_tx_leakage_threshold); 265 #endif 266 267 QDF_STATUS tgt_dfs_control(struct wlan_objmgr_pdev *pdev, 268 u_int id, 269 void *indata, 270 uint32_t insize, 271 void *outdata, 272 uint32_t *outsize, 273 int *error) 274 { 275 struct wlan_dfs *dfs; 276 277 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 278 if (!dfs) { 279 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 280 return QDF_STATUS_E_FAILURE; 281 } 282 283 *error = dfs_control(dfs, id, indata, insize, outdata, outsize); 284 285 return QDF_STATUS_SUCCESS; 286 } 287 qdf_export_symbol(tgt_dfs_control); 288 289 QDF_STATUS tgt_dfs_find_vht80_chan_for_precac(struct wlan_objmgr_pdev *pdev, 290 uint32_t chan_mode, 291 uint8_t ch_freq_seg1, 292 uint32_t *cfreq1, 293 uint32_t *cfreq2, 294 uint32_t *phy_mode, 295 bool *dfs_set_cfreq2, 296 bool *set_agile) 297 { 298 struct wlan_dfs *dfs; 299 300 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 301 if (!dfs) { 302 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 303 return QDF_STATUS_E_FAILURE; 304 } 305 306 dfs_find_vht80_chan_for_precac(dfs, 307 chan_mode, 308 ch_freq_seg1, 309 cfreq1, 310 cfreq2, 311 phy_mode, 312 dfs_set_cfreq2, 313 set_agile); 314 315 return QDF_STATUS_SUCCESS; 316 } 317 qdf_export_symbol(tgt_dfs_find_vht80_chan_for_precac); 318 319 QDF_STATUS tgt_dfs_process_radar_ind(struct wlan_objmgr_pdev *pdev, 320 struct radar_found_info *radar_found) 321 { 322 struct wlan_dfs *dfs; 323 324 if (!pdev) { 325 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null pdev"); 326 return QDF_STATUS_E_FAILURE; 327 } 328 329 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 330 if (!dfs) { 331 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is null"); 332 return QDF_STATUS_E_FAILURE; 333 } 334 335 return dfs_process_radar_ind(dfs, radar_found); 336 } 337 qdf_export_symbol(tgt_dfs_process_radar_ind); 338 339 #ifndef QCA_MCL_DFS_SUPPORT 340 QDF_STATUS tgt_dfs_cac_complete(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id) 341 { 342 return QDF_STATUS_SUCCESS; 343 } 344 #else 345 QDF_STATUS tgt_dfs_cac_complete(struct wlan_objmgr_pdev *pdev, uint32_t vdev_id) 346 { 347 dfs_mlme_proc_cac(pdev, vdev_id); 348 349 return QDF_STATUS_SUCCESS; 350 } 351 #endif 352 qdf_export_symbol(tgt_dfs_cac_complete); 353 354 QDF_STATUS tgt_dfs_reg_ev_handler(struct wlan_objmgr_psoc *psoc, 355 bool dfs_offload) 356 { 357 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 358 359 if (!psoc) { 360 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 361 return QDF_STATUS_E_FAILURE; 362 } 363 364 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 365 if (!dfs_tx_ops) { 366 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "null dfs_tx_ops"); 367 return QDF_STATUS_E_FAILURE; 368 } 369 370 if (dfs_tx_ops->dfs_reg_ev_handler) 371 return dfs_tx_ops->dfs_reg_ev_handler(psoc, dfs_offload); 372 373 return QDF_STATUS_E_FAILURE; 374 } 375 qdf_export_symbol(tgt_dfs_reg_ev_handler); 376 377 QDF_STATUS tgt_dfs_stop(struct wlan_objmgr_pdev *pdev) 378 { 379 struct wlan_dfs *dfs; 380 381 dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); 382 if (!dfs) { 383 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 384 return QDF_STATUS_E_FAILURE; 385 } 386 387 dfs_stop(dfs); 388 389 return QDF_STATUS_SUCCESS; 390 } 391 qdf_export_symbol(tgt_dfs_stop); 392 393 QDF_STATUS tgt_dfs_process_emulate_bang_radar_cmd(struct wlan_objmgr_pdev *pdev, 394 struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test) 395 { 396 struct wlan_objmgr_psoc *psoc; 397 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 398 399 psoc = wlan_pdev_get_psoc(pdev); 400 if (!psoc) { 401 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 402 return QDF_STATUS_E_FAILURE; 403 } 404 405 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 406 if (dfs_tx_ops && dfs_tx_ops->dfs_process_emulate_bang_radar_cmd) 407 return dfs_tx_ops->dfs_process_emulate_bang_radar_cmd(pdev, 408 dfs_unit_test); 409 else 410 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 411 "dfs_tx_ops=%pK", dfs_tx_ops); 412 413 return QDF_STATUS_E_FAILURE; 414 } 415 qdf_export_symbol(tgt_dfs_process_emulate_bang_radar_cmd); 416 417 #ifdef QCA_MCL_DFS_SUPPORT 418 QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev) 419 { 420 struct wlan_objmgr_psoc *psoc; 421 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 422 struct dfs_soc_priv_obj *soc_obj; 423 424 psoc = wlan_pdev_get_psoc(pdev); 425 if (!psoc) { 426 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); 427 return QDF_STATUS_E_FAILURE; 428 } 429 430 soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 431 WLAN_UMAC_COMP_DFS); 432 if (!soc_obj) { 433 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 434 "Failed to get dfs psoc component"); 435 return QDF_STATUS_E_FAILURE; 436 } 437 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 438 if (dfs_tx_ops && dfs_tx_ops->dfs_set_phyerr_filter_offload) 439 return dfs_tx_ops->dfs_set_phyerr_filter_offload(pdev, 440 soc_obj->dfs_is_phyerr_filter_offload); 441 else 442 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 443 "dfs_tx_ops=%pK", dfs_tx_ops); 444 445 return QDF_STATUS_E_FAILURE; 446 } 447 qdf_export_symbol(tgt_dfs_set_phyerr_filter_offload); 448 #endif 449