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