1 /* 2 * Copyright (c) 2017 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * DOC: contains scan north bound interface definitions 21 */ 22 23 #include <scheduler_api.h> 24 #include <wlan_scan_ucfg_api.h> 25 #include <wlan_objmgr_global_obj.h> 26 #include <wlan_objmgr_cmn.h> 27 #include <wlan_serialization_api.h> 28 #include <wlan_scan_tgt_api.h> 29 #include <wlan_reg_services_api.h> 30 #include <wlan_utility.h> 31 #include "../../core/src/wlan_scan_main.h" 32 #include "../../core/src/wlan_scan_manager.h" 33 #include "../../core/src/wlan_scan_cache_db.h" 34 #ifdef WLAN_PMO_ENABLE 35 #include <wlan_pmo_obj_mgmt_api.h> 36 #endif 37 #ifdef WLAN_POLICY_MGR_ENABLE 38 #include <wlan_policy_mgr_api.h> 39 #endif 40 41 QDF_STATUS ucfg_scan_register_bcn_cb(struct wlan_objmgr_psoc *psoc, 42 update_beacon_cb cb, enum scan_cb_type type) 43 { 44 return scm_scan_register_bcn_cb(psoc, cb, type); 45 } 46 47 qdf_list_t *ucfg_scan_get_result(struct wlan_objmgr_pdev *pdev, 48 struct scan_filter *filter) 49 { 50 return scm_get_scan_result(pdev, filter); 51 } 52 53 QDF_STATUS ucfg_scan_db_iterate(struct wlan_objmgr_pdev *pdev, 54 scan_iterator_func func, void *arg) 55 { 56 return scm_iterate_scan_db(pdev, func, arg); 57 } 58 59 QDF_STATUS ucfg_scan_purge_results(qdf_list_t *scan_list) 60 { 61 return scm_purge_scan_results(scan_list); 62 } 63 64 QDF_STATUS ucfg_scan_flush_results(struct wlan_objmgr_pdev *pdev, 65 struct scan_filter *filter) 66 { 67 return scm_flush_results(pdev, filter); 68 } 69 70 void ucfg_scan_filter_valid_channel(struct wlan_objmgr_pdev *pdev, 71 uint8_t *chan_list, uint32_t num_chan) 72 { 73 scm_filter_valid_channel(pdev, chan_list, num_chan); 74 } 75 76 QDF_STATUS ucfg_scan_init(void) 77 { 78 QDF_STATUS status; 79 80 status = wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_SCAN, 81 wlan_scan_psoc_created_notification, NULL); 82 if (QDF_IS_STATUS_ERROR(status)) { 83 scm_err("Failed to register psoc create handler"); 84 goto fail_create_psoc; 85 } 86 87 status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN, 88 wlan_scan_psoc_destroyed_notification, NULL); 89 if (QDF_IS_STATUS_ERROR(status)) { 90 scm_err("Failed to create psoc delete handler"); 91 goto fail_psoc_destroy; 92 } 93 scm_info("scan psoc create and delete handler registered with objmgr"); 94 95 status = wlan_objmgr_register_vdev_create_handler(WLAN_UMAC_COMP_SCAN, 96 wlan_scan_vdev_created_notification, NULL); 97 if (QDF_IS_STATUS_ERROR(status)) { 98 scm_err("Failed to register vdev create handler"); 99 goto fail_pdev_create; 100 } 101 102 status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_SCAN, 103 wlan_scan_vdev_destroyed_notification, NULL); 104 if (QDF_IS_STATUS_SUCCESS(status)) { 105 scm_info("scan vdev create and delete handler registered with objmgr"); 106 return QDF_STATUS_SUCCESS; 107 } 108 109 scm_err("Failed to destroy vdev delete handler"); 110 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN, 111 wlan_scan_vdev_created_notification, NULL); 112 fail_pdev_create: 113 wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN, 114 wlan_scan_psoc_destroyed_notification, NULL); 115 fail_psoc_destroy: 116 wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SCAN, 117 wlan_scan_psoc_created_notification, NULL); 118 fail_create_psoc: 119 return status; 120 } 121 122 QDF_STATUS ucfg_scan_deinit(void) 123 { 124 QDF_STATUS status; 125 126 status = wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SCAN, 127 wlan_scan_psoc_created_notification, NULL); 128 if (status != QDF_STATUS_SUCCESS) 129 scm_err("Failed to unregister psoc create handler"); 130 131 status = wlan_objmgr_unregister_psoc_destroy_handler( 132 WLAN_UMAC_COMP_SCAN, 133 wlan_scan_psoc_destroyed_notification, NULL); 134 if (status != QDF_STATUS_SUCCESS) 135 scm_err("Failed to unregister psoc delete handler"); 136 137 status = wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN, 138 wlan_scan_vdev_created_notification, NULL); 139 if (status != QDF_STATUS_SUCCESS) 140 scm_err("Failed to unregister vdev create handler"); 141 142 status = wlan_objmgr_unregister_vdev_destroy_handler( 143 WLAN_UMAC_COMP_SCAN, 144 wlan_scan_vdev_destroyed_notification, NULL); 145 if (status != QDF_STATUS_SUCCESS) 146 scm_err("Failed to unregister vdev delete handler"); 147 148 return status; 149 } 150 151 #ifdef FEATURE_WLAN_SCAN_PNO 152 153 QDF_STATUS ucfg_scan_pno_start(struct wlan_objmgr_vdev *vdev, 154 struct pno_scan_req_params *req) 155 { 156 struct scan_vdev_obj *scan_vdev_obj; 157 QDF_STATUS status; 158 159 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 160 if (!scan_vdev_obj) { 161 scm_err("null scan_vdev_obj"); 162 return QDF_STATUS_E_INVAL; 163 } 164 if (scan_vdev_obj->pno_in_progress) { 165 scm_err("pno already in progress"); 166 return QDF_STATUS_E_ALREADY; 167 } 168 169 status = tgt_scan_pno_start(vdev, req); 170 if (QDF_IS_STATUS_ERROR(status)) 171 scm_err("pno start failed"); 172 else 173 scan_vdev_obj->pno_in_progress = true; 174 175 return status; 176 } 177 178 QDF_STATUS ucfg_scan_pno_stop(struct wlan_objmgr_vdev *vdev) 179 { 180 struct scan_vdev_obj *scan_vdev_obj; 181 QDF_STATUS status; 182 183 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 184 if (!scan_vdev_obj) { 185 scm_err("null scan_vdev_obj"); 186 return QDF_STATUS_E_INVAL; 187 } 188 if (!scan_vdev_obj->pno_in_progress) { 189 scm_err("pno already stopped"); 190 return QDF_STATUS_E_ALREADY; 191 } 192 193 status = tgt_scan_pno_stop(vdev, wlan_vdev_get_id(vdev)); 194 if (QDF_IS_STATUS_ERROR(status)) 195 scm_err("pno start failed"); 196 else 197 scan_vdev_obj->pno_in_progress = false; 198 199 return status; 200 } 201 202 bool ucfg_scan_get_pno_in_progress(struct wlan_objmgr_vdev *vdev) 203 { 204 struct scan_vdev_obj *scan_vdev_obj; 205 206 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 207 if (!scan_vdev_obj) { 208 scm_err("null scan_vdev_obj"); 209 return false; 210 } 211 212 return scan_vdev_obj->pno_in_progress; 213 } 214 215 bool ucfg_scan_get_pno_match(struct wlan_objmgr_vdev *vdev) 216 { 217 struct scan_vdev_obj *scan_vdev_obj; 218 219 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 220 if (!scan_vdev_obj) { 221 scm_err("null scan_vdev_obj"); 222 return false; 223 } 224 225 return scan_vdev_obj->pno_match_evt_received; 226 } 227 228 static QDF_STATUS 229 wlan_pno_global_init(struct pno_def_config *pno_def) 230 { 231 struct nlo_mawc_params *mawc_cfg; 232 233 qdf_wake_lock_create(&pno_def->pno_wake_lock, "wlan_pno_wl"); 234 mawc_cfg = &pno_def->mawc_params; 235 pno_def->channel_prediction = SCAN_PNO_CHANNEL_PREDICTION; 236 pno_def->top_k_num_of_channels = SCAN_TOP_K_NUM_OF_CHANNELS; 237 pno_def->stationary_thresh = SCAN_STATIONARY_THRESHOLD; 238 pno_def->channel_prediction_full_scan = 239 SCAN_CHANNEL_PREDICTION_FULL_SCAN_MS; 240 pno_def->adaptive_dwell_mode = SCAN_ADAPTIVE_PNOSCAN_DWELL_MODE; 241 mawc_cfg->enable = SCAN_MAWC_NLO_ENABLED; 242 mawc_cfg->exp_backoff_ratio = SCAN_MAWC_NLO_EXP_BACKOFF_RATIO; 243 mawc_cfg->init_scan_interval = SCAN_MAWC_NLO_INIT_SCAN_INTERVAL; 244 mawc_cfg->max_scan_interval = SCAN_MAWC_NLO_MAX_SCAN_INTERVAL; 245 246 return QDF_STATUS_SUCCESS; 247 } 248 249 static QDF_STATUS 250 wlan_pno_global_deinit(struct pno_def_config *pno_def) 251 { 252 qdf_wake_lock_destroy(&pno_def->pno_wake_lock); 253 254 return QDF_STATUS_SUCCESS; 255 } 256 257 QDF_STATUS 258 ucfg_scan_get_pno_def_params(struct wlan_objmgr_vdev *vdev, 259 struct pno_scan_req_params *req) 260 { 261 struct scan_default_params *scan_def; 262 struct wlan_scan_obj *scan = wlan_vdev_get_scan_obj(vdev); 263 struct pno_def_config *pno_def; 264 265 if (!vdev | !req | !scan) { 266 scm_err("vdev: 0x%pK, req: 0x%pK scan_obj: 0x%pK", 267 vdev, req, scan); 268 return QDF_STATUS_E_INVAL; 269 } 270 271 scan_def = wlan_vdev_get_def_scan_params(vdev); 272 pno_def = &scan->pno_cfg; 273 274 req->active_dwell_time = scan_def->active_dwell; 275 req->passive_dwell_time = scan_def->passive_dwell; 276 277 req->adaptive_dwell_mode = pno_def->adaptive_dwell_mode; 278 279 req->pno_channel_prediction = pno_def->adaptive_dwell_mode; 280 req->top_k_num_of_channels = pno_def->top_k_num_of_channels; 281 req->stationary_thresh = pno_def->stationary_thresh; 282 req->channel_prediction_full_scan = 283 pno_def->channel_prediction_full_scan; 284 req->mawc_params.vdev_id = wlan_vdev_get_id(vdev); 285 qdf_mem_copy(&req->mawc_params, &pno_def->mawc_params, 286 sizeof(req->mawc_params)); 287 288 return QDF_STATUS_SUCCESS; 289 } 290 291 static QDF_STATUS ucfg_scan_update_pno_config(struct pno_def_config *pno, 292 struct pno_user_cfg *pno_cfg) 293 { 294 pno->channel_prediction = pno_cfg->channel_prediction; 295 pno->top_k_num_of_channels = pno_cfg->top_k_num_of_channels; 296 pno->stationary_thresh = pno_cfg->stationary_thresh; 297 pno->adaptive_dwell_mode = pno_cfg->adaptive_dwell_mode; 298 pno->channel_prediction_full_scan = 299 pno_cfg->channel_prediction_full_scan; 300 qdf_mem_copy(&pno->mawc_params, &pno_cfg->mawc_params, 301 sizeof(pno->mawc_params)); 302 303 return QDF_STATUS_SUCCESS; 304 } 305 306 QDF_STATUS 307 ucfg_scan_register_pno_cb(struct wlan_objmgr_psoc *psoc, 308 scan_event_handler event_cb, void *arg) 309 { 310 struct wlan_scan_obj *scan; 311 312 if (!psoc) { 313 scm_err("null psoc"); 314 return QDF_STATUS_E_INVAL; 315 } 316 scan = wlan_psoc_get_scan_obj(psoc); 317 qdf_spin_lock_bh(&scan->lock); 318 scan->pno_cfg.pno_cb.func = event_cb; 319 scan->pno_cfg.pno_cb.arg = arg; 320 qdf_spin_unlock_bh(&scan->lock); 321 scm_info("event_cb: 0x%pK, arg: 0x%pK", event_cb, arg); 322 323 return QDF_STATUS_SUCCESS; 324 } 325 326 #else 327 328 static inline QDF_STATUS 329 wlan_pno_global_init(struct pno_def_config *pno_def) 330 { 331 return QDF_STATUS_SUCCESS; 332 } 333 static inline QDF_STATUS 334 wlan_pno_global_deinit(struct pno_def_config *pno_def) 335 { 336 return QDF_STATUS_SUCCESS; 337 } 338 339 static inline QDF_STATUS 340 ucfg_scan_update_pno_config(struct pno_def_config *pno, 341 struct pno_user_cfg *pno_cfg) 342 { 343 return QDF_STATUS_SUCCESS; 344 } 345 346 #endif 347 348 #ifdef WLAN_POLICY_MGR_ENABLE 349 /** 350 * ucfg_scan_update_dbs_scan_ctrl_ext_flag() - update dbs scan ctrl flags 351 * @req: pointer to scan request 352 * 353 * This function updates the dbs scan ctrl flags. 354 * Non-DBS scan is requested if any of the below case is met: 355 * 1. HW is DBS incapable 356 * 2. Directed scan 357 * 3. Channel list has only few channels 358 * 4. Channel list has single band channels 359 * For remaining cases, dbs scan is requested. 360 * 361 * Return: None 362 */ 363 static void 364 ucfg_scan_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req) 365 { 366 uint32_t num_chan; 367 struct wlan_objmgr_psoc *psoc; 368 uint32_t scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS; 369 uint32_t conn_cnt; 370 371 psoc = wlan_vdev_get_psoc(req->vdev); 372 373 if (DISABLE_DBS_CXN_AND_SCAN == 374 wlan_objmgr_psoc_get_dual_mac_disable(psoc)) 375 goto end; 376 377 conn_cnt = policy_mgr_get_connection_count(psoc); 378 if (conn_cnt > 0) { 379 scm_debug("%d active connections, go for DBS scan", 380 conn_cnt); 381 scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT; 382 goto end; 383 } 384 385 if (req->scan_req.num_ssids) { 386 scm_debug("directed SSID"); 387 goto end; 388 } 389 390 if (req->scan_req.num_bssid) { 391 scm_debug("directed BSSID"); 392 goto end; 393 } 394 395 num_chan = req->scan_req.chan_list.num_chan; 396 397 /* num_chan=0 means all channels */ 398 if (!num_chan) 399 scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT; 400 401 if (num_chan < SCAN_MIN_CHAN_DBS_SCAN_THRESHOLD) 402 goto end; 403 404 while (num_chan > 1) { 405 if (!WLAN_REG_IS_SAME_BAND_CHANNELS( 406 req->scan_req.chan_list.chan[0].freq, 407 req->scan_req.chan_list.chan[num_chan-1].freq)) { 408 scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT; 409 break; 410 } 411 num_chan--; 412 } 413 414 end: 415 req->scan_req.scan_ctrl_flags_ext |= 416 ((scan_dbs_policy << SCAN_FLAG_EXT_DBS_SCAN_POLICY_BIT) 417 & SCAN_FLAG_EXT_DBS_SCAN_POLICY_MASK); 418 scm_debug("scan_ctrl_flags_ext: 0x%x", 419 req->scan_req.scan_ctrl_flags_ext); 420 } 421 #else 422 static void 423 ucfg_scan_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req) 424 { 425 } 426 #endif 427 428 QDF_STATUS 429 ucfg_scan_start(struct scan_start_request *req) 430 { 431 struct scheduler_msg msg = {0}; 432 QDF_STATUS status; 433 struct wlan_scan_obj *scan_obj; 434 struct wlan_objmgr_pdev *pdev; 435 436 if (!req || !req->vdev) { 437 scm_err("vdev: %pK, req: %pK", req->vdev, req); 438 if (req) 439 scm_scan_free_scan_request_mem(req); 440 return QDF_STATUS_E_NULL_VALUE; 441 } 442 443 pdev = wlan_vdev_get_pdev(req->vdev); 444 if (!pdev) { 445 scm_err("Failed to get pdev object"); 446 scm_scan_free_scan_request_mem(req); 447 return QDF_STATUS_E_NULL_VALUE; 448 } 449 450 scan_obj = wlan_pdev_get_scan_obj(pdev); 451 if (!scan_obj) { 452 scm_err("Failed to get scan object"); 453 scm_scan_free_scan_request_mem(req); 454 return QDF_STATUS_E_NULL_VALUE; 455 } 456 457 if (!scan_obj->enable_scan) { 458 scm_err("scan disabled, rejecting the scan req"); 459 scm_scan_free_scan_request_mem(req); 460 return QDF_STATUS_E_AGAIN; 461 } 462 463 scm_debug("reqid: %d, scanid: %d, vdevid: %d", 464 req->scan_req.scan_req_id, req->scan_req.scan_id, 465 req->scan_req.vdev_id); 466 467 /* Overwrite scan parameters as required */ 468 if (!ucfg_scan_get_wide_band_scan(pdev)) { 469 scm_debug("wide_band_scan not supported, Scan 20 MHz"); 470 req->scan_req.scan_f_wide_band = false; 471 } 472 473 if (scan_obj->scan_def.usr_cfg_probe_rpt_time) { 474 req->scan_req.repeat_probe_time = 475 scan_obj->scan_def.usr_cfg_probe_rpt_time; 476 scm_debug("usr_cfg_probe_rpt_time %d", 477 req->scan_req.repeat_probe_time); 478 } 479 480 if (scan_obj->scan_def.usr_cfg_num_probes) { 481 req->scan_req.n_probes = scan_obj->scan_def.usr_cfg_num_probes; 482 scm_debug("usr_cfg_num_probes %d", req->scan_req.n_probes); 483 } 484 ucfg_scan_update_dbs_scan_ctrl_ext_flag(req); 485 if (req->scan_req.scan_f_passive) 486 req->scan_req.scan_ctrl_flags_ext |= 487 SCAN_FLAG_EXT_FILTER_PUBLIC_ACTION_FRAME; 488 489 /* Try to get vdev reference. Return if reference could 490 * not be taken. Reference will be released once scan 491 * request handling completes along with free of @req. 492 */ 493 status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID); 494 if (QDF_IS_STATUS_ERROR(status)) { 495 scm_info("unable to get reference"); 496 scm_scan_free_scan_request_mem(req); 497 return status; 498 } 499 500 msg.bodyptr = req; 501 msg.callback = scm_scan_start_req; 502 msg.flush_callback = scm_scan_start_flush_callback; 503 504 status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg); 505 if (QDF_IS_STATUS_ERROR(status)) { 506 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 507 scm_err("failed to post to QDF_MODULE_ID_OS_IF"); 508 scm_scan_free_scan_request_mem(req); 509 } 510 511 return status; 512 } 513 514 QDF_STATUS ucfg_scan_set_enable(struct wlan_objmgr_psoc *psoc, bool enable) 515 { 516 struct wlan_scan_obj *scan_obj; 517 518 scan_obj = wlan_psoc_get_scan_obj(psoc); 519 if (!scan_obj) { 520 scm_err("Failed to get scan object"); 521 return QDF_STATUS_E_NULL_VALUE; 522 } 523 scan_obj->enable_scan = enable; 524 scm_debug("set enable_scan to %d", scan_obj->enable_scan); 525 526 return QDF_STATUS_SUCCESS; 527 } 528 529 bool ucfg_scan_get_enable(struct wlan_objmgr_psoc *psoc) 530 { 531 struct wlan_scan_obj *scan_obj; 532 533 scan_obj = wlan_psoc_get_scan_obj(psoc); 534 if (!scan_obj) { 535 scm_err("Failed to get scan object"); 536 return false; 537 } 538 return scan_obj->enable_scan; 539 } 540 541 QDF_STATUS 542 ucfg_scan_set_wide_band_scan(struct wlan_objmgr_pdev *pdev, bool enable) 543 { 544 uint8_t pdev_id; 545 struct wlan_scan_obj *scan_obj; 546 547 if (!pdev) { 548 scm_warn("null vdev"); 549 return QDF_STATUS_E_NULL_VALUE; 550 } 551 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 552 scan_obj = wlan_pdev_get_scan_obj(pdev); 553 554 scm_debug("set wide_band_scan to %d", enable); 555 scan_obj->pdev_info[pdev_id].wide_band_scan = enable; 556 557 return QDF_STATUS_SUCCESS; 558 } 559 560 bool ucfg_scan_get_wide_band_scan(struct wlan_objmgr_pdev *pdev) 561 { 562 uint8_t pdev_id; 563 struct wlan_scan_obj *scan_obj; 564 565 if (!pdev) { 566 scm_warn("null vdev"); 567 return QDF_STATUS_E_NULL_VALUE; 568 } 569 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 570 scan_obj = wlan_pdev_get_scan_obj(pdev); 571 572 return scan_obj->pdev_info[pdev_id].wide_band_scan; 573 } 574 575 QDF_STATUS 576 ucfg_scan_cancel(struct scan_cancel_request *req) 577 { 578 struct scheduler_msg msg = {0}; 579 QDF_STATUS status; 580 581 if (!req || !req->vdev) { 582 scm_err("vdev: %pK, req: %pK", req->vdev, req); 583 if (req) 584 qdf_mem_free(req); 585 return QDF_STATUS_E_NULL_VALUE; 586 } 587 scm_info("reqid: %d, scanid: %d, vdevid: %d, type: %d", 588 req->cancel_req.requester, req->cancel_req.scan_id, 589 req->cancel_req.vdev_id, req->cancel_req.req_type); 590 591 status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID); 592 if (QDF_IS_STATUS_ERROR(status)) { 593 scm_info("Failed to get vdev ref; status:%d", status); 594 goto req_free; 595 } 596 597 msg.bodyptr = req; 598 msg.callback = scm_scan_cancel_req; 599 msg.flush_callback = scm_scan_cancel_flush_callback; 600 601 status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg); 602 if (QDF_IS_STATUS_ERROR(status)) { 603 scm_err("failed to post to QDF_MODULE_ID_OS_IF"); 604 goto vdev_put; 605 } 606 607 return QDF_STATUS_SUCCESS; 608 609 vdev_put: 610 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 611 612 req_free: 613 qdf_mem_free(req); 614 615 return status; 616 } 617 618 QDF_STATUS 619 ucfg_scan_cancel_sync(struct scan_cancel_request *req) 620 { 621 QDF_STATUS status; 622 bool cancel_vdev = false, cancel_pdev = false; 623 struct wlan_objmgr_vdev *vdev; 624 struct wlan_objmgr_pdev *pdev; 625 uint32_t max_wait_iterations = SCM_CANCEL_SCAN_WAIT_ITERATION; 626 qdf_event_t cancel_scan_event; 627 628 if (!req || !req->vdev) { 629 scm_err("vdev: %pK, req: %pK", req->vdev, req); 630 if (req) 631 qdf_mem_free(req); 632 return QDF_STATUS_E_NULL_VALUE; 633 } 634 635 if (req->cancel_req.req_type == 636 WLAN_SCAN_CANCEL_PDEV_ALL) 637 cancel_pdev = true; 638 else if (req->cancel_req.req_type == 639 WLAN_SCAN_CANCEL_VDEV_ALL) 640 cancel_vdev = true; 641 642 vdev = req->vdev; 643 status = ucfg_scan_cancel(req); 644 if (QDF_IS_STATUS_ERROR(status)) { 645 scm_err("failed to post to QDF_MODULE_ID_OS_IF"); 646 return status; 647 } 648 649 /* 650 * If cancel req is to cancel all scan of pdev or vdev 651 * wait untill all scan of pdev or vdev get cancelled 652 */ 653 qdf_event_create(&cancel_scan_event); 654 qdf_event_reset(&cancel_scan_event); 655 656 if (cancel_pdev) { 657 pdev = wlan_vdev_get_pdev(vdev); 658 while ((ucfg_scan_get_pdev_status(pdev) != 659 SCAN_NOT_IN_PROGRESS) && max_wait_iterations) { 660 scm_debug("wait for all pdev scan to get complete"); 661 qdf_wait_single_event(&cancel_scan_event, 662 qdf_system_msecs_to_ticks( 663 SCM_CANCEL_SCAN_WAIT_TIME)); 664 max_wait_iterations--; 665 } 666 } else if (cancel_vdev) { 667 while ((ucfg_scan_get_vdev_status(vdev) != 668 SCAN_NOT_IN_PROGRESS) && max_wait_iterations) { 669 scm_debug("wait for all vdev scan to get complete"); 670 qdf_wait_single_event(&cancel_scan_event, 671 qdf_system_msecs_to_ticks( 672 SCM_CANCEL_SCAN_WAIT_TIME)); 673 max_wait_iterations--; 674 } 675 } 676 677 qdf_event_destroy(&cancel_scan_event); 678 679 if (!max_wait_iterations) { 680 scm_err("Failed to wait for scans to get complete"); 681 return QDF_STATUS_E_TIMEOUT; 682 } 683 684 return status; 685 } 686 687 wlan_scan_requester 688 ucfg_scan_register_requester(struct wlan_objmgr_psoc *psoc, 689 uint8_t *name, scan_event_handler event_cb, void *arg) 690 { 691 int i, j; 692 struct wlan_scan_obj *scan; 693 struct scan_requester_info *requesters; 694 wlan_scan_requester requester = {0}; 695 696 if (!psoc) { 697 scm_err("null psoc"); 698 return 0; 699 } 700 scan = wlan_psoc_get_scan_obj(psoc); 701 requesters = scan->requesters; 702 qdf_spin_lock_bh(&scan->lock); 703 for (i = 0; i < WLAN_MAX_REQUESTORS; ++i) { 704 if (requesters[i].requester == 0) { 705 requesters[i].requester = 706 WLAN_SCAN_REQUESTER_ID_PREFIX | i; 707 j = 0; 708 while (name[j] && (j < (WLAN_MAX_MODULE_NAME - 1))) { 709 requesters[i].module[j] = name[j]; 710 ++j; 711 } 712 requesters[i].module[j] = 0; 713 requesters[i].ev_handler.func = event_cb; 714 requesters[i].ev_handler.arg = arg; 715 requester = requesters[i].requester; 716 break; 717 } 718 } 719 qdf_spin_unlock_bh(&scan->lock); 720 scm_info("module: %s, event_cb: 0x%pK, arg: 0x%pK, reqid: %d", 721 name, event_cb, arg, requester); 722 723 return requester; 724 } 725 726 void 727 ucfg_scan_unregister_requester(struct wlan_objmgr_psoc *psoc, 728 wlan_scan_requester requester) 729 { 730 int idx = requester & ~WLAN_SCAN_REQUESTER_ID_PREFIX; 731 struct wlan_scan_obj *scan; 732 struct scan_requester_info *requesters; 733 734 if (!psoc) { 735 scm_err("null psoc"); 736 return; 737 } 738 scan = wlan_psoc_get_scan_obj(psoc); 739 requesters = scan->requesters; 740 scm_info("reqid: %d", requester); 741 742 qdf_spin_lock_bh(&scan->lock); 743 requesters[idx].requester = 0; 744 requesters[idx].module[0] = 0; 745 requesters[idx].ev_handler.func = NULL; 746 requesters[idx].ev_handler.arg = NULL; 747 qdf_spin_unlock_bh(&scan->lock); 748 } 749 750 uint8_t* 751 ucfg_get_scan_requester_name(struct wlan_objmgr_psoc *psoc, 752 wlan_scan_requester requester) 753 { 754 int idx = requester & ~WLAN_SCAN_REQUESTER_ID_PREFIX; 755 struct wlan_scan_obj *scan; 756 struct scan_requester_info *requesters; 757 758 if (!psoc) { 759 scm_err("null psoc"); 760 return "null"; 761 } 762 scan = wlan_psoc_get_scan_obj(psoc); 763 requesters = scan->requesters; 764 765 if ((idx < WLAN_MAX_REQUESTORS) && 766 (requesters[idx].requester == requester)) { 767 return requesters[idx].module; 768 } 769 770 return (uint8_t *)"unknown"; 771 } 772 773 wlan_scan_id 774 ucfg_scan_get_scan_id(struct wlan_objmgr_psoc *psoc) 775 { 776 wlan_scan_id id; 777 struct wlan_scan_obj *scan; 778 779 if (!psoc) { 780 QDF_ASSERT(0); 781 scm_err("null psoc"); 782 return 0; 783 } 784 scan = wlan_psoc_get_scan_obj(psoc); 785 786 id = qdf_atomic_inc_return(&scan->scan_ids); 787 id = id & WLAN_SCAN_ID_MASK; 788 /* Mark this scan request as triggered by host 789 * by setting WLAN_HOST_SCAN_REQ_ID_PREFIX flag. 790 */ 791 id = id | WLAN_HOST_SCAN_REQ_ID_PREFIX; 792 scm_info("scan_id: 0x%x", id); 793 794 return id; 795 } 796 797 static QDF_STATUS 798 scm_add_scan_event_handler(struct pdev_scan_ev_handler *pdev_ev_handler, 799 scan_event_handler event_cb, void *arg) 800 { 801 struct cb_handler *cb_handler; 802 uint32_t handler_cnt = pdev_ev_handler->handler_cnt; 803 804 /* Assign next available slot to this registration request */ 805 cb_handler = &(pdev_ev_handler->cb_handlers[handler_cnt]); 806 cb_handler->func = event_cb; 807 cb_handler->arg = arg; 808 pdev_ev_handler->handler_cnt++; 809 810 return QDF_STATUS_SUCCESS; 811 } 812 813 QDF_STATUS 814 ucfg_scan_register_event_handler(struct wlan_objmgr_pdev *pdev, 815 scan_event_handler event_cb, void *arg) 816 { 817 uint32_t idx; 818 struct wlan_scan_obj *scan; 819 struct pdev_scan_ev_handler *pdev_ev_handler; 820 struct cb_handler *cb_handler; 821 822 /* scan event handler call back can't be NULL */ 823 if (!pdev || !event_cb) { 824 scm_err("pdev: %pK, event_cb: %pK", pdev, event_cb); 825 return QDF_STATUS_E_NULL_VALUE; 826 } 827 828 scm_info("pdev: %pK, event_cb: %pK, arg: %pK\n", pdev, event_cb, arg); 829 830 scan = wlan_pdev_get_scan_obj(pdev); 831 pdev_ev_handler = wlan_pdev_get_pdev_scan_ev_handlers(pdev); 832 cb_handler = &(pdev_ev_handler->cb_handlers[0]); 833 834 qdf_spin_lock_bh(&scan->lock); 835 /* Ensure its not a duplicate registration request */ 836 for (idx = 0; idx < MAX_SCAN_EVENT_HANDLERS_PER_PDEV; 837 idx++, cb_handler++) { 838 if ((cb_handler->func == event_cb) && 839 (cb_handler->arg == arg)) { 840 qdf_spin_unlock_bh(&scan->lock); 841 scm_warn("func: %pK, arg: %pK already exists", 842 event_cb, arg); 843 return QDF_STATUS_SUCCESS; 844 } 845 } 846 847 QDF_ASSERT(pdev_ev_handler->handler_cnt < 848 MAX_SCAN_EVENT_HANDLERS_PER_PDEV); 849 850 if (pdev_ev_handler->handler_cnt >= MAX_SCAN_EVENT_HANDLERS_PER_PDEV) { 851 qdf_spin_unlock_bh(&scan->lock); 852 scm_warn("No more registrations possible"); 853 return QDF_STATUS_E_NOMEM; 854 } 855 856 scm_add_scan_event_handler(pdev_ev_handler, event_cb, arg); 857 qdf_spin_unlock_bh(&scan->lock); 858 859 scm_info("event_cb: 0x%pK, arg: 0x%pK", event_cb, arg); 860 861 return QDF_STATUS_SUCCESS; 862 } 863 864 static QDF_STATUS 865 wlan_scan_global_init(struct wlan_scan_obj *scan_obj) 866 { 867 scan_obj->enable_scan = true; 868 scan_obj->scan_def.active_dwell = SCAN_ACTIVE_DWELL_TIME; 869 scan_obj->scan_def.passive_dwell = SCAN_PASSIVE_DWELL_TIME; 870 scan_obj->scan_def.max_rest_time = SCAN_MAX_REST_TIME; 871 scan_obj->scan_def.min_rest_time = SCAN_MIN_REST_TIME; 872 scan_obj->scan_def.conc_active_dwell = SCAN_CONC_ACTIVE_DWELL_TIME; 873 scan_obj->scan_def.conc_passive_dwell = SCAN_CONC_PASSIVE_DWELL_TIME; 874 scan_obj->scan_def.conc_max_rest_time = SCAN_CONC_MAX_REST_TIME; 875 scan_obj->scan_def.conc_min_rest_time = SCAN_CONC_MIN_REST_TIME; 876 scan_obj->scan_def.conc_idle_time = SCAN_CONC_IDLE_TIME; 877 scan_obj->scan_def.repeat_probe_time = SCAN_REPEAT_PROBE_TIME; 878 scan_obj->scan_def.probe_spacing_time = SCAN_PROBE_SPACING_TIME; 879 scan_obj->scan_def.probe_delay = SCAN_PROBE_DELAY; 880 scan_obj->scan_def.burst_duration = SCAN_BURST_DURATION; 881 scan_obj->scan_def.max_scan_time = SCAN_MAX_SCAN_TIME; 882 scan_obj->scan_def.num_probes = SCAN_NUM_PROBES; 883 scan_obj->scan_def.scan_cache_aging_time = SCAN_CACHE_AGING_TIME; 884 scan_obj->scan_def.max_bss_per_pdev = SCAN_MAX_BSS_PDEV; 885 scan_obj->scan_def.scan_priority = SCAN_PRIORITY; 886 scan_obj->scan_def.idle_time = SCAN_NETWORK_IDLE_TIMEOUT; 887 scan_obj->scan_def.adaptive_dwell_time_mode = SCAN_DWELL_MODE_DEFAULT; 888 /* scan contrl flags */ 889 scan_obj->scan_def.scan_f_passive = true; 890 scan_obj->scan_def.scan_f_ofdm_rates = true; 891 scan_obj->scan_def.scan_f_2ghz = true; 892 scan_obj->scan_def.scan_f_5ghz = true; 893 scan_obj->scan_def.scan_f_chan_stat_evnt = SCAN_CHAN_STATS_EVENT_ENAB; 894 /* scan event flags */ 895 scan_obj->scan_def.scan_ev_started = true; 896 scan_obj->scan_def.scan_ev_completed = true; 897 scan_obj->scan_def.scan_ev_bss_chan = true; 898 scan_obj->scan_def.scan_ev_foreign_chan = true; 899 scan_obj->scan_def.scan_ev_foreign_chn_exit = true; 900 scan_obj->scan_def.scan_ev_dequeued = true; 901 scan_obj->scan_def.scan_ev_preempted = true; 902 scan_obj->scan_def.scan_ev_start_failed = true; 903 scan_obj->scan_def.scan_ev_restarted = true; 904 /* init scan id seed */ 905 qdf_atomic_init(&scan_obj->scan_ids); 906 907 return wlan_pno_global_init(&scan_obj->pno_cfg); 908 } 909 910 static QDF_STATUS 911 scm_remove_scan_event_handler(struct pdev_scan_ev_handler *pdev_ev_handler, 912 struct cb_handler *entry) 913 { 914 struct cb_handler *last_entry; 915 uint32_t handler_cnt = pdev_ev_handler->handler_cnt; 916 917 /* Replace event handler being deleted 918 * with the last one in the list. 919 */ 920 last_entry = &(pdev_ev_handler->cb_handlers[handler_cnt - 1]); 921 entry->func = last_entry->func; 922 entry->arg = last_entry->arg; 923 924 /* Clear our last entry */ 925 last_entry->func = NULL; 926 last_entry->arg = NULL; 927 pdev_ev_handler->handler_cnt--; 928 929 return QDF_STATUS_SUCCESS; 930 } 931 932 void 933 ucfg_scan_unregister_event_handler(struct wlan_objmgr_pdev *pdev, 934 scan_event_handler event_cb, void *arg) 935 { 936 uint8_t found = false; 937 uint32_t idx; 938 uint32_t handler_cnt; 939 struct wlan_scan_obj *scan; 940 struct cb_handler *cb_handler; 941 struct pdev_scan_ev_handler *pdev_ev_handler; 942 943 scm_info("pdev: %pK, event_cb: 0x%pK, arg: 0x%pK", pdev, event_cb, arg); 944 if (!pdev) { 945 scm_err("null pdev"); 946 return; 947 } 948 scan = wlan_pdev_get_scan_obj(pdev); 949 pdev_ev_handler = wlan_pdev_get_pdev_scan_ev_handlers(pdev); 950 cb_handler = &(pdev_ev_handler->cb_handlers[0]); 951 952 qdf_spin_lock_bh(&scan->lock); 953 handler_cnt = pdev_ev_handler->handler_cnt; 954 if (!handler_cnt) { 955 qdf_spin_unlock_bh(&scan->lock); 956 scm_info("No event handlers registered"); 957 return; 958 } 959 960 for (idx = 0; idx < MAX_SCAN_EVENT_HANDLERS_PER_PDEV; 961 idx++, cb_handler++) { 962 if ((cb_handler->func == event_cb) && 963 (cb_handler->arg == arg)) { 964 /* Event handler found, remove it 965 * from event handler list. 966 */ 967 found = true; 968 scm_remove_scan_event_handler(pdev_ev_handler, 969 cb_handler); 970 handler_cnt--; 971 break; 972 } 973 } 974 qdf_spin_unlock_bh(&scan->lock); 975 976 scm_info("event handler %s, remaining handlers: %d", 977 (found ? "removed" : "not found"), handler_cnt); 978 } 979 980 #ifdef WLAN_POLICY_MGR_ENABLE 981 /** 982 * ucfg_scan_req_update_params() - update scan req params depending 983 * on active modes 984 * @vdev: vdev object pointer 985 * @req: scan request 986 * 987 * Return: void 988 */ 989 static void ucfg_scan_req_update_params(struct wlan_objmgr_vdev *vdev, 990 struct scan_start_request *req) 991 { 992 bool ap_or_go_present; 993 struct wlan_objmgr_psoc *psoc; 994 995 psoc = wlan_vdev_get_psoc(vdev); 996 997 if (!psoc) 998 return; 999 1000 ap_or_go_present = policy_mgr_mode_specific_connection_count( 1001 psoc, QDF_SAP_MODE, NULL) || 1002 policy_mgr_mode_specific_connection_count( 1003 psoc, QDF_P2P_GO_MODE, NULL); 1004 1005 /* 1006 * If AP is active set min rest time same as max rest time, so that 1007 * firmware spends more time on home channel which will increase the 1008 * probability of sending beacon at TBTT 1009 */ 1010 if (ap_or_go_present) 1011 req->scan_req.min_rest_time = req->scan_req.max_rest_time; 1012 } 1013 #else 1014 static inline void ucfg_scan_req_update_params(struct wlan_objmgr_vdev *vdev, 1015 struct scan_start_request *req){} 1016 #endif 1017 1018 1019 QDF_STATUS 1020 ucfg_scan_init_default_params(struct wlan_objmgr_vdev *vdev, 1021 struct scan_start_request *req) 1022 { 1023 struct scan_default_params *def; 1024 1025 if (!vdev | !req) { 1026 scm_err("vdev: 0x%pK, req: 0x%pK", vdev, req); 1027 return QDF_STATUS_E_INVAL; 1028 } 1029 def = wlan_vdev_get_def_scan_params(vdev); 1030 1031 /* Zero out everything and explicitly set fields as required */ 1032 qdf_mem_zero(req, sizeof(*req)); 1033 1034 req->vdev = vdev; 1035 req->scan_req.vdev_id = wlan_vdev_get_id(vdev); 1036 req->scan_req.scan_priority = def->scan_priority; 1037 req->scan_req.dwell_time_active = def->active_dwell; 1038 req->scan_req.dwell_time_passive = def->passive_dwell; 1039 req->scan_req.min_rest_time = def->min_rest_time; 1040 req->scan_req.max_rest_time = def->max_rest_time; 1041 req->scan_req.repeat_probe_time = def->repeat_probe_time; 1042 req->scan_req.probe_spacing_time = def->probe_spacing_time; 1043 req->scan_req.idle_time = def->idle_time; 1044 req->scan_req.max_scan_time = def->max_scan_time; 1045 req->scan_req.probe_delay = def->probe_delay; 1046 req->scan_req.burst_duration = def->burst_duration; 1047 req->scan_req.n_probes = def->num_probes; 1048 req->scan_req.adaptive_dwell_time_mode = 1049 def->adaptive_dwell_time_mode; 1050 req->scan_req.scan_flags = def->scan_flags; 1051 req->scan_req.scan_events = def->scan_events; 1052 req->scan_req.scan_random.randomize = def->enable_mac_spoofing; 1053 ucfg_scan_req_update_params(vdev, req); 1054 1055 return QDF_STATUS_SUCCESS; 1056 } 1057 1058 QDF_STATUS 1059 ucfg_scan_init_ssid_params(struct scan_start_request *req, 1060 uint32_t num_ssid, struct wlan_ssid *ssid_list) 1061 { 1062 uint32_t max_ssid = sizeof(req->scan_req.ssid) / 1063 sizeof(req->scan_req.ssid[0]); 1064 1065 if (!req) { 1066 scm_err("null request"); 1067 return QDF_STATUS_E_NULL_VALUE; 1068 } 1069 if (!num_ssid) { 1070 /* empty channel list provided */ 1071 req->scan_req.num_ssids = 0; 1072 qdf_mem_zero(&req->scan_req.ssid[0], 1073 sizeof(req->scan_req.ssid)); 1074 return QDF_STATUS_SUCCESS; 1075 } 1076 if (!ssid_list) { 1077 scm_err("null ssid_list while num_ssid: %d", num_ssid); 1078 return QDF_STATUS_E_NULL_VALUE; 1079 } 1080 if (num_ssid > max_ssid) { 1081 /* got a big list. alert and continue */ 1082 scm_warn("overflow: received %d, max supported : %d", 1083 num_ssid, max_ssid); 1084 return QDF_STATUS_E_E2BIG; 1085 } 1086 1087 if (max_ssid > num_ssid) 1088 max_ssid = num_ssid; 1089 1090 req->scan_req.num_ssids = max_ssid; 1091 qdf_mem_copy(&req->scan_req.ssid[0], ssid_list, 1092 (req->scan_req.num_ssids * sizeof(req->scan_req.ssid[0]))); 1093 1094 return QDF_STATUS_SUCCESS; 1095 } 1096 1097 QDF_STATUS 1098 ucfg_scan_init_bssid_params(struct scan_start_request *req, 1099 uint32_t num_bssid, struct qdf_mac_addr *bssid_list) 1100 { 1101 uint32_t max_bssid = sizeof(req->scan_req.bssid_list) / 1102 sizeof(req->scan_req.bssid_list[0]); 1103 1104 if (!req) { 1105 scm_err("null request"); 1106 return QDF_STATUS_E_NULL_VALUE; 1107 } 1108 if (!num_bssid) { 1109 /* empty channel list provided */ 1110 req->scan_req.num_bssid = 0; 1111 qdf_mem_zero(&req->scan_req.bssid_list[0], 1112 sizeof(req->scan_req.bssid_list)); 1113 return QDF_STATUS_SUCCESS; 1114 } 1115 if (!bssid_list) { 1116 scm_err("null bssid_list while num_bssid: %d", num_bssid); 1117 return QDF_STATUS_E_NULL_VALUE; 1118 } 1119 if (num_bssid > max_bssid) { 1120 /* got a big list. alert and continue */ 1121 scm_warn("overflow: received %d, max supported : %d", 1122 num_bssid, max_bssid); 1123 return QDF_STATUS_E_E2BIG; 1124 } 1125 1126 if (max_bssid > num_bssid) 1127 max_bssid = num_bssid; 1128 1129 req->scan_req.num_bssid = max_bssid; 1130 qdf_mem_copy(&req->scan_req.bssid_list[0], bssid_list, 1131 req->scan_req.num_bssid * sizeof(req->scan_req.bssid_list[0])); 1132 1133 return QDF_STATUS_SUCCESS; 1134 } 1135 1136 QDF_STATUS 1137 ucfg_scan_init_chanlist_params(struct scan_start_request *req, 1138 uint32_t num_chans, uint32_t *chan_list, uint32_t *phymode) 1139 { 1140 uint32_t idx; 1141 uint32_t max_chans = sizeof(req->scan_req.chan_list.chan) / 1142 sizeof(req->scan_req.chan_list.chan[0]); 1143 if (!req) { 1144 scm_err("null request"); 1145 return QDF_STATUS_E_NULL_VALUE; 1146 } 1147 if (!num_chans) { 1148 /* empty channel list provided */ 1149 qdf_mem_zero(&req->scan_req.chan_list, 1150 sizeof(req->scan_req.chan_list)); 1151 req->scan_req.chan_list.num_chan = 0; 1152 return QDF_STATUS_SUCCESS; 1153 } 1154 if (!chan_list) { 1155 scm_err("null chan_list while num_chans: %d", num_chans); 1156 return QDF_STATUS_E_NULL_VALUE; 1157 } 1158 1159 if (num_chans > max_chans) { 1160 /* got a big list. alert and continue */ 1161 scm_warn("overflow: received %d, max supported : %d", 1162 num_chans, max_chans); 1163 return QDF_STATUS_E_E2BIG; 1164 } 1165 1166 if (max_chans > num_chans) 1167 max_chans = num_chans; 1168 1169 req->scan_req.chan_list.num_chan = max_chans; 1170 for (idx = 0; idx < max_chans; idx++) { 1171 req->scan_req.chan_list.chan[idx].freq = 1172 (chan_list[idx] > WLAN_24_GHZ_BASE_FREQ) ? 1173 chan_list[idx] : wlan_chan_to_freq(chan_list[idx]); 1174 req->scan_req.chan_list.chan[idx].phymode = 1175 (phymode ? phymode[idx] : 0); 1176 } 1177 1178 /* Enable wide band scan by default if phymode list is provided. 1179 * This flag will be cleared in @ucfg_scan_start() if underlying 1180 * phy doesn't support wide band scan. 1181 */ 1182 if (phymode) 1183 req->scan_req.scan_f_wide_band = true; 1184 1185 return QDF_STATUS_SUCCESS; 1186 } 1187 1188 static inline enum scm_scan_status 1189 get_scan_status_from_serialization_status( 1190 enum wlan_serialization_cmd_status status) 1191 { 1192 enum scm_scan_status scan_status; 1193 1194 switch (status) { 1195 case WLAN_SER_CMD_IN_PENDING_LIST: 1196 scan_status = SCAN_IS_PENDING; 1197 break; 1198 case WLAN_SER_CMD_IN_ACTIVE_LIST: 1199 scan_status = SCAN_IS_ACTIVE; 1200 break; 1201 case WLAN_SER_CMDS_IN_ALL_LISTS: 1202 scan_status = SCAN_IS_ACTIVE_AND_PENDING; 1203 break; 1204 case WLAN_SER_CMD_NOT_FOUND: 1205 scan_status = SCAN_NOT_IN_PROGRESS; 1206 break; 1207 default: 1208 scm_warn("invalid serialization status %d", status); 1209 QDF_ASSERT(0); 1210 scan_status = SCAN_NOT_IN_PROGRESS; 1211 break; 1212 } 1213 1214 return scan_status; 1215 } 1216 1217 enum scm_scan_status 1218 ucfg_scan_get_vdev_status(struct wlan_objmgr_vdev *vdev) 1219 { 1220 enum wlan_serialization_cmd_status status; 1221 1222 if (!vdev) { 1223 scm_err("null vdev"); 1224 return QDF_STATUS_E_NULL_VALUE; 1225 } 1226 status = wlan_serialization_vdev_scan_status(vdev); 1227 1228 return get_scan_status_from_serialization_status(status); 1229 } 1230 1231 enum scm_scan_status 1232 ucfg_scan_get_pdev_status(struct wlan_objmgr_pdev *pdev) 1233 { 1234 enum wlan_serialization_cmd_status status; 1235 1236 if (!pdev) { 1237 scm_err("null pdev"); 1238 return SCAN_NOT_IN_PROGRESS; 1239 } 1240 status = wlan_serialization_pdev_scan_status(pdev); 1241 1242 return get_scan_status_from_serialization_status(status); 1243 } 1244 1245 static void 1246 ucfg_scan_register_unregister_bcn_cb(struct wlan_objmgr_psoc *psoc, 1247 bool enable) 1248 { 1249 QDF_STATUS status; 1250 struct mgmt_txrx_mgmt_frame_cb_info cb_info[2]; 1251 1252 cb_info[0].frm_type = MGMT_PROBE_RESP; 1253 cb_info[0].mgmt_rx_cb = tgt_scan_bcn_probe_rx_callback; 1254 cb_info[1].frm_type = MGMT_BEACON; 1255 cb_info[1].mgmt_rx_cb = tgt_scan_bcn_probe_rx_callback; 1256 1257 if (enable) 1258 status = wlan_mgmt_txrx_register_rx_cb(psoc, 1259 WLAN_UMAC_COMP_SCAN, cb_info, 2); 1260 else 1261 status = wlan_mgmt_txrx_deregister_rx_cb(psoc, 1262 WLAN_UMAC_COMP_SCAN, cb_info, 2); 1263 if (status != QDF_STATUS_SUCCESS) 1264 scm_err("%s the Handle with MGMT TXRX layer has failed", 1265 enable ? "Registering" : "Deregistering"); 1266 } 1267 1268 static void ucfg_scan_assign_rssi_category(struct scan_default_params *params, 1269 int32_t best_ap_rssi, uint32_t cat_offset) 1270 { 1271 int i; 1272 1273 scm_info("best AP RSSI:%d, cat offset: %d", best_ap_rssi, cat_offset); 1274 if (cat_offset) 1275 for (i = 0; i < SCM_NUM_RSSI_CAT; i++) { 1276 params->rssi_cat[SCM_NUM_RSSI_CAT - i - 1] = 1277 (best_ap_rssi - 1278 params->select_5ghz_margin - 1279 (int)(i * cat_offset)); 1280 params->bss_prefer_val[i] = i; 1281 } 1282 } 1283 1284 QDF_STATUS ucfg_scan_update_user_config(struct wlan_objmgr_psoc *psoc, 1285 struct scan_user_cfg *scan_cfg) 1286 { 1287 struct wlan_scan_obj *scan_obj; 1288 struct scan_default_params *scan_def; 1289 1290 if (!psoc) { 1291 scm_err("null psoc"); 1292 return QDF_STATUS_E_FAILURE; 1293 } 1294 scan_obj = wlan_psoc_get_scan_obj(psoc); 1295 if (scan_obj == NULL) { 1296 scm_err("Failed to get scan object"); 1297 return QDF_STATUS_E_FAILURE; 1298 } 1299 1300 scan_def = &scan_obj->scan_def; 1301 scan_def->active_dwell = scan_cfg->active_dwell; 1302 scan_def->passive_dwell = scan_cfg->passive_dwell; 1303 scan_def->conc_active_dwell = scan_cfg->conc_active_dwell; 1304 scan_def->conc_passive_dwell = scan_cfg->conc_passive_dwell; 1305 scan_def->conc_max_rest_time = scan_cfg->conc_max_rest_time; 1306 scan_def->conc_min_rest_time = scan_cfg->conc_min_rest_time; 1307 scan_def->conc_idle_time = scan_cfg->conc_idle_time; 1308 scan_def->scan_cache_aging_time = scan_cfg->scan_cache_aging_time; 1309 scan_def->prefer_5ghz = scan_cfg->prefer_5ghz; 1310 scan_def->select_5ghz_margin = scan_cfg->select_5ghz_margin; 1311 scan_def->adaptive_dwell_time_mode = scan_cfg->scan_dwell_time_mode; 1312 scan_def->scan_f_chan_stat_evnt = scan_cfg->is_snr_monitoring_enabled; 1313 scan_obj->ie_whitelist = scan_cfg->ie_whitelist; 1314 scan_def->usr_cfg_probe_rpt_time = scan_cfg->usr_cfg_probe_rpt_time; 1315 scan_def->usr_cfg_num_probes = scan_cfg->usr_cfg_num_probes; 1316 scan_def->is_bssid_hint_priority = scan_cfg->is_bssid_hint_priority; 1317 scan_def->enable_mac_spoofing = scan_cfg->enable_mac_spoofing; 1318 1319 ucfg_scan_assign_rssi_category(scan_def, 1320 scan_cfg->scan_bucket_threshold, 1321 scan_cfg->rssi_cat_gap); 1322 1323 ucfg_scan_update_pno_config(&scan_obj->pno_cfg, 1324 &scan_cfg->pno_cfg); 1325 1326 qdf_mem_copy(&scan_def->score_config, &scan_cfg->score_config, 1327 sizeof(struct scoring_config)); 1328 scm_validate_scoring_config(&scan_def->score_config); 1329 1330 return QDF_STATUS_SUCCESS; 1331 } 1332 1333 QDF_STATUS ucfg_scan_update_roam_params(struct wlan_objmgr_psoc *psoc, 1334 struct roam_filter_params *roam_params) 1335 { 1336 struct scan_default_params *scan_def; 1337 1338 if (!psoc) { 1339 scm_err("null psoc"); 1340 return QDF_STATUS_E_FAILURE; 1341 } 1342 scan_def = wlan_scan_psoc_get_def_params(psoc); 1343 if (!scan_def) { 1344 scm_err("Failed to get scan object"); 1345 return QDF_STATUS_E_FAILURE; 1346 } 1347 1348 qdf_mem_copy(&scan_def->roam_params, roam_params, 1349 sizeof(struct roam_filter_params)); 1350 1351 return QDF_STATUS_SUCCESS; 1352 } 1353 1354 static QDF_STATUS 1355 ucfg_scan_cancel_pdev_scan(struct wlan_objmgr_pdev *pdev) 1356 { 1357 struct scan_cancel_request *req; 1358 QDF_STATUS status; 1359 struct wlan_objmgr_vdev *vdev; 1360 1361 req = qdf_mem_malloc(sizeof(*req)); 1362 if (!req) { 1363 scm_err("Failed to allocate memory"); 1364 return QDF_STATUS_E_NOMEM; 1365 } 1366 1367 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 0, WLAN_OSIF_ID); 1368 if (!vdev) { 1369 scm_err("Failed to get vdev"); 1370 return QDF_STATUS_E_INVAL; 1371 } 1372 req->vdev = vdev; 1373 req->cancel_req.scan_id = INVAL_SCAN_ID; 1374 req->cancel_req.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1375 req->cancel_req.vdev_id = INVAL_VDEV_ID; 1376 req->cancel_req.req_type = WLAN_SCAN_CANCEL_PDEV_ALL; 1377 status = ucfg_scan_cancel_sync(req); 1378 if (QDF_IS_STATUS_ERROR(status)) 1379 scm_err("Cancel scan request failed"); 1380 wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); 1381 1382 return status; 1383 } 1384 1385 #ifdef WLAN_PMO_ENABLE 1386 1387 static QDF_STATUS 1388 ucfg_scan_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg) 1389 { 1390 struct wlan_objmgr_pdev *pdev = NULL; 1391 QDF_STATUS status = QDF_STATUS_SUCCESS; 1392 int i; 1393 1394 /* Check all pdev */ 1395 for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) { 1396 pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_SCAN_ID); 1397 if (!pdev) 1398 continue; 1399 if (ucfg_scan_get_pdev_status(pdev) != 1400 SCAN_NOT_IN_PROGRESS) 1401 status = ucfg_scan_cancel_pdev_scan(pdev); 1402 wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID); 1403 if (QDF_IS_STATUS_ERROR(status)) { 1404 scm_err("failed to cancel scan for pdev_id %d", i); 1405 return status; 1406 } 1407 } 1408 1409 return QDF_STATUS_SUCCESS; 1410 } 1411 1412 static QDF_STATUS 1413 ucfg_scan_resume_handler(struct wlan_objmgr_psoc *psoc, void *arg) 1414 { 1415 return QDF_STATUS_SUCCESS; 1416 } 1417 1418 static inline void 1419 ucfg_scan_register_pmo_handler(void) 1420 { 1421 pmo_register_suspend_handler(WLAN_UMAC_COMP_SCAN, 1422 ucfg_scan_suspend_handler, NULL); 1423 pmo_register_resume_handler(WLAN_UMAC_COMP_SCAN, 1424 ucfg_scan_resume_handler, NULL); 1425 } 1426 1427 static inline void 1428 ucfg_scan_unregister_pmo_handler(void) 1429 { 1430 pmo_unregister_suspend_handler(WLAN_UMAC_COMP_SCAN, 1431 ucfg_scan_suspend_handler); 1432 pmo_unregister_resume_handler(WLAN_UMAC_COMP_SCAN, 1433 ucfg_scan_resume_handler); 1434 } 1435 1436 #else 1437 static inline void 1438 ucfg_scan_register_pmo_handler(void) 1439 { 1440 } 1441 1442 static inline void 1443 ucfg_scan_unregister_pmo_handler(void) 1444 { 1445 } 1446 #endif 1447 1448 QDF_STATUS 1449 ucfg_scan_psoc_open(struct wlan_objmgr_psoc *psoc) 1450 { 1451 struct wlan_scan_obj *scan_obj; 1452 1453 scm_info("psoc open: 0x%pK", psoc); 1454 if (!psoc) { 1455 scm_err("null psoc"); 1456 return QDF_STATUS_E_FAILURE; 1457 } 1458 scan_obj = wlan_psoc_get_scan_obj(psoc); 1459 if (scan_obj == NULL) { 1460 scm_err("Failed to get scan object"); 1461 return QDF_STATUS_E_FAILURE; 1462 } 1463 /* Initialize the scan Globals */ 1464 wlan_scan_global_init(scan_obj); 1465 qdf_spinlock_create(&scan_obj->lock); 1466 ucfg_scan_register_pmo_handler(); 1467 1468 return QDF_STATUS_SUCCESS; 1469 } 1470 1471 QDF_STATUS 1472 ucfg_scan_psoc_close(struct wlan_objmgr_psoc *psoc) 1473 { 1474 struct wlan_scan_obj *scan_obj; 1475 1476 scm_info("psoc close: 0x%pK", psoc); 1477 if (!psoc) { 1478 scm_err("null psoc"); 1479 return QDF_STATUS_E_FAILURE; 1480 } 1481 scan_obj = wlan_psoc_get_scan_obj(psoc); 1482 if (scan_obj == NULL) { 1483 scm_err("Failed to get scan object"); 1484 return QDF_STATUS_E_FAILURE; 1485 } 1486 ucfg_scan_unregister_pmo_handler(); 1487 qdf_spinlock_destroy(&scan_obj->lock); 1488 wlan_pno_global_deinit(&scan_obj->pno_cfg); 1489 1490 return QDF_STATUS_SUCCESS; 1491 } 1492 1493 static bool scm_serialization_scan_rules_cb( 1494 union wlan_serialization_rules_info *comp_info, 1495 uint8_t comp_id) 1496 { 1497 switch (comp_id) { 1498 case WLAN_UMAC_COMP_TDLS: 1499 if (comp_info->scan_info.is_tdls_in_progress) { 1500 scm_info("Cancel scan. Tdls in progress"); 1501 return false; 1502 } 1503 break; 1504 case WLAN_UMAC_COMP_DFS: 1505 if (comp_info->scan_info.is_cac_in_progress) { 1506 scm_info("Cancel scan. CAC in progress"); 1507 return false; 1508 } 1509 break; 1510 default: 1511 scm_info("not handled comp_id %d", comp_id); 1512 break; 1513 } 1514 1515 return true; 1516 } 1517 1518 QDF_STATUS 1519 ucfg_scan_psoc_enable(struct wlan_objmgr_psoc *psoc) 1520 { 1521 QDF_STATUS status; 1522 1523 scm_info("psoc enable: 0x%pK", psoc); 1524 if (!psoc) { 1525 scm_err("null psoc"); 1526 return QDF_STATUS_E_FAILURE; 1527 } 1528 /* Subscribe for scan events from lmac layesr */ 1529 status = tgt_scan_register_ev_handler(psoc); 1530 QDF_ASSERT(status == QDF_STATUS_SUCCESS); 1531 scm_db_init(psoc); 1532 ucfg_scan_register_unregister_bcn_cb(psoc, true); 1533 status = wlan_serialization_register_apply_rules_cb(psoc, 1534 WLAN_SER_CMD_SCAN, 1535 scm_serialization_scan_rules_cb); 1536 QDF_ASSERT(status == QDF_STATUS_SUCCESS); 1537 return status; 1538 } 1539 1540 QDF_STATUS 1541 ucfg_scan_psoc_disable(struct wlan_objmgr_psoc *psoc) 1542 { 1543 QDF_STATUS status; 1544 1545 scm_info("psoc disable: 0x%pK", psoc); 1546 if (!psoc) { 1547 scm_err("null psoc"); 1548 return QDF_STATUS_E_FAILURE; 1549 } 1550 /* Unsubscribe for scan events from lmac layesr */ 1551 status = tgt_scan_unregister_ev_handler(psoc); 1552 QDF_ASSERT(status == QDF_STATUS_SUCCESS); 1553 ucfg_scan_register_unregister_bcn_cb(psoc, false); 1554 scm_db_deinit(psoc); 1555 1556 return status; 1557 } 1558 1559 uint32_t 1560 ucfg_scan_get_max_active_scans(struct wlan_objmgr_psoc *psoc) 1561 { 1562 struct scan_default_params *scan_params = NULL; 1563 1564 if (!psoc) { 1565 scm_err("null psoc"); 1566 return 0; 1567 } 1568 scan_params = wlan_scan_psoc_get_def_params(psoc); 1569 1570 return scan_params->max_active_scans_allowed; 1571 } 1572 1573 bool ucfg_copy_ie_whitelist_attrs(struct wlan_objmgr_psoc *psoc, 1574 struct probe_req_whitelist_attr *ie_whitelist) 1575 { 1576 struct wlan_scan_obj *scan_obj = NULL; 1577 1578 scan_obj = wlan_psoc_get_scan_obj(psoc); 1579 if (!scan_obj) 1580 return false; 1581 1582 qdf_mem_copy(ie_whitelist, &scan_obj->ie_whitelist, 1583 sizeof(*ie_whitelist)); 1584 1585 return true; 1586 } 1587 1588 bool ucfg_ie_whitelist_enabled(struct wlan_objmgr_psoc *psoc, 1589 struct wlan_objmgr_vdev *vdev) 1590 { 1591 struct wlan_scan_obj *scan_obj = NULL; 1592 1593 scan_obj = wlan_psoc_get_scan_obj(psoc); 1594 if (!scan_obj) 1595 return false; 1596 1597 if ((wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) || 1598 wlan_vdev_is_connected(vdev)) 1599 return false; 1600 1601 if (!scan_obj->ie_whitelist.white_list) 1602 return false; 1603 1604 return true; 1605 } 1606