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