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 "../../core/src/wlan_scan_main.h" 30 #include "../../core/src/wlan_scan_manager.h" 31 #include "../../core/src/wlan_scan_cache_db.h" 32 #ifdef WLAN_PMO_ENABLE 33 #include <wlan_pmo_obj_mgmt_api.h> 34 #endif 35 36 QDF_STATUS ucfg_scan_register_bcn_cb(struct wlan_objmgr_psoc *psoc, 37 update_beacon_cb cb, enum scan_cb_type type) 38 { 39 return scm_scan_register_bcn_cb(psoc, cb, type); 40 } 41 42 qdf_list_t *ucfg_scan_get_result(struct wlan_objmgr_pdev *pdev, 43 struct scan_filter *filter) 44 { 45 return scm_get_scan_result(pdev, filter); 46 } 47 48 QDF_STATUS ucfg_scan_db_iterate(struct wlan_objmgr_pdev *pdev, 49 scan_iterator_func func, void *arg) 50 { 51 return scm_iterate_scan_db(pdev, func, arg); 52 } 53 54 QDF_STATUS ucfg_scan_purge_results(qdf_list_t *scan_list) 55 { 56 return scm_purge_scan_results(scan_list); 57 } 58 59 QDF_STATUS ucfg_scan_flush_results(struct wlan_objmgr_pdev *pdev, 60 struct scan_filter *filter) 61 { 62 return scm_flush_results(pdev, filter); 63 } 64 65 void ucfg_scan_filter_valid_channel(struct wlan_objmgr_pdev *pdev, 66 uint8_t *chan_list, uint32_t num_chan) 67 { 68 scm_filter_valid_channel(pdev, chan_list, num_chan); 69 } 70 71 QDF_STATUS ucfg_scan_init(void) 72 { 73 QDF_STATUS status; 74 75 status = wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_SCAN, 76 wlan_scan_psoc_created_notification, NULL); 77 if (QDF_IS_STATUS_ERROR(status)) { 78 scm_err("Failed to register psoc create handler"); 79 goto fail_create_psoc; 80 } 81 82 status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN, 83 wlan_scan_psoc_destroyed_notification, NULL); 84 if (QDF_IS_STATUS_ERROR(status)) { 85 scm_err("Failed to create psoc delete handler"); 86 goto fail_psoc_destroy; 87 } 88 scm_info("scan psoc create and delete handler registered with objmgr"); 89 90 status = wlan_objmgr_register_vdev_create_handler(WLAN_UMAC_COMP_SCAN, 91 wlan_scan_vdev_created_notification, NULL); 92 if (QDF_IS_STATUS_ERROR(status)) { 93 scm_err("Failed to register vdev create handler"); 94 goto fail_pdev_create; 95 } 96 97 status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_SCAN, 98 wlan_scan_vdev_destroyed_notification, NULL); 99 if (QDF_IS_STATUS_SUCCESS(status)) { 100 scm_info("scan vdev create and delete handler registered with objmgr"); 101 return QDF_STATUS_SUCCESS; 102 } 103 104 scm_err("Failed to destroy vdev delete handler"); 105 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN, 106 wlan_scan_vdev_created_notification, NULL); 107 fail_pdev_create: 108 wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN, 109 wlan_scan_psoc_destroyed_notification, NULL); 110 fail_psoc_destroy: 111 wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SCAN, 112 wlan_scan_psoc_created_notification, NULL); 113 fail_create_psoc: 114 return status; 115 } 116 117 QDF_STATUS ucfg_scan_deinit(void) 118 { 119 QDF_STATUS status; 120 121 status = wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SCAN, 122 wlan_scan_psoc_created_notification, NULL); 123 if (status != QDF_STATUS_SUCCESS) 124 scm_err("Failed to unregister psoc create handler"); 125 126 status = wlan_objmgr_unregister_psoc_destroy_handler( 127 WLAN_UMAC_COMP_SCAN, 128 wlan_scan_psoc_destroyed_notification, NULL); 129 if (status != QDF_STATUS_SUCCESS) 130 scm_err("Failed to unregister psoc delete handler"); 131 132 status = wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN, 133 wlan_scan_vdev_created_notification, NULL); 134 if (status != QDF_STATUS_SUCCESS) 135 scm_err("Failed to unregister vdev create handler"); 136 137 status = wlan_objmgr_unregister_vdev_destroy_handler( 138 WLAN_UMAC_COMP_SCAN, 139 wlan_scan_vdev_destroyed_notification, NULL); 140 if (status != QDF_STATUS_SUCCESS) 141 scm_err("Failed to unregister vdev delete handler"); 142 143 return status; 144 } 145 146 #ifdef FEATURE_WLAN_SCAN_PNO 147 148 QDF_STATUS ucfg_scan_pno_start(struct wlan_objmgr_vdev *vdev, 149 struct pno_scan_req_params *req) 150 { 151 struct scan_vdev_obj *scan_vdev_obj; 152 QDF_STATUS status; 153 154 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 155 if (!scan_vdev_obj) { 156 scm_err("null scan_vdev_obj"); 157 return QDF_STATUS_E_INVAL; 158 } 159 if (scan_vdev_obj->pno_in_progress) { 160 scm_err("pno already in progress"); 161 return QDF_STATUS_E_ALREADY; 162 } 163 164 status = tgt_scan_pno_start(vdev, req); 165 if (QDF_IS_STATUS_ERROR(status)) 166 scm_err("pno start failed"); 167 else 168 scan_vdev_obj->pno_in_progress = true; 169 170 return status; 171 } 172 173 QDF_STATUS ucfg_scan_pno_stop(struct wlan_objmgr_vdev *vdev) 174 { 175 struct scan_vdev_obj *scan_vdev_obj; 176 QDF_STATUS status; 177 178 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 179 if (!scan_vdev_obj) { 180 scm_err("null scan_vdev_obj"); 181 return QDF_STATUS_E_INVAL; 182 } 183 if (!scan_vdev_obj->pno_in_progress) { 184 scm_err("pno already stopped"); 185 return QDF_STATUS_E_ALREADY; 186 } 187 188 status = tgt_scan_pno_stop(vdev, wlan_vdev_get_id(vdev)); 189 if (QDF_IS_STATUS_ERROR(status)) 190 scm_err("pno start failed"); 191 else 192 scan_vdev_obj->pno_in_progress = false; 193 194 return status; 195 } 196 197 bool ucfg_scan_get_pno_in_progress(struct wlan_objmgr_vdev *vdev) 198 { 199 struct scan_vdev_obj *scan_vdev_obj; 200 201 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 202 if (!scan_vdev_obj) { 203 scm_err("null scan_vdev_obj"); 204 return false; 205 } 206 207 return scan_vdev_obj->pno_in_progress; 208 } 209 210 bool ucfg_scan_get_pno_match(struct wlan_objmgr_vdev *vdev) 211 { 212 struct scan_vdev_obj *scan_vdev_obj; 213 214 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 215 if (!scan_vdev_obj) { 216 scm_err("null scan_vdev_obj"); 217 return false; 218 } 219 220 return scan_vdev_obj->pno_match_evt_received; 221 } 222 223 static QDF_STATUS 224 wlan_pno_global_init(struct pno_def_config *pno_def) 225 { 226 qdf_wake_lock_create(&pno_def->pno_wake_lock, "wlan_pno_wl"); 227 pno_def->channel_prediction = SCAN_PNO_CHANNEL_PREDICTION; 228 pno_def->top_k_num_of_channels = SCAN_TOP_K_NUM_OF_CHANNELS; 229 pno_def->stationary_thresh = SCAN_STATIONARY_THRESHOLD; 230 pno_def->channel_prediction_full_scan = 231 SCAN_CHANNEL_PREDICTION_FULL_SCAN_MS; 232 pno_def->adaptive_dwell_mode = SCAN_ADAPTIVE_PNOSCAN_DWELL_MODE; 233 234 return QDF_STATUS_SUCCESS; 235 } 236 237 static QDF_STATUS 238 wlan_pno_global_deinit(struct pno_def_config *pno_def) 239 { 240 qdf_wake_lock_destroy(&pno_def->pno_wake_lock); 241 242 return QDF_STATUS_SUCCESS; 243 } 244 245 QDF_STATUS 246 ucfg_scan_get_pno_def_params(struct wlan_objmgr_vdev *vdev, 247 struct pno_scan_req_params *req) 248 { 249 struct scan_default_params *scan_def; 250 struct wlan_scan_obj *scan = wlan_vdev_get_scan_obj(vdev); 251 struct pno_def_config *pno_def; 252 253 if (!vdev | !req | !scan) { 254 scm_err("vdev: 0x%p, req: 0x%p scan_obj: 0x%p", 255 vdev, req, scan); 256 return QDF_STATUS_E_INVAL; 257 } 258 259 scan_def = wlan_vdev_get_def_scan_params(vdev); 260 pno_def = &scan->pno_cfg; 261 262 req->active_dwell_time = scan_def->active_dwell; 263 req->passive_dwell_time = scan_def->passive_dwell; 264 265 req->adaptive_dwell_mode = pno_def->adaptive_dwell_mode; 266 267 req->pno_channel_prediction = pno_def->adaptive_dwell_mode; 268 req->top_k_num_of_channels = pno_def->top_k_num_of_channels; 269 req->stationary_thresh = pno_def->stationary_thresh; 270 req->channel_prediction_full_scan = 271 pno_def->channel_prediction_full_scan; 272 273 return QDF_STATUS_SUCCESS; 274 } 275 276 static QDF_STATUS ucfg_scan_update_pno_config(struct pno_def_config *pno, 277 struct pno_user_cfg *pno_cfg) 278 { 279 pno->channel_prediction = pno_cfg->channel_prediction; 280 pno->top_k_num_of_channels = pno_cfg->top_k_num_of_channels; 281 pno->stationary_thresh = pno_cfg->stationary_thresh; 282 pno->adaptive_dwell_mode = pno_cfg->adaptive_dwell_mode; 283 pno->channel_prediction_full_scan = 284 pno_cfg->channel_prediction_full_scan; 285 286 return QDF_STATUS_SUCCESS; 287 } 288 289 QDF_STATUS 290 ucfg_scan_register_pno_cb(struct wlan_objmgr_psoc *psoc, 291 scan_event_handler event_cb, void *arg) 292 { 293 struct wlan_scan_obj *scan; 294 295 if (!psoc) { 296 scm_err("null psoc"); 297 return QDF_STATUS_E_INVAL; 298 } 299 scan = wlan_psoc_get_scan_obj(psoc); 300 qdf_spin_lock_bh(&scan->lock); 301 scan->pno_cfg.pno_cb.func = event_cb; 302 scan->pno_cfg.pno_cb.arg = arg; 303 qdf_spin_unlock_bh(&scan->lock); 304 scm_info("event_cb: 0x%p, arg: 0x%p", event_cb, arg); 305 306 return QDF_STATUS_SUCCESS; 307 } 308 309 #else 310 311 static inline QDF_STATUS 312 wlan_pno_global_init(struct pno_def_config *pno_def) 313 { 314 return QDF_STATUS_SUCCESS; 315 } 316 static inline QDF_STATUS 317 wlan_pno_global_deinit(struct pno_def_config *pno_def) 318 { 319 return QDF_STATUS_SUCCESS; 320 } 321 322 static inline QDF_STATUS 323 ucfg_scan_update_pno_config(struct pno_def_config *pno, 324 struct pno_user_cfg *pno_cfg) 325 { 326 return QDF_STATUS_SUCCESS; 327 } 328 329 #endif 330 331 332 QDF_STATUS 333 ucfg_scan_start(struct scan_start_request *req) 334 { 335 struct scheduler_msg msg = {0}; 336 QDF_STATUS status; 337 338 if (!req || !req->vdev) { 339 scm_err("vdev: %p, req: %p", req->vdev, req); 340 if (req) 341 scm_scan_free_scan_request_mem(req); 342 return QDF_STATUS_E_NULL_VALUE; 343 } 344 scm_info("reqid: %d, scanid: %d, vdevid: %d", 345 req->scan_req.scan_req_id, req->scan_req.scan_id, 346 req->scan_req.vdev_id); 347 348 /* Try to get vdev reference. Return if reference could 349 * not be taken. Reference will be released once scan 350 * request handling completes along with free of @req. 351 */ 352 status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID); 353 if (QDF_IS_STATUS_ERROR(status)) { 354 scm_info("unable to get reference"); 355 scm_scan_free_scan_request_mem(req); 356 return status; 357 } 358 359 msg.bodyptr = req; 360 msg.callback = scm_scan_start_req; 361 362 status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg); 363 if (QDF_IS_STATUS_ERROR(status)) { 364 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 365 scm_err("failed to post to QDF_MODULE_ID_OS_IF"); 366 scm_scan_free_scan_request_mem(req); 367 } 368 369 return status; 370 } 371 372 QDF_STATUS 373 ucfg_scan_cancel(struct scan_cancel_request *req) 374 { 375 struct scheduler_msg msg = {0}; 376 QDF_STATUS status; 377 378 if (!req || !req->vdev) { 379 scm_err("vdev: %p, req: %p", req->vdev, req); 380 if (req) 381 qdf_mem_free(req); 382 return QDF_STATUS_E_NULL_VALUE; 383 } 384 scm_info("reqid: %d, scanid: %d, vdevid: %d, type: %d", 385 req->cancel_req.requester, req->cancel_req.scan_id, 386 req->cancel_req.vdev_id, req->cancel_req.req_type); 387 388 /* Get vdev reference unconditionally. 389 * Reference will be released once scan cancel is 390 * posted to FW. 391 */ 392 wlan_objmgr_vdev_get_ref(req->vdev, WLAN_SCAN_ID); 393 394 msg.bodyptr = req; 395 msg.callback = scm_scan_cancel_req; 396 397 status = scheduler_post_msg(QDF_MODULE_ID_OS_IF, &msg); 398 if (QDF_IS_STATUS_ERROR(status)) { 399 scm_err("failed to post to QDF_MODULE_ID_OS_IF"); 400 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 401 qdf_mem_free(req); 402 } 403 404 return status; 405 } 406 407 QDF_STATUS 408 ucfg_scan_cancel_sync(struct scan_cancel_request *req) 409 { 410 QDF_STATUS status; 411 bool cancel_vdev = false, cancel_pdev = false; 412 struct wlan_objmgr_vdev *vdev; 413 struct wlan_objmgr_pdev *pdev; 414 uint32_t max_wait_iterations = SCM_CANCEL_SCAN_WAIT_ITERATION; 415 qdf_event_t cancel_scan_event; 416 417 if (!req || !req->vdev) { 418 scm_err("vdev: %p, req: %p", req->vdev, req); 419 if (req) 420 qdf_mem_free(req); 421 return QDF_STATUS_E_NULL_VALUE; 422 } 423 424 if (req->cancel_req.req_type == 425 WLAN_SCAN_CANCEL_PDEV_ALL) 426 cancel_pdev = true; 427 else if (req->cancel_req.req_type == 428 WLAN_SCAN_CANCEL_VDEV_ALL) 429 cancel_vdev = true; 430 431 vdev = req->vdev; 432 status = ucfg_scan_cancel(req); 433 if (QDF_IS_STATUS_ERROR(status)) { 434 scm_err("failed to post to QDF_MODULE_ID_OS_IF"); 435 return status; 436 } 437 438 /* 439 * If cancel req is to cancel all scan of pdev or vdev 440 * wait untill all scan of pdev or vdev get cancelled 441 */ 442 qdf_event_create(&cancel_scan_event); 443 qdf_event_reset(&cancel_scan_event); 444 445 if (cancel_pdev) { 446 wlan_vdev_obj_lock(vdev); 447 pdev = wlan_vdev_get_pdev(vdev); 448 wlan_vdev_obj_unlock(vdev); 449 while ((ucfg_scan_get_pdev_status(pdev) != 450 SCAN_NOT_IN_PROGRESS) && max_wait_iterations) { 451 scm_debug("wait for all pdev scan to get complete"); 452 qdf_wait_single_event(&cancel_scan_event, 453 qdf_system_msecs_to_ticks( 454 SCM_CANCEL_SCAN_WAIT_TIME)); 455 max_wait_iterations--; 456 } 457 } else if (cancel_vdev) { 458 while ((ucfg_scan_get_vdev_status(vdev) != 459 SCAN_NOT_IN_PROGRESS) && max_wait_iterations) { 460 scm_debug("wait for all vdev scan to get complete"); 461 qdf_wait_single_event(&cancel_scan_event, 462 qdf_system_msecs_to_ticks( 463 SCM_CANCEL_SCAN_WAIT_TIME)); 464 max_wait_iterations--; 465 } 466 } 467 468 qdf_event_destroy(&cancel_scan_event); 469 470 if (!max_wait_iterations) { 471 scm_err("Failed to wait for scans to get complete"); 472 return QDF_STATUS_E_TIMEOUT; 473 } 474 475 return status; 476 } 477 478 wlan_scan_requester 479 ucfg_scan_register_requester(struct wlan_objmgr_psoc *psoc, 480 uint8_t *name, scan_event_handler event_cb, void *arg) 481 { 482 int i, j; 483 struct wlan_scan_obj *scan; 484 struct scan_requester_info *requesters; 485 wlan_scan_requester requester = {0}; 486 487 if (!psoc) { 488 scm_err("null psoc"); 489 return 0; 490 } 491 scan = wlan_psoc_get_scan_obj(psoc); 492 requesters = scan->requesters; 493 qdf_spin_lock_bh(&scan->lock); 494 for (i = 0; i < WLAN_MAX_REQUESTORS; ++i) { 495 if (requesters[i].requester == 0) { 496 requesters[i].requester = 497 WLAN_SCAN_REQUESTER_ID_PREFIX | i; 498 j = 0; 499 while (name[j] && (j < (WLAN_MAX_MODULE_NAME - 1))) { 500 requesters[i].module[j] = name[j]; 501 ++j; 502 } 503 requesters[i].module[j] = 0; 504 requesters[i].ev_handler.func = event_cb; 505 requesters[i].ev_handler.arg = arg; 506 requester = requesters[i].requester; 507 break; 508 } 509 } 510 qdf_spin_unlock_bh(&scan->lock); 511 scm_info("module: %s, event_cb: 0x%p, arg: 0x%p, reqid: %d", 512 name, event_cb, arg, requester); 513 514 return requester; 515 } 516 517 void 518 ucfg_scan_unregister_requester(struct wlan_objmgr_psoc *psoc, 519 wlan_scan_requester requester) 520 { 521 int idx = requester & ~WLAN_SCAN_REQUESTER_ID_PREFIX; 522 struct wlan_scan_obj *scan; 523 struct scan_requester_info *requesters; 524 525 if (!psoc) { 526 scm_err("null psoc"); 527 return; 528 } 529 scan = wlan_psoc_get_scan_obj(psoc); 530 requesters = scan->requesters; 531 scm_info("reqid: %d", requester); 532 533 qdf_spin_lock_bh(&scan->lock); 534 requesters[idx].requester = 0; 535 requesters[idx].module[0] = 0; 536 requesters[idx].ev_handler.func = NULL; 537 requesters[idx].ev_handler.arg = NULL; 538 qdf_spin_unlock_bh(&scan->lock); 539 } 540 541 uint8_t* 542 ucfg_get_scan_requester_name(struct wlan_objmgr_psoc *psoc, 543 wlan_scan_requester requester) 544 { 545 int idx = requester & ~WLAN_SCAN_REQUESTER_ID_PREFIX; 546 struct wlan_scan_obj *scan; 547 struct scan_requester_info *requesters; 548 549 if (!psoc) { 550 scm_err("null psoc"); 551 return "null"; 552 } 553 scan = wlan_psoc_get_scan_obj(psoc); 554 requesters = scan->requesters; 555 556 if ((idx < WLAN_MAX_REQUESTORS) && 557 (requesters[idx].requester == requester)) { 558 return requesters[idx].module; 559 } 560 561 return (uint8_t *)"unknown"; 562 } 563 564 wlan_scan_id 565 ucfg_scan_get_scan_id(struct wlan_objmgr_psoc *psoc) 566 { 567 wlan_scan_id id; 568 struct wlan_scan_obj *scan; 569 570 if (!psoc) { 571 QDF_ASSERT(0); 572 scm_err("null psoc"); 573 return 0; 574 } 575 scan = wlan_psoc_get_scan_obj(psoc); 576 577 id = qdf_atomic_inc_return(&scan->scan_ids); 578 id = id & WLAN_SCAN_ID_MASK; 579 /* Mark this scan request as triggered by host 580 * by setting WLAN_HOST_SCAN_REQ_ID_PREFIX flag. 581 */ 582 id = id | WLAN_HOST_SCAN_REQ_ID_PREFIX; 583 scm_info("scan_id: 0x%x", id); 584 585 return id; 586 } 587 588 static QDF_STATUS 589 scm_add_scan_event_handler(struct pdev_scan_ev_handler *pdev_ev_handler, 590 scan_event_handler event_cb, void *arg) 591 { 592 struct cb_handler *cb_handler; 593 uint32_t handler_cnt = pdev_ev_handler->handler_cnt; 594 595 /* Assign next available slot to this registration request */ 596 cb_handler = &(pdev_ev_handler->cb_handlers[handler_cnt]); 597 cb_handler->func = event_cb; 598 cb_handler->arg = arg; 599 pdev_ev_handler->handler_cnt++; 600 601 return QDF_STATUS_SUCCESS; 602 } 603 604 QDF_STATUS 605 ucfg_scan_register_event_handler(struct wlan_objmgr_pdev *pdev, 606 scan_event_handler event_cb, void *arg) 607 { 608 uint32_t idx; 609 struct wlan_scan_obj *scan; 610 struct pdev_scan_ev_handler *pdev_ev_handler; 611 struct cb_handler *cb_handler; 612 613 /* scan event handler call back can't be NULL */ 614 if (!pdev || !event_cb) { 615 scm_err("pdev: %p, event_cb: %p", pdev, event_cb); 616 return QDF_STATUS_E_NULL_VALUE; 617 } 618 619 scm_info("pdev: %p, event_cb: %p, arg: %p\n", pdev, event_cb, arg); 620 621 scan = wlan_pdev_get_scan_obj(pdev); 622 pdev_ev_handler = wlan_pdev_get_pdev_scan_ev_handlers(pdev); 623 cb_handler = &(pdev_ev_handler->cb_handlers[0]); 624 625 qdf_spin_lock_bh(&scan->lock); 626 /* Ensure its not a duplicate registration request */ 627 for (idx = 0; idx < MAX_SCAN_EVENT_HANDLERS_PER_PDEV; 628 idx++, cb_handler++) { 629 if ((cb_handler->func == event_cb) && 630 (cb_handler->arg == arg)) { 631 qdf_spin_unlock_bh(&scan->lock); 632 scm_warn("func: %p, arg: %p already exists", 633 event_cb, arg); 634 return QDF_STATUS_SUCCESS; 635 } 636 } 637 638 QDF_ASSERT(pdev_ev_handler->handler_cnt < 639 MAX_SCAN_EVENT_HANDLERS_PER_PDEV); 640 641 if (pdev_ev_handler->handler_cnt >= MAX_SCAN_EVENT_HANDLERS_PER_PDEV) { 642 qdf_spin_unlock_bh(&scan->lock); 643 scm_warn("No more registrations possible"); 644 return QDF_STATUS_E_NOMEM; 645 } 646 647 scm_add_scan_event_handler(pdev_ev_handler, event_cb, arg); 648 qdf_spin_unlock_bh(&scan->lock); 649 650 scm_info("event_cb: 0x%p, arg: 0x%p", event_cb, arg); 651 652 return QDF_STATUS_SUCCESS; 653 } 654 655 static QDF_STATUS 656 wlan_scan_global_init(struct wlan_scan_obj *scan_obj) 657 { 658 scan_obj->scan_def.active_dwell = SCAN_ACTIVE_DWELL_TIME; 659 scan_obj->scan_def.passive_dwell = SCAN_PASSIVE_DWELL_TIME; 660 scan_obj->scan_def.max_rest_time = SCAN_MAX_REST_TIME; 661 scan_obj->scan_def.min_rest_time = SCAN_MIN_REST_TIME; 662 scan_obj->scan_def.conc_active_dwell = SCAN_CONC_ACTIVE_DWELL_TIME; 663 scan_obj->scan_def.conc_passive_dwell = SCAN_CONC_PASSIVE_DWELL_TIME; 664 scan_obj->scan_def.conc_max_rest_time = SCAN_CONC_MAX_REST_TIME; 665 scan_obj->scan_def.conc_min_rest_time = SCAN_CONC_MIN_REST_TIME; 666 scan_obj->scan_def.conc_idle_time = SCAN_CONC_IDLE_TIME; 667 scan_obj->scan_def.repeat_probe_time = SCAN_REPEAT_PROBE_TIME; 668 scan_obj->scan_def.probe_spacing_time = SCAN_PROBE_SPACING_TIME; 669 scan_obj->scan_def.probe_delay = SCAN_PROBE_DELAY; 670 scan_obj->scan_def.burst_duration = SCAN_BURST_DURATION; 671 scan_obj->scan_def.max_scan_time = SCAN_MAX_SCAN_TIME; 672 scan_obj->scan_def.num_probes = SCAN_NUM_PROBES; 673 scan_obj->scan_def.scan_cache_aging_time = SCAN_CACHE_AGING_TIME; 674 scan_obj->scan_def.max_bss_per_pdev = SCAN_MAX_BSS_PDEV; 675 scan_obj->scan_def.scan_priority = SCAN_PRIORITY; 676 scan_obj->scan_def.idle_time = SCAN_NETWORK_IDLE_TIMEOUT; 677 scan_obj->scan_def.adaptive_dwell_time_mode = SCAN_DWELL_MODE_DEFAULT; 678 /* scan contrl flags */ 679 scan_obj->scan_def.scan_f_passive = true; 680 scan_obj->scan_def.scan_f_ofdm_rates = true; 681 scan_obj->scan_def.scan_f_2ghz = true; 682 scan_obj->scan_def.scan_f_5ghz = true; 683 /* scan event flags */ 684 scan_obj->scan_def.scan_ev_started = true; 685 scan_obj->scan_def.scan_ev_completed = true; 686 scan_obj->scan_def.scan_ev_bss_chan = true; 687 scan_obj->scan_def.scan_ev_foreign_chan = true; 688 scan_obj->scan_def.scan_ev_dequeued = true; 689 scan_obj->scan_def.scan_ev_preempted = true; 690 scan_obj->scan_def.scan_ev_start_failed = true; 691 scan_obj->scan_def.scan_ev_restarted = true; 692 /* init scan id seed */ 693 qdf_atomic_init(&scan_obj->scan_ids); 694 695 return wlan_pno_global_init(&scan_obj->pno_cfg); 696 } 697 698 static QDF_STATUS 699 scm_remove_scan_event_handler(struct pdev_scan_ev_handler *pdev_ev_handler, 700 struct cb_handler *entry) 701 { 702 struct cb_handler *last_entry; 703 uint32_t handler_cnt = pdev_ev_handler->handler_cnt; 704 705 /* Replace event handler being deleted 706 * with the last one in the list. 707 */ 708 last_entry = &(pdev_ev_handler->cb_handlers[handler_cnt - 1]); 709 entry->func = last_entry->func; 710 entry->arg = last_entry->arg; 711 712 /* Clear our last entry */ 713 last_entry->func = NULL; 714 last_entry->arg = NULL; 715 pdev_ev_handler->handler_cnt--; 716 717 return QDF_STATUS_SUCCESS; 718 } 719 720 void 721 ucfg_scan_unregister_event_handler(struct wlan_objmgr_pdev *pdev, 722 scan_event_handler event_cb, void *arg) 723 { 724 uint8_t found = false; 725 uint32_t idx; 726 uint32_t handler_cnt; 727 struct wlan_scan_obj *scan; 728 struct cb_handler *cb_handler; 729 struct pdev_scan_ev_handler *pdev_ev_handler; 730 731 scm_info("pdev: %p, event_cb: 0x%p, arg: 0x%p", pdev, event_cb, arg); 732 if (!pdev) { 733 scm_err("null pdev"); 734 return; 735 } 736 scan = wlan_pdev_get_scan_obj(pdev); 737 pdev_ev_handler = wlan_pdev_get_pdev_scan_ev_handlers(pdev); 738 cb_handler = &(pdev_ev_handler->cb_handlers[0]); 739 740 qdf_spin_lock_bh(&scan->lock); 741 handler_cnt = pdev_ev_handler->handler_cnt; 742 if (!handler_cnt) { 743 qdf_spin_unlock_bh(&scan->lock); 744 scm_info("No event handlers registered"); 745 return; 746 } 747 748 for (idx = 0; idx < MAX_SCAN_EVENT_HANDLERS_PER_PDEV; 749 idx++, cb_handler++) { 750 if ((cb_handler->func == event_cb) && 751 (cb_handler->arg == arg)) { 752 /* Event handler found, remove it 753 * from event handler list. 754 */ 755 found = true; 756 scm_remove_scan_event_handler(pdev_ev_handler, 757 cb_handler); 758 handler_cnt--; 759 break; 760 } 761 } 762 qdf_spin_unlock_bh(&scan->lock); 763 764 scm_info("event handler %s, remaining handlers: %d", 765 (found ? "removed" : "not found"), handler_cnt); 766 } 767 768 QDF_STATUS 769 ucfg_scan_init_default_params(struct wlan_objmgr_vdev *vdev, 770 struct scan_start_request *req) 771 { 772 struct scan_default_params *def; 773 774 if (!vdev | !req) { 775 scm_err("vdev: 0x%p, req: 0x%p", vdev, req); 776 return QDF_STATUS_E_INVAL; 777 } 778 def = wlan_vdev_get_def_scan_params(vdev); 779 780 /* Zero out everything and explicitly set fields as required */ 781 qdf_mem_zero(req, sizeof(*req)); 782 783 req->vdev = vdev; 784 req->scan_req.vdev_id = wlan_vdev_get_id(vdev); 785 req->scan_req.scan_priority = def->scan_priority; 786 req->scan_req.dwell_time_active = def->active_dwell; 787 req->scan_req.dwell_time_passive = def->passive_dwell; 788 req->scan_req.min_rest_time = def->min_rest_time; 789 req->scan_req.max_rest_time = def->max_rest_time; 790 req->scan_req.repeat_probe_time = def->repeat_probe_time; 791 req->scan_req.probe_spacing_time = def->probe_spacing_time; 792 req->scan_req.idle_time = def->idle_time; 793 req->scan_req.max_scan_time = def->max_scan_time; 794 req->scan_req.probe_delay = def->probe_delay; 795 req->scan_req.burst_duration = def->burst_duration; 796 req->scan_req.n_probes = def->num_probes; 797 req->scan_req.adaptive_dwell_time_mode = 798 def->adaptive_dwell_time_mode; 799 req->scan_req.scan_flags = def->scan_flags; 800 req->scan_req.scan_events = def->scan_events; 801 802 return QDF_STATUS_SUCCESS; 803 } 804 805 QDF_STATUS 806 ucfg_scan_init_ssid_params(struct scan_start_request *req, 807 uint32_t num_ssid, struct wlan_ssid *ssid_list) 808 { 809 uint32_t max_ssid = sizeof(req->scan_req.ssid) / 810 sizeof(req->scan_req.ssid[0]); 811 812 if (!req) { 813 scm_err("null request"); 814 return QDF_STATUS_E_NULL_VALUE; 815 } 816 if (!num_ssid) { 817 /* empty channel list provided */ 818 req->scan_req.num_ssids = 0; 819 qdf_mem_zero(&req->scan_req.ssid[0], 820 sizeof(req->scan_req.ssid)); 821 return QDF_STATUS_SUCCESS; 822 } 823 if (!ssid_list) { 824 scm_err("null ssid_list while num_ssid: %d", num_ssid); 825 return QDF_STATUS_E_NULL_VALUE; 826 } 827 if (num_ssid > max_ssid) { 828 /* got a big list. alert and continue */ 829 scm_warn("overflow: received %d, max supported : %d", 830 num_ssid, max_ssid); 831 return QDF_STATUS_E_E2BIG; 832 } 833 834 if (max_ssid > num_ssid) 835 max_ssid = num_ssid; 836 837 req->scan_req.num_ssids = max_ssid; 838 qdf_mem_copy(&req->scan_req.ssid[0], ssid_list, 839 (req->scan_req.num_ssids * sizeof(req->scan_req.ssid[0]))); 840 841 return QDF_STATUS_SUCCESS; 842 } 843 844 QDF_STATUS 845 ucfg_scan_init_bssid_params(struct scan_start_request *req, 846 uint32_t num_bssid, struct qdf_mac_addr *bssid_list) 847 { 848 uint32_t max_bssid = sizeof(req->scan_req.bssid_list) / 849 sizeof(req->scan_req.bssid_list[0]); 850 851 if (!req) { 852 scm_err("null request"); 853 return QDF_STATUS_E_NULL_VALUE; 854 } 855 if (!num_bssid) { 856 /* empty channel list provided */ 857 req->scan_req.num_bssid = 0; 858 qdf_mem_zero(&req->scan_req.bssid_list[0], 859 sizeof(req->scan_req.bssid_list)); 860 return QDF_STATUS_SUCCESS; 861 } 862 if (!bssid_list) { 863 scm_err("null bssid_list while num_bssid: %d", num_bssid); 864 return QDF_STATUS_E_NULL_VALUE; 865 } 866 if (num_bssid > max_bssid) { 867 /* got a big list. alert and continue */ 868 scm_warn("overflow: received %d, max supported : %d", 869 num_bssid, max_bssid); 870 return QDF_STATUS_E_E2BIG; 871 } 872 873 if (max_bssid > num_bssid) 874 max_bssid = num_bssid; 875 876 req->scan_req.num_bssid = max_bssid; 877 qdf_mem_copy(&req->scan_req.bssid_list[0], bssid_list, 878 req->scan_req.num_bssid * sizeof(req->scan_req.bssid_list[0])); 879 880 return QDF_STATUS_SUCCESS; 881 } 882 883 QDF_STATUS 884 ucfg_scan_init_chanlist_params(struct scan_start_request *req, 885 uint32_t num_chans, uint32_t *chan_list) 886 { 887 888 uint32_t max_chans = sizeof(req->scan_req.chan_list) / 889 sizeof(req->scan_req.chan_list[0]); 890 if (!req) { 891 scm_err("null request"); 892 return QDF_STATUS_E_NULL_VALUE; 893 } 894 if (!num_chans) { 895 /* empty channel list provided */ 896 req->scan_req.num_chan = 0; 897 qdf_mem_zero(&req->scan_req.chan_list[0], 898 sizeof(req->scan_req.chan_list)); 899 return QDF_STATUS_SUCCESS; 900 } 901 if (!chan_list) { 902 scm_err("null chan_list while num_chans: %d", num_chans); 903 return QDF_STATUS_E_NULL_VALUE; 904 } 905 906 if (num_chans > max_chans) { 907 /* got a big list. alert and continue */ 908 scm_warn("overflow: received %d, max supported : %d", 909 num_chans, max_chans); 910 return QDF_STATUS_E_E2BIG; 911 } 912 913 if (max_chans > num_chans) 914 max_chans = num_chans; 915 916 req->scan_req.num_chan = max_chans; 917 qdf_mem_copy(&req->scan_req.chan_list[0], chan_list, 918 req->scan_req.num_chan * sizeof(req->scan_req.chan_list[0])); 919 920 return QDF_STATUS_SUCCESS; 921 } 922 923 static inline enum scm_scan_status 924 get_scan_status_from_serialization_status( 925 enum wlan_serialization_cmd_status status) 926 { 927 enum scm_scan_status scan_status; 928 929 switch (status) { 930 case WLAN_SER_CMD_IN_PENDING_LIST: 931 scan_status = SCAN_IS_PENDING; 932 break; 933 case WLAN_SER_CMD_IN_ACTIVE_LIST: 934 scan_status = SCAN_IS_ACTIVE; 935 break; 936 case WLAN_SER_CMDS_IN_ALL_LISTS: 937 scan_status = SCAN_IS_ACTIVE_AND_PENDING; 938 break; 939 case WLAN_SER_CMD_NOT_FOUND: 940 scan_status = SCAN_NOT_IN_PROGRESS; 941 break; 942 default: 943 scm_warn("invalid serialization status %d", status); 944 QDF_ASSERT(0); 945 scan_status = SCAN_NOT_IN_PROGRESS; 946 break; 947 } 948 949 return scan_status; 950 } 951 952 enum scm_scan_status 953 ucfg_scan_get_vdev_status(struct wlan_objmgr_vdev *vdev) 954 { 955 enum wlan_serialization_cmd_status status; 956 957 if (!vdev) { 958 scm_err("null vdev"); 959 return QDF_STATUS_E_NULL_VALUE; 960 } 961 status = wlan_serialization_vdev_scan_status(vdev); 962 963 return get_scan_status_from_serialization_status(status); 964 } 965 966 enum scm_scan_status 967 ucfg_scan_get_pdev_status(struct wlan_objmgr_pdev *pdev) 968 { 969 enum wlan_serialization_cmd_status status; 970 971 if (!pdev) { 972 scm_err("null pdev"); 973 return SCAN_NOT_IN_PROGRESS; 974 } 975 status = wlan_serialization_pdev_scan_status(pdev); 976 977 return get_scan_status_from_serialization_status(status); 978 } 979 980 static void 981 ucfg_scan_register_unregister_bcn_cb(struct wlan_objmgr_psoc *psoc, 982 bool enable) 983 { 984 QDF_STATUS status; 985 struct mgmt_txrx_mgmt_frame_cb_info cb_info[2]; 986 987 cb_info[0].frm_type = MGMT_PROBE_RESP; 988 cb_info[0].mgmt_rx_cb = tgt_scan_bcn_probe_rx_callback; 989 cb_info[1].frm_type = MGMT_BEACON; 990 cb_info[1].mgmt_rx_cb = tgt_scan_bcn_probe_rx_callback; 991 992 if (enable) 993 status = wlan_mgmt_txrx_register_rx_cb(psoc, 994 WLAN_UMAC_COMP_SCAN, cb_info, 2); 995 else 996 status = wlan_mgmt_txrx_deregister_rx_cb(psoc, 997 WLAN_UMAC_COMP_SCAN, cb_info, 2); 998 if (status != QDF_STATUS_SUCCESS) 999 scm_err("%s the Handle with MGMT TXRX layer has failed", 1000 enable ? "Registering" : "Deregistering"); 1001 } 1002 1003 static void ucfg_scan_assign_rssi_category(struct scan_default_params *params, 1004 int32_t best_ap_rssi, uint32_t cat_offset) 1005 { 1006 int i; 1007 1008 scm_info("best AP RSSI:%d, cat offset: %d", best_ap_rssi, cat_offset); 1009 if (cat_offset) 1010 for (i = 0; i < SCM_NUM_RSSI_CAT; i++) { 1011 params->rssi_cat[SCM_NUM_RSSI_CAT - i - 1] = 1012 (best_ap_rssi - 1013 params->select_5ghz_margin - 1014 (int)(i * cat_offset)); 1015 params->bss_prefer_val[i] = i; 1016 } 1017 } 1018 1019 QDF_STATUS ucfg_scan_update_user_config(struct wlan_objmgr_psoc *psoc, 1020 struct scan_user_cfg *scan_cfg) 1021 { 1022 struct wlan_scan_obj *scan_obj; 1023 struct scan_default_params *scan_def; 1024 1025 if (!psoc) { 1026 scm_err("null psoc"); 1027 return QDF_STATUS_E_FAILURE; 1028 } 1029 scan_obj = wlan_psoc_get_scan_obj(psoc); 1030 if (scan_obj == NULL) { 1031 scm_err("Failed to get scan object"); 1032 return QDF_STATUS_E_FAILURE; 1033 } 1034 1035 scan_def = &scan_obj->scan_def; 1036 scan_def->active_dwell = scan_cfg->active_dwell; 1037 scan_def->passive_dwell = scan_cfg->passive_dwell; 1038 scan_def->conc_active_dwell = scan_cfg->conc_active_dwell; 1039 scan_def->conc_passive_dwell = scan_cfg->conc_passive_dwell; 1040 scan_def->conc_max_rest_time = scan_cfg->conc_max_rest_time; 1041 scan_def->conc_min_rest_time = scan_cfg->conc_min_rest_time; 1042 scan_def->conc_idle_time = scan_cfg->conc_idle_time; 1043 scan_def->scan_cache_aging_time = scan_cfg->scan_cache_aging_time; 1044 scan_def->prefer_5ghz = scan_cfg->prefer_5ghz; 1045 scan_def->select_5ghz_margin = scan_cfg->select_5ghz_margin; 1046 scan_def->adaptive_dwell_time_mode = scan_cfg->scan_dwell_time_mode; 1047 scan_def->scan_f_chan_stat_evnt = scan_cfg->is_snr_monitoring_enabled; 1048 1049 ucfg_scan_assign_rssi_category(scan_def, 1050 scan_cfg->scan_bucket_threshold, 1051 scan_cfg->rssi_cat_gap); 1052 1053 return ucfg_scan_update_pno_config(&scan_obj->pno_cfg, 1054 &scan_cfg->pno_cfg); 1055 } 1056 1057 QDF_STATUS ucfg_scan_update_roam_params(struct wlan_objmgr_psoc *psoc, 1058 struct roam_filter_params *roam_params) 1059 { 1060 struct scan_default_params *scan_def; 1061 1062 if (!psoc) { 1063 scm_err("null psoc"); 1064 return QDF_STATUS_E_FAILURE; 1065 } 1066 scan_def = wlan_scan_psoc_get_def_params(psoc); 1067 if (!scan_def) { 1068 scm_err("Failed to get scan object"); 1069 return QDF_STATUS_E_FAILURE; 1070 } 1071 1072 qdf_mem_copy(&scan_def->roam_params, roam_params, 1073 sizeof(struct roam_filter_params)); 1074 1075 return QDF_STATUS_SUCCESS; 1076 } 1077 1078 static QDF_STATUS 1079 ucfg_scan_cancel_pdev_scan(struct wlan_objmgr_pdev *pdev) 1080 { 1081 struct scan_cancel_request *req; 1082 QDF_STATUS status; 1083 struct wlan_objmgr_vdev *vdev; 1084 1085 req = qdf_mem_malloc(sizeof(*req)); 1086 if (!req) { 1087 scm_err("Failed to allocate memory"); 1088 return QDF_STATUS_E_NOMEM; 1089 } 1090 1091 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, 0, WLAN_OSIF_ID); 1092 if (!vdev) { 1093 scm_err("Failed to get vdev"); 1094 return QDF_STATUS_E_INVAL; 1095 } 1096 req->vdev = vdev; 1097 req->cancel_req.scan_id = INVAL_SCAN_ID; 1098 wlan_pdev_obj_lock(pdev); 1099 req->cancel_req.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 1100 wlan_pdev_obj_unlock(pdev); 1101 req->cancel_req.vdev_id = INVAL_VDEV_ID; 1102 req->cancel_req.req_type = WLAN_SCAN_CANCEL_PDEV_ALL; 1103 status = ucfg_scan_cancel_sync(req); 1104 if (QDF_IS_STATUS_ERROR(status)) 1105 scm_err("Cancel scan request failed"); 1106 wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); 1107 1108 return status; 1109 } 1110 1111 #ifdef WLAN_PMO_ENABLE 1112 1113 static QDF_STATUS 1114 ucfg_scan_suspend_handler(struct wlan_objmgr_psoc *psoc, void *arg) 1115 { 1116 struct wlan_objmgr_pdev *pdev = NULL; 1117 QDF_STATUS status = QDF_STATUS_SUCCESS; 1118 int i; 1119 1120 /* Check all pdev */ 1121 for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) { 1122 pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_SCAN_ID); 1123 if (!pdev) 1124 continue; 1125 if (ucfg_scan_get_pdev_status(pdev) != 1126 SCAN_NOT_IN_PROGRESS) 1127 status = ucfg_scan_cancel_pdev_scan(pdev); 1128 wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID); 1129 if (QDF_IS_STATUS_ERROR(status)) { 1130 scm_err("failed to cancel scan for pdev_id %d", i); 1131 return status; 1132 } 1133 } 1134 1135 return QDF_STATUS_SUCCESS; 1136 } 1137 1138 static QDF_STATUS 1139 ucfg_scan_resume_handler(struct wlan_objmgr_psoc *psoc, void *arg) 1140 { 1141 return QDF_STATUS_SUCCESS; 1142 } 1143 1144 static inline void 1145 ucfg_scan_register_pmo_handler(void) 1146 { 1147 pmo_register_suspend_handler(WLAN_UMAC_COMP_SCAN, 1148 ucfg_scan_suspend_handler, NULL); 1149 pmo_register_resume_handler(WLAN_UMAC_COMP_SCAN, 1150 ucfg_scan_resume_handler, NULL); 1151 } 1152 1153 static inline void 1154 ucfg_scan_unregister_pmo_handler(void) 1155 { 1156 pmo_unregister_suspend_handler(WLAN_UMAC_COMP_SCAN, 1157 ucfg_scan_suspend_handler); 1158 pmo_unregister_resume_handler(WLAN_UMAC_COMP_SCAN, 1159 ucfg_scan_resume_handler); 1160 } 1161 1162 #else 1163 static inline void 1164 ucfg_scan_register_pmo_handler(void) 1165 { 1166 } 1167 1168 static inline void 1169 ucfg_scan_unregister_pmo_handler(void) 1170 { 1171 } 1172 #endif 1173 1174 QDF_STATUS 1175 ucfg_scan_psoc_open(struct wlan_objmgr_psoc *psoc) 1176 { 1177 struct wlan_scan_obj *scan_obj; 1178 1179 scm_info("psoc open: 0x%p", psoc); 1180 if (!psoc) { 1181 scm_err("null psoc"); 1182 return QDF_STATUS_E_FAILURE; 1183 } 1184 scan_obj = wlan_psoc_get_scan_obj(psoc); 1185 if (scan_obj == NULL) { 1186 scm_err("Failed to get scan object"); 1187 return QDF_STATUS_E_FAILURE; 1188 } 1189 /* Initialize the scan Globals */ 1190 wlan_scan_global_init(scan_obj); 1191 qdf_spinlock_create(&scan_obj->lock); 1192 ucfg_scan_register_pmo_handler(); 1193 1194 return QDF_STATUS_SUCCESS; 1195 } 1196 1197 QDF_STATUS 1198 ucfg_scan_psoc_close(struct wlan_objmgr_psoc *psoc) 1199 { 1200 struct wlan_scan_obj *scan_obj; 1201 1202 scm_info("psoc close: 0x%p", psoc); 1203 if (!psoc) { 1204 scm_err("null psoc"); 1205 return QDF_STATUS_E_FAILURE; 1206 } 1207 scan_obj = wlan_psoc_get_scan_obj(psoc); 1208 if (scan_obj == NULL) { 1209 scm_err("Failed to get scan object"); 1210 return QDF_STATUS_E_FAILURE; 1211 } 1212 ucfg_scan_unregister_pmo_handler(); 1213 qdf_spinlock_destroy(&scan_obj->lock); 1214 wlan_pno_global_deinit(&scan_obj->pno_cfg); 1215 1216 return QDF_STATUS_SUCCESS; 1217 } 1218 1219 static bool scm_serialization_scan_rules_cb( 1220 union wlan_serialization_rules_info *comp_info, 1221 uint8_t comp_id) 1222 { 1223 switch (comp_id) { 1224 case QDF_MODULE_ID_TDLS: 1225 if (comp_info->scan_info.is_tdls_in_progress) { 1226 scm_info("Cancel scan. Tdls in progress"); 1227 return false; 1228 } 1229 break; 1230 case QDF_MODULE_ID_DFS: 1231 if (comp_info->scan_info.is_cac_in_progress) { 1232 scm_info("Cancel scan. CAC in progress"); 1233 return false; 1234 } 1235 break; 1236 default: 1237 scm_info("not handled comp_id %d", comp_id); 1238 break; 1239 } 1240 1241 return true; 1242 } 1243 1244 QDF_STATUS 1245 ucfg_scan_psoc_enable(struct wlan_objmgr_psoc *psoc) 1246 { 1247 QDF_STATUS status; 1248 1249 scm_info("psoc enable: 0x%p", psoc); 1250 if (!psoc) { 1251 scm_err("null psoc"); 1252 return QDF_STATUS_E_FAILURE; 1253 } 1254 /* Subscribe for scan events from lmac layesr */ 1255 status = tgt_scan_register_ev_handler(psoc); 1256 QDF_ASSERT(status == QDF_STATUS_SUCCESS); 1257 scm_db_init(psoc); 1258 ucfg_scan_register_unregister_bcn_cb(psoc, true); 1259 status = wlan_serialization_register_apply_rules_cb(psoc, 1260 WLAN_SER_CMD_SCAN, 1261 scm_serialization_scan_rules_cb); 1262 QDF_ASSERT(status == QDF_STATUS_SUCCESS); 1263 return status; 1264 } 1265 1266 QDF_STATUS 1267 ucfg_scan_psoc_disable(struct wlan_objmgr_psoc *psoc) 1268 { 1269 QDF_STATUS status; 1270 1271 scm_info("psoc disable: 0x%p", psoc); 1272 if (!psoc) { 1273 scm_err("null psoc"); 1274 return QDF_STATUS_E_FAILURE; 1275 } 1276 /* Unsubscribe for scan events from lmac layesr */ 1277 status = tgt_scan_unregister_ev_handler(psoc); 1278 QDF_ASSERT(status == QDF_STATUS_SUCCESS); 1279 ucfg_scan_register_unregister_bcn_cb(psoc, false); 1280 scm_db_deinit(psoc); 1281 1282 return status; 1283 } 1284 1285 uint32_t 1286 ucfg_scan_get_max_active_scans(struct wlan_objmgr_psoc *psoc) 1287 { 1288 struct scan_default_params *scan_params = NULL; 1289 1290 if (!psoc) { 1291 scm_err("null psoc"); 1292 return 0; 1293 } 1294 scan_params = wlan_scan_psoc_get_def_params(psoc); 1295 1296 return scan_params->max_active_scans_allowed; 1297 } 1298