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