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