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