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