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