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