1 /* 2 * Copyright (c) 2016-2020 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 init/deint functions for DFS module. 22 */ 23 24 #include "wlan_dfs_ucfg_api.h" 25 #include "wlan_dfs_tgt_api.h" 26 #include <wlan_objmgr_vdev_obj.h> 27 #include "wlan_dfs_utils_api.h" 28 #ifndef QCA_MCL_DFS_SUPPORT 29 #include "ieee80211_mlme_dfs_interface.h" 30 #endif 31 #include "wlan_objmgr_global_obj.h" 32 #include "wlan_dfs_init_deinit_api.h" 33 #include "wlan_dfs_lmac_api.h" 34 #include "../../core/src/dfs.h" 35 #include "a_types.h" 36 #include "wlan_serialization_api.h" 37 #include <qdf_trace.h> 38 #include "wlan_scan_ucfg_api.h" 39 #include "wlan_dfs_mlme_api.h" 40 #include "../../core/src/dfs_zero_cac.h" 41 42 struct dfs_to_mlme global_dfs_to_mlme; 43 44 struct wlan_dfs *wlan_pdev_get_dfs_obj(struct wlan_objmgr_pdev *pdev) 45 { 46 struct wlan_dfs *dfs; 47 dfs = wlan_objmgr_pdev_get_comp_private_obj(pdev, 48 WLAN_UMAC_COMP_DFS); 49 50 return dfs; 51 } 52 53 /* 54 * register_dfs_precac_auto_chan_callbacks_freq() - Register auto chan switch 55 * frequency based APIs callback. 56 * @mlme_callback: Pointer to dfs_to_mlme. 57 */ 58 #ifndef QCA_MCL_DFS_SUPPORT 59 #if defined(WLAN_DFS_PRECAC_AUTO_CHAN_SUPPORT) && defined(CONFIG_CHAN_FREQ_API) 60 static inline void 61 register_dfs_precac_auto_chan_callbacks_freq(struct dfs_to_mlme *mlme_callback) 62 { 63 if (!mlme_callback) 64 return; 65 66 mlme_callback->mlme_precac_chan_change_csa_for_freq = 67 mlme_dfs_precac_chan_change_csa_for_freq; 68 } 69 #else 70 static inline void 71 register_dfs_precac_auto_chan_callbacks_freq(struct dfs_to_mlme *mlme_callback) 72 { 73 } 74 #endif 75 #endif 76 77 /* 78 * register_dfs_callbacks_for_freq() - Register dfs callbacks. 79 * @mlme_callback: Pointer to dfs_to_mlme. 80 */ 81 #ifndef QCA_MCL_DFS_SUPPORT 82 #ifdef CONFIG_CHAN_FREQ_API 83 static inline void 84 register_dfs_callbacks_for_freq(struct dfs_to_mlme *mlme_callback) 85 { 86 if (!mlme_callback) 87 return; 88 89 mlme_callback->mlme_mark_dfs_for_freq = mlme_dfs_mark_dfs_for_freq; 90 mlme_callback->mlme_find_dot11_chan_for_freq = 91 mlme_dfs_find_dot11_chan_for_freq; 92 mlme_callback->mlme_get_dfs_channels_for_freq = 93 mlme_dfs_get_dfs_channels_for_freq; 94 mlme_callback->mlme_get_cac_timeout_for_freq = 95 mlme_dfs_get_cac_timeout_for_freq; 96 mlme_callback->mlme_get_extchan_for_freq = 97 mlme_dfs_get_extchan_for_freq; 98 mlme_callback->mlme_start_csa_for_freq = mlme_dfs_start_csa_for_freq; 99 } 100 #endif 101 #endif 102 103 #ifndef QCA_MCL_DFS_SUPPORT 104 void register_dfs_callbacks(void) 105 { 106 struct dfs_to_mlme *tmp_dfs_to_mlme = &global_dfs_to_mlme; 107 108 tmp_dfs_to_mlme->pdev_component_obj_attach = 109 wlan_objmgr_pdev_component_obj_attach; 110 tmp_dfs_to_mlme->pdev_component_obj_detach = 111 wlan_objmgr_pdev_component_obj_detach; 112 113 tmp_dfs_to_mlme->dfs_start_rcsa = mlme_dfs_start_rcsa; 114 tmp_dfs_to_mlme->mlme_proc_cac = mlme_dfs_proc_cac; 115 tmp_dfs_to_mlme->mlme_deliver_event_up_after_cac = 116 mlme_dfs_deliver_event_up_after_cac; 117 tmp_dfs_to_mlme->mlme_get_dfs_ch_nchans = mlme_dfs_get_dfs_ch_nchans; 118 tmp_dfs_to_mlme->mlme_set_no_chans_available = 119 mlme_dfs_set_no_chans_available; 120 tmp_dfs_to_mlme->mlme_ieee2mhz = mlme_dfs_ieee2mhz; 121 tmp_dfs_to_mlme->mlme_dfs_ch_flags_ext = mlme_dfs_dfs_ch_flags_ext; 122 tmp_dfs_to_mlme->mlme_channel_change_by_precac = 123 mlme_dfs_channel_change_by_precac; 124 tmp_dfs_to_mlme->mlme_nol_timeout_notification = 125 mlme_dfs_nol_timeout_notification; 126 tmp_dfs_to_mlme->mlme_clist_update = mlme_dfs_clist_update; 127 tmp_dfs_to_mlme->mlme_rebuild_chan_list_with_non_dfs_channels = 128 mlme_dfs_rebuild_chan_list_with_non_dfs_channels; 129 tmp_dfs_to_mlme->mlme_restart_vaps_with_non_dfs_chan = 130 mlme_dfs_restart_vaps_with_non_dfs_chan; 131 tmp_dfs_to_mlme->mlme_is_opmode_sta = 132 mlme_dfs_is_opmode_sta; 133 tmp_dfs_to_mlme->mlme_check_allowed_prim_chanlist = 134 mlme_dfs_check_allowed_prim_chanlist; 135 tmp_dfs_to_mlme->mlme_update_scan_channel_list = 136 mlme_dfs_update_scan_channel_list; 137 tmp_dfs_to_mlme->mlme_bringdown_vaps = 138 mlme_dfs_bringdown_vaps; 139 tmp_dfs_to_mlme->mlme_dfs_deliver_event = 140 mlme_dfs_deliver_event; 141 142 tmp_dfs_to_mlme->mlme_acquire_radar_mode_switch_lock = 143 mlme_acquire_radar_mode_switch_lock; 144 tmp_dfs_to_mlme->mlme_release_radar_mode_switch_lock = 145 mlme_release_radar_mode_switch_lock; 146 /* 147 * Register precac auto channel switch feature related callbacks 148 */ 149 register_dfs_precac_auto_chan_callbacks_freq(tmp_dfs_to_mlme); 150 /* Register freq based callbacks */ 151 register_dfs_callbacks_for_freq(tmp_dfs_to_mlme); 152 } 153 #else 154 void register_dfs_callbacks(void) 155 { 156 struct dfs_to_mlme *tmp_dfs_to_mlme = &global_dfs_to_mlme; 157 158 tmp_dfs_to_mlme->pdev_component_obj_attach = 159 wlan_objmgr_pdev_component_obj_attach; 160 tmp_dfs_to_mlme->pdev_component_obj_detach = 161 wlan_objmgr_pdev_component_obj_detach; 162 } 163 #endif 164 165 /** 166 * dfs_psoc_obj_create_notification() - dfs psoc create notification handler 167 * @psoc: psoc object 168 * @arg_list: Argument list 169 * 170 * Return: QDF_STATUS 171 */ 172 static QDF_STATUS dfs_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc, 173 void *arg_list) 174 { 175 QDF_STATUS status; 176 struct dfs_soc_priv_obj *dfs_soc_obj; 177 178 dfs_soc_obj = qdf_mem_malloc(sizeof(*dfs_soc_obj)); 179 if (!dfs_soc_obj) 180 return QDF_STATUS_E_NOMEM; 181 182 dfs_soc_obj->psoc = psoc; 183 184 status = wlan_objmgr_psoc_component_obj_attach(psoc, 185 WLAN_UMAC_COMP_DFS, 186 (void *)dfs_soc_obj, 187 QDF_STATUS_SUCCESS); 188 189 if (QDF_IS_STATUS_ERROR(status)) { 190 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 191 "Failed to attach psoc dfs component"); 192 qdf_mem_free(dfs_soc_obj); 193 return status; 194 } 195 /* Initialize precac timer here*/ 196 dfs_zero_cac_timer_init(dfs_soc_obj); 197 198 dfs_debug(NULL, WLAN_DEBUG_DFS1, 199 "DFS obj attach to psoc successfully"); 200 201 return status; 202 } 203 204 /** 205 * dfs_psoc_obj_destroy_notification() - dfs psoc destroy notification handler 206 * @psoc: psoc object 207 * @arg_list: Argument list 208 * 209 * Return: QDF_STATUS 210 */ 211 static QDF_STATUS dfs_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc, 212 void *arg_list) 213 { 214 QDF_STATUS status; 215 struct dfs_soc_priv_obj *dfs_soc_obj; 216 217 dfs_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 218 WLAN_UMAC_COMP_DFS); 219 if (!dfs_soc_obj) { 220 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 221 "Failed to get dfs obj in psoc"); 222 return QDF_STATUS_E_FAILURE; 223 } 224 225 dfs_zero_cac_timer_detach(dfs_soc_obj); 226 227 status = wlan_objmgr_psoc_component_obj_detach(psoc, 228 WLAN_UMAC_COMP_DFS, 229 dfs_soc_obj); 230 231 if (QDF_IS_STATUS_ERROR(status)) 232 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 233 "Failed to detach psoc dfs component"); 234 235 qdf_mem_free(dfs_soc_obj); 236 237 return status; 238 } 239 240 QDF_STATUS dfs_init(void) 241 { 242 QDF_STATUS status; 243 244 status = wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_DFS, 245 dfs_psoc_obj_create_notification, 246 NULL); 247 248 if (QDF_IS_STATUS_ERROR(status)) { 249 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 250 "Failed to register psoc create handler for dfs"); 251 goto err_psoc_create; 252 } 253 254 status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_DFS, 255 dfs_psoc_obj_destroy_notification, 256 NULL); 257 258 if (QDF_IS_STATUS_ERROR(status)) { 259 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 260 "Failed to register psoc delete handler for dfs"); 261 goto err_psoc_delete; 262 } 263 264 register_dfs_callbacks(); 265 266 status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_DFS, 267 wlan_dfs_pdev_obj_create_notification, 268 NULL); 269 270 if (QDF_IS_STATUS_ERROR(status)) { 271 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 272 "Failed to register pdev create handler for dfs"); 273 goto err_pdev_create; 274 } 275 276 status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, 277 wlan_dfs_pdev_obj_destroy_notification, 278 NULL); 279 280 if (QDF_IS_STATUS_ERROR(status)) { 281 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 282 "Failed to register pdev delete handler for dfs"); 283 goto err_pdev_delete; 284 } 285 286 status = qdf_print_set_category_verbose(qdf_get_pidx(), 287 QDF_MODULE_ID_DFS, QDF_TRACE_LEVEL_INFO, true); 288 289 if (QDF_IS_STATUS_ERROR(status)) { 290 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 291 "Failed to set verbose for category"); 292 goto err_category_verbose; 293 } 294 295 return QDF_STATUS_SUCCESS; 296 297 err_category_verbose: 298 wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, 299 wlan_dfs_pdev_obj_destroy_notification, 300 NULL); 301 err_pdev_delete: 302 wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS, 303 wlan_dfs_pdev_obj_create_notification, 304 NULL); 305 err_pdev_create: 306 wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS, 307 dfs_psoc_obj_destroy_notification, 308 NULL); 309 err_psoc_delete: 310 wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS, 311 dfs_psoc_obj_create_notification, 312 NULL); 313 err_psoc_create: 314 return status; 315 } 316 317 QDF_STATUS dfs_deinit(void) 318 { 319 QDF_STATUS status; 320 321 status = wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS, 322 dfs_psoc_obj_create_notification, 323 NULL); 324 325 if (QDF_IS_STATUS_ERROR(status)) 326 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 327 "Failed to deregister dfs psoc obj create"); 328 329 status = wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS, 330 dfs_psoc_obj_destroy_notification, 331 NULL); 332 333 if (QDF_IS_STATUS_ERROR(status)) 334 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 335 "Failed to deregister dfs psoc obj destroy"); 336 337 status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS, 338 wlan_dfs_pdev_obj_create_notification, 339 NULL); 340 341 if (QDF_IS_STATUS_ERROR(status)) 342 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 343 "Failed to deregister dfs pdev obj create"); 344 345 status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, 346 wlan_dfs_pdev_obj_destroy_notification, 347 NULL); 348 349 if (QDF_IS_STATUS_ERROR(status)) 350 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 351 "Failed to deregister dfs pdev obj destroy"); 352 353 return QDF_STATUS_SUCCESS; 354 } 355 356 QDF_STATUS wlan_dfs_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev, 357 void *arg) 358 { 359 struct wlan_dfs *dfs = NULL; 360 struct wlan_objmgr_psoc *psoc; 361 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 362 uint8_t pdev_id; 363 QDF_STATUS status; 364 bool is_5ghz = false; 365 366 if (!pdev) { 367 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null pdev"); 368 return QDF_STATUS_E_FAILURE; 369 } 370 371 psoc = wlan_pdev_get_psoc(pdev); 372 if (!psoc) { 373 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 374 return QDF_STATUS_E_FAILURE; 375 } 376 377 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 378 if (!(dfs_tx_ops && dfs_tx_ops->dfs_is_pdev_5ghz)) { 379 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_tx_ops is null"); 380 return QDF_STATUS_E_FAILURE; 381 } 382 383 status = dfs_tx_ops->dfs_is_pdev_5ghz(pdev, &is_5ghz); 384 if (QDF_IS_STATUS_ERROR(status)) { 385 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "Failed to get is_5ghz value"); 386 return QDF_STATUS_E_FAILURE; 387 } 388 389 if (!is_5ghz) { 390 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 391 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 392 "Do not allocate DFS object for 2G, pdev_id = %d", 393 pdev_id); 394 return QDF_STATUS_SUCCESS; 395 } 396 397 if (dfs_create_object(&dfs) == 1) { 398 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "failed to create object"); 399 return QDF_STATUS_E_FAILURE; 400 } 401 402 status = global_dfs_to_mlme.pdev_component_obj_attach(pdev, 403 WLAN_UMAC_COMP_DFS, (void *)dfs, QDF_STATUS_SUCCESS); 404 if (QDF_IS_STATUS_ERROR(status)) { 405 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "obj attach failed"); 406 dfs_destroy_object(dfs); 407 return QDF_STATUS_E_FAILURE; 408 } 409 410 dfs->dfs_pdev_obj = pdev; 411 412 if (!dfs_tx_ops->dfs_is_tgt_offload) { 413 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 414 "dfs_is_tgt_offload is null"); 415 dfs_destroy_object(dfs); 416 return QDF_STATUS_E_FAILURE; 417 } 418 419 dfs->dfs_is_offload_enabled = dfs_tx_ops->dfs_is_tgt_offload(psoc); 420 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_offload %d", 421 dfs->dfs_is_offload_enabled); 422 dfs_agile_soc_obj_init(dfs, psoc); 423 424 if (dfs_attach(dfs) == 1) { 425 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_attch failed"); 426 dfs_destroy_object(dfs); 427 return QDF_STATUS_E_FAILURE; 428 } 429 430 return QDF_STATUS_SUCCESS; 431 } 432 433 QDF_STATUS wlan_dfs_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev, 434 void *arg) 435 { 436 struct wlan_dfs *dfs = NULL; 437 438 if (!pdev) { 439 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "PDEV is NULL"); 440 return QDF_STATUS_E_FAILURE; 441 } 442 443 dfs = wlan_pdev_get_dfs_obj(pdev); 444 445 /* DFS is NULL during unload. should we call this function before */ 446 if (dfs) { 447 global_dfs_to_mlme.pdev_component_obj_detach(pdev, 448 WLAN_UMAC_COMP_DFS, 449 (void *)dfs); 450 451 dfs_detach(dfs); 452 dfs->dfs_pdev_obj = NULL; 453 dfs_destroy_object(dfs); 454 } 455 456 return QDF_STATUS_SUCCESS; 457 } 458 459 static void dfs_scan_serialization_comp_info_cb( 460 struct wlan_objmgr_vdev *vdev, 461 union wlan_serialization_rules_info *comp_info) 462 { 463 struct wlan_dfs *dfs = NULL; 464 struct wlan_objmgr_pdev *pdev; 465 466 if (!comp_info) { 467 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "comp_info is NULL"); 468 return; 469 } 470 471 if (!vdev) { 472 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "vdev is NULL"); 473 return; 474 } 475 476 pdev = wlan_vdev_get_pdev(vdev); 477 if (!pdev) { 478 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "pdev is NULL"); 479 return; 480 } 481 482 comp_info->scan_info.is_cac_in_progress = false; 483 484 if (!tgt_dfs_is_pdev_5ghz(pdev)) 485 return; 486 487 dfs = wlan_pdev_get_dfs_obj(pdev); 488 if (!dfs) { 489 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 490 return; 491 } 492 493 if (dfs_is_ap_cac_timer_running(dfs)) 494 comp_info->scan_info.is_cac_in_progress = true; 495 } 496 497 QDF_STATUS wifi_dfs_psoc_enable(struct wlan_objmgr_psoc *psoc) 498 { 499 QDF_STATUS status; 500 501 status = tgt_dfs_reg_ev_handler(psoc); 502 if (status != QDF_STATUS_SUCCESS) { 503 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "tgt_dfs_reg_ev_handler failed"); 504 return QDF_STATUS_E_FAILURE; 505 } 506 507 status = wlan_serialization_register_comp_info_cb(psoc, 508 WLAN_UMAC_COMP_DFS, 509 WLAN_SER_CMD_SCAN, 510 dfs_scan_serialization_comp_info_cb); 511 if (status != QDF_STATUS_SUCCESS) { 512 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "Serialize scan cmd register failed"); 513 return status; 514 } 515 516 return QDF_STATUS_SUCCESS; 517 } 518 519 QDF_STATUS wifi_dfs_psoc_disable(struct wlan_objmgr_psoc *psoc) 520 { 521 QDF_STATUS status; 522 523 status = wlan_serialization_deregister_comp_info_cb(psoc, 524 WLAN_UMAC_COMP_DFS, 525 WLAN_SER_CMD_SCAN); 526 if (status != QDF_STATUS_SUCCESS) { 527 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "Serialize scan cmd deregister failed"); 528 return status; 529 } 530 531 return QDF_STATUS_SUCCESS; 532 } 533