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 /* Initialize Rolling CAC timer */ 199 dfs_rcac_timer_init(dfs_soc_obj); 200 201 /* DFS Rolling CAC SM initialization */ 202 dfs_rcac_sm_create(dfs_soc_obj); 203 204 dfs_debug(NULL, WLAN_DEBUG_DFS1, 205 "DFS obj attach to psoc successfully"); 206 207 return status; 208 } 209 210 /** 211 * dfs_psoc_obj_destroy_notification() - dfs psoc destroy notification handler 212 * @psoc: psoc object 213 * @arg_list: Argument list 214 * 215 * Return: QDF_STATUS 216 */ 217 static QDF_STATUS dfs_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc, 218 void *arg_list) 219 { 220 QDF_STATUS status; 221 struct dfs_soc_priv_obj *dfs_soc_obj; 222 223 dfs_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 224 WLAN_UMAC_COMP_DFS); 225 if (!dfs_soc_obj) { 226 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 227 "Failed to get dfs obj in psoc"); 228 return QDF_STATUS_E_FAILURE; 229 } 230 231 /* Delete DFS Rolling CAC SM */ 232 dfs_rcac_sm_destroy(dfs_soc_obj); 233 234 dfs_rcac_timer_deinit(dfs_soc_obj); 235 dfs_zero_cac_timer_detach(dfs_soc_obj); 236 237 status = wlan_objmgr_psoc_component_obj_detach(psoc, 238 WLAN_UMAC_COMP_DFS, 239 dfs_soc_obj); 240 241 if (QDF_IS_STATUS_ERROR(status)) 242 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 243 "Failed to detach psoc dfs component"); 244 245 qdf_mem_free(dfs_soc_obj); 246 247 return status; 248 } 249 250 QDF_STATUS dfs_init(void) 251 { 252 QDF_STATUS status; 253 254 status = wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_DFS, 255 dfs_psoc_obj_create_notification, 256 NULL); 257 258 if (QDF_IS_STATUS_ERROR(status)) { 259 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 260 "Failed to register psoc create handler for dfs"); 261 goto err_psoc_create; 262 } 263 264 status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_DFS, 265 dfs_psoc_obj_destroy_notification, 266 NULL); 267 268 if (QDF_IS_STATUS_ERROR(status)) { 269 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 270 "Failed to register psoc delete handler for dfs"); 271 goto err_psoc_delete; 272 } 273 274 register_dfs_callbacks(); 275 276 status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_DFS, 277 wlan_dfs_pdev_obj_create_notification, 278 NULL); 279 280 if (QDF_IS_STATUS_ERROR(status)) { 281 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 282 "Failed to register pdev create handler for dfs"); 283 goto err_pdev_create; 284 } 285 286 status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, 287 wlan_dfs_pdev_obj_destroy_notification, 288 NULL); 289 290 if (QDF_IS_STATUS_ERROR(status)) { 291 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 292 "Failed to register pdev delete handler for dfs"); 293 goto err_pdev_delete; 294 } 295 296 status = qdf_print_set_category_verbose(qdf_get_pidx(), 297 QDF_MODULE_ID_DFS, QDF_TRACE_LEVEL_INFO, true); 298 299 if (QDF_IS_STATUS_ERROR(status)) { 300 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 301 "Failed to set verbose for category"); 302 goto err_category_verbose; 303 } 304 305 return QDF_STATUS_SUCCESS; 306 307 err_category_verbose: 308 wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, 309 wlan_dfs_pdev_obj_destroy_notification, 310 NULL); 311 err_pdev_delete: 312 wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS, 313 wlan_dfs_pdev_obj_create_notification, 314 NULL); 315 err_pdev_create: 316 wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS, 317 dfs_psoc_obj_destroy_notification, 318 NULL); 319 err_psoc_delete: 320 wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS, 321 dfs_psoc_obj_create_notification, 322 NULL); 323 err_psoc_create: 324 return status; 325 } 326 327 QDF_STATUS dfs_deinit(void) 328 { 329 QDF_STATUS status; 330 331 status = wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS, 332 dfs_psoc_obj_create_notification, 333 NULL); 334 335 if (QDF_IS_STATUS_ERROR(status)) 336 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 337 "Failed to deregister dfs psoc obj create"); 338 339 status = wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS, 340 dfs_psoc_obj_destroy_notification, 341 NULL); 342 343 if (QDF_IS_STATUS_ERROR(status)) 344 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 345 "Failed to deregister dfs psoc obj destroy"); 346 347 status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS, 348 wlan_dfs_pdev_obj_create_notification, 349 NULL); 350 351 if (QDF_IS_STATUS_ERROR(status)) 352 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 353 "Failed to deregister dfs pdev obj create"); 354 355 status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, 356 wlan_dfs_pdev_obj_destroy_notification, 357 NULL); 358 359 if (QDF_IS_STATUS_ERROR(status)) 360 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, 361 "Failed to deregister dfs pdev obj destroy"); 362 363 return QDF_STATUS_SUCCESS; 364 } 365 366 QDF_STATUS wlan_dfs_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev, 367 void *arg) 368 { 369 struct wlan_dfs *dfs = NULL; 370 struct wlan_objmgr_psoc *psoc; 371 struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; 372 uint8_t pdev_id; 373 QDF_STATUS status; 374 bool is_5ghz = false; 375 376 if (!pdev) { 377 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null pdev"); 378 return QDF_STATUS_E_FAILURE; 379 } 380 381 psoc = wlan_pdev_get_psoc(pdev); 382 if (!psoc) { 383 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "null psoc"); 384 return QDF_STATUS_E_FAILURE; 385 } 386 387 dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); 388 if (!(dfs_tx_ops && dfs_tx_ops->dfs_is_pdev_5ghz)) { 389 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_tx_ops is null"); 390 return QDF_STATUS_E_FAILURE; 391 } 392 393 status = dfs_tx_ops->dfs_is_pdev_5ghz(pdev, &is_5ghz); 394 if (QDF_IS_STATUS_ERROR(status)) { 395 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "Failed to get is_5ghz value"); 396 return QDF_STATUS_E_FAILURE; 397 } 398 399 if (!is_5ghz) { 400 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 401 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, 402 "Do not allocate DFS object for 2G, pdev_id = %d", 403 pdev_id); 404 return QDF_STATUS_SUCCESS; 405 } 406 407 if (dfs_create_object(&dfs) == 1) { 408 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "failed to create object"); 409 return QDF_STATUS_E_FAILURE; 410 } 411 412 status = global_dfs_to_mlme.pdev_component_obj_attach(pdev, 413 WLAN_UMAC_COMP_DFS, (void *)dfs, QDF_STATUS_SUCCESS); 414 if (QDF_IS_STATUS_ERROR(status)) { 415 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "obj attach failed"); 416 dfs_destroy_object(dfs); 417 return QDF_STATUS_E_FAILURE; 418 } 419 420 dfs->dfs_pdev_obj = pdev; 421 422 if (!dfs_tx_ops->dfs_is_tgt_offload) { 423 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, 424 "dfs_is_tgt_offload is null"); 425 dfs_destroy_object(dfs); 426 return QDF_STATUS_E_FAILURE; 427 } 428 429 dfs->dfs_is_offload_enabled = dfs_tx_ops->dfs_is_tgt_offload(psoc); 430 dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_offload %d", 431 dfs->dfs_is_offload_enabled); 432 dfs_agile_soc_obj_init(dfs, psoc); 433 434 if (dfs_attach(dfs) == 1) { 435 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs_attch failed"); 436 dfs_destroy_object(dfs); 437 return QDF_STATUS_E_FAILURE; 438 } 439 440 return QDF_STATUS_SUCCESS; 441 } 442 443 QDF_STATUS wlan_dfs_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev, 444 void *arg) 445 { 446 struct wlan_dfs *dfs = NULL; 447 448 if (!pdev) { 449 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "PDEV is NULL"); 450 return QDF_STATUS_E_FAILURE; 451 } 452 453 dfs = wlan_pdev_get_dfs_obj(pdev); 454 455 /* DFS is NULL during unload. should we call this function before */ 456 if (dfs) { 457 global_dfs_to_mlme.pdev_component_obj_detach(pdev, 458 WLAN_UMAC_COMP_DFS, 459 (void *)dfs); 460 461 dfs_detach(dfs); 462 dfs->dfs_pdev_obj = NULL; 463 dfs_destroy_object(dfs); 464 } 465 466 return QDF_STATUS_SUCCESS; 467 } 468 469 static void dfs_scan_serialization_comp_info_cb( 470 struct wlan_objmgr_vdev *vdev, 471 union wlan_serialization_rules_info *comp_info) 472 { 473 struct wlan_dfs *dfs = NULL; 474 struct wlan_objmgr_pdev *pdev; 475 476 if (!comp_info) { 477 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "comp_info is NULL"); 478 return; 479 } 480 481 if (!vdev) { 482 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "vdev is NULL"); 483 return; 484 } 485 486 pdev = wlan_vdev_get_pdev(vdev); 487 if (!pdev) { 488 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "pdev is NULL"); 489 return; 490 } 491 492 comp_info->scan_info.is_cac_in_progress = false; 493 494 if (!tgt_dfs_is_pdev_5ghz(pdev)) 495 return; 496 497 dfs = wlan_pdev_get_dfs_obj(pdev); 498 if (!dfs) { 499 dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); 500 return; 501 } 502 503 if (dfs_is_ap_cac_timer_running(dfs)) 504 comp_info->scan_info.is_cac_in_progress = true; 505 } 506 507 QDF_STATUS wifi_dfs_psoc_enable(struct wlan_objmgr_psoc *psoc) 508 { 509 QDF_STATUS status; 510 511 status = tgt_dfs_reg_ev_handler(psoc); 512 if (status != QDF_STATUS_SUCCESS) { 513 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "tgt_dfs_reg_ev_handler failed"); 514 return QDF_STATUS_E_FAILURE; 515 } 516 517 status = wlan_serialization_register_comp_info_cb(psoc, 518 WLAN_UMAC_COMP_DFS, 519 WLAN_SER_CMD_SCAN, 520 dfs_scan_serialization_comp_info_cb); 521 if (status != QDF_STATUS_SUCCESS) { 522 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "Serialize scan cmd register failed"); 523 return status; 524 } 525 526 return QDF_STATUS_SUCCESS; 527 } 528 529 QDF_STATUS wifi_dfs_psoc_disable(struct wlan_objmgr_psoc *psoc) 530 { 531 QDF_STATUS status; 532 533 status = wlan_serialization_deregister_comp_info_cb(psoc, 534 WLAN_UMAC_COMP_DFS, 535 WLAN_SER_CMD_SCAN); 536 if (status != QDF_STATUS_SUCCESS) { 537 dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "Serialize scan cmd deregister failed"); 538 return status; 539 } 540 541 return QDF_STATUS_SUCCESS; 542 } 543