1 /* 2 * Copyright (c) 2017-2019 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 manager functionality 21 */ 22 23 #include <wlan_serialization_api.h> 24 #include <wlan_scan_ucfg_api.h> 25 #include <wlan_scan_tgt_api.h> 26 #include "wlan_scan_main.h" 27 #include "wlan_scan_manager.h" 28 #include "wlan_utility.h" 29 #include <wlan_reg_services_api.h> 30 #ifdef FEATURE_WLAN_SCAN_PNO 31 #include <host_diag_core_event.h> 32 #endif 33 #ifdef WLAN_POLICY_MGR_ENABLE 34 #include <wlan_policy_mgr_api.h> 35 #endif 36 #include <wlan_dfs_utils_api.h> 37 38 QDF_STATUS 39 scm_scan_free_scan_request_mem(struct scan_start_request *req) 40 { 41 void *ie; 42 43 if (!req) { 44 scm_err("null request"); 45 QDF_ASSERT(0); 46 return QDF_STATUS_E_FAILURE; 47 } 48 scm_debug("freed scan request: 0x%pK, scan_id: %d, requester: %d", 49 req, req->scan_req.scan_id, req->scan_req.scan_req_id); 50 /* Free vendor(extra) ie */ 51 ie = req->scan_req.extraie.ptr; 52 if (ie) { 53 req->scan_req.extraie.ptr = NULL; 54 req->scan_req.extraie.len = 0; 55 qdf_mem_free(ie); 56 } 57 58 /* Free htcap ie */ 59 ie = req->scan_req.htcap.ptr; 60 if (ie) { 61 req->scan_req.htcap.len = 0; 62 req->scan_req.htcap.ptr = NULL; 63 qdf_mem_free(ie); 64 } 65 66 /* Free vhtcap ie */ 67 ie = req->scan_req.vhtcap.ptr; 68 if (ie) { 69 req->scan_req.vhtcap.len = 0; 70 req->scan_req.vhtcap.ptr = NULL; 71 qdf_mem_free(ie); 72 } 73 /* free scan_start_request memory */ 74 qdf_mem_free(req); 75 76 return QDF_STATUS_SUCCESS; 77 } 78 79 static QDF_STATUS 80 scm_scan_get_pdev_global_event_handlers(struct scan_event_listeners *listeners, 81 struct pdev_scan_ev_handler *pdev_ev_handler) 82 { 83 uint32_t i; 84 struct cb_handler *cb_handlers = &(pdev_ev_handler->cb_handlers[0]); 85 86 for (i = 0; i < MAX_SCAN_EVENT_HANDLERS_PER_PDEV; i++, cb_handlers++) { 87 if ((cb_handlers->func) && 88 (listeners->count < MAX_SCAN_EVENT_LISTENERS)) { 89 listeners->cb[listeners->count].func = 90 cb_handlers->func; 91 listeners->cb[listeners->count].arg = 92 cb_handlers->arg; 93 listeners->count++; 94 } 95 } 96 97 return QDF_STATUS_SUCCESS; 98 } 99 100 static QDF_STATUS 101 scm_scan_get_requester_event_handler(struct scan_event_listeners *listeners, 102 struct scan_requester_info *requesters, 103 wlan_scan_requester requester_id) 104 { 105 uint32_t idx; 106 struct cb_handler *ev_handler; 107 108 idx = requester_id & WLAN_SCAN_REQUESTER_ID_PREFIX; 109 if (idx != WLAN_SCAN_REQUESTER_ID_PREFIX) 110 return QDF_STATUS_SUCCESS; 111 112 idx = requester_id & WLAN_SCAN_REQUESTER_ID_MASK; 113 if (idx < WLAN_MAX_REQUESTORS) { 114 ev_handler = &(requesters[idx].ev_handler); 115 if (ev_handler->func) { 116 if (listeners->count < MAX_SCAN_EVENT_LISTENERS) { 117 listeners->cb[listeners->count].func = 118 ev_handler->func; 119 listeners->cb[listeners->count].arg = 120 ev_handler->arg; 121 listeners->count++; 122 } 123 } 124 return QDF_STATUS_SUCCESS; 125 } else { 126 scm_err("invalid requester id"); 127 return QDF_STATUS_E_INVAL; 128 } 129 130 } 131 132 static void scm_scan_post_event(struct wlan_objmgr_vdev *vdev, 133 struct scan_event *event) 134 { 135 uint32_t i = 0; 136 struct wlan_scan_obj *scan; 137 struct pdev_scan_ev_handler *pdev_ev_handler; 138 struct cb_handler *cb_handlers; 139 struct scan_requester_info *requesters; 140 struct scan_event_listeners *listeners; 141 142 if (!vdev || !event) { 143 scm_err("vdev: 0x%pK, event: 0x%pK", vdev, event); 144 return; 145 } 146 if (!event->requester) { 147 scm_err("invalid requester id"); 148 QDF_ASSERT(0); 149 } 150 scan = wlan_vdev_get_scan_obj(vdev); 151 pdev_ev_handler = wlan_vdev_get_pdev_scan_ev_handlers(vdev); 152 if (!pdev_ev_handler) 153 return; 154 cb_handlers = &(pdev_ev_handler->cb_handlers[0]); 155 requesters = scan->requesters; 156 157 scm_debug("vdev: %d, type: %d, reason: %d, freq: %d, req: %d, scanid: %d", 158 event->vdev_id, event->type, event->reason, event->chan_freq, 159 event->requester, event->scan_id); 160 161 listeners = qdf_mem_malloc_atomic(sizeof(*listeners)); 162 if (!listeners) { 163 scm_warn("couldn't allocate listeners list"); 164 return; 165 } 166 167 /* initialize number of listeners */ 168 listeners->count = 0; 169 170 /* 171 * Initiator of scan request decides which all scan events 172 * he is interested in and FW will send only those scan events 173 * to host driver. 174 * All the events received by scan module will be notified 175 * to all registered handlers. 176 */ 177 178 qdf_spin_lock_bh(&scan->lock); 179 /* find all global scan event handlers on this pdev */ 180 scm_scan_get_pdev_global_event_handlers(listeners, pdev_ev_handler); 181 /* find owner who triggered this scan request */ 182 scm_scan_get_requester_event_handler(listeners, requesters, 183 event->requester); 184 qdf_spin_unlock_bh(&scan->lock); 185 186 /* notify all interested handlers */ 187 for (i = 0; i < listeners->count; i++) { 188 scm_debug("func: 0x%pK, arg: 0x%pK", 189 listeners->cb[i].func, listeners->cb[i].arg); 190 listeners->cb[i].func(vdev, event, listeners->cb[i].arg); 191 } 192 qdf_mem_free(listeners); 193 } 194 195 static QDF_STATUS 196 scm_release_serialization_command(struct wlan_objmgr_vdev *vdev, 197 uint32_t scan_id) 198 { 199 struct wlan_serialization_queued_cmd_info cmd = {0}; 200 201 cmd.requestor = WLAN_UMAC_COMP_SCAN; 202 cmd.cmd_type = WLAN_SER_CMD_SCAN; 203 cmd.cmd_id = scan_id; 204 cmd.req_type = WLAN_SER_CANCEL_SINGLE_SCAN; 205 cmd.vdev = vdev; 206 cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE; 207 208 /* Inform serialization for command completion */ 209 wlan_serialization_remove_cmd(&cmd); 210 211 return QDF_STATUS_SUCCESS; 212 } 213 214 static QDF_STATUS 215 scm_post_internal_scan_complete_event(struct scan_start_request *req, 216 enum scan_completion_reason reason) 217 { 218 struct scan_event event = {0, }; 219 220 /* prepare internal scan complete event */ 221 event.type = SCAN_EVENT_TYPE_COMPLETED; 222 event.reason = reason; 223 event.chan_freq = 0; /* Invalid frequency */ 224 event.vdev_id = req->scan_req.vdev_id; 225 event.requester = req->scan_req.scan_req_id; 226 event.scan_id = req->scan_req.scan_id; 227 /* Fill scan_start_request used to trigger this scan */ 228 event.scan_start_req = req; 229 /* post scan event to registered handlers */ 230 scm_scan_post_event(req->vdev, &event); 231 232 return QDF_STATUS_SUCCESS; 233 } 234 235 static inline struct pdev_scan_info * 236 scm_scan_get_pdev_priv_info(uint8_t pdev_id, struct wlan_scan_obj *scan_obj) 237 { 238 return &scan_obj->pdev_info[pdev_id]; 239 } 240 241 static QDF_STATUS 242 scm_update_last_scan_time(struct scan_start_request *req) 243 { 244 uint8_t pdev_id; 245 struct wlan_scan_obj *scan_obj; 246 struct pdev_scan_info *pdev_scan_info; 247 248 scan_obj = wlan_vdev_get_scan_obj(req->vdev); 249 pdev_id = wlan_scan_vdev_get_pdev_id(req->vdev); 250 pdev_scan_info = scm_scan_get_pdev_priv_info(pdev_id, scan_obj); 251 /* update last scan start time */ 252 pdev_scan_info->last_scan_time = qdf_system_ticks(); 253 254 return QDF_STATUS_SUCCESS; 255 } 256 257 static QDF_STATUS 258 scm_activate_scan_request(struct scan_start_request *req) 259 { 260 QDF_STATUS status; 261 262 status = tgt_scan_start(req); 263 if (status != QDF_STATUS_SUCCESS) { 264 scm_err("tgt_scan_start failed, status: %d", status); 265 /* scan could not be started and hence 266 * we will not receive any completions. 267 * post scan cancelled 268 */ 269 scm_post_internal_scan_complete_event(req, 270 SCAN_REASON_CANCELLED); 271 return status; 272 } 273 /* save last scan start time */ 274 status = scm_update_last_scan_time(req); 275 276 return status; 277 } 278 279 static QDF_STATUS 280 scm_cancel_scan_request(struct scan_start_request *req) 281 { 282 struct scan_cancel_request cancel_req = {0, }; 283 QDF_STATUS status; 284 285 cancel_req.vdev = req->vdev; 286 cancel_req.cancel_req.scan_id = req->scan_req.scan_id; 287 cancel_req.cancel_req.requester = req->scan_req.scan_req_id; 288 cancel_req.cancel_req.req_type = WLAN_SCAN_CANCEL_SINGLE; 289 cancel_req.cancel_req.vdev_id = req->scan_req.vdev_id; 290 /* send scan cancel to fw */ 291 status = tgt_scan_cancel(&cancel_req); 292 if (status != QDF_STATUS_SUCCESS) 293 scm_err("tgt_scan_cancel failed: status: %d, scanid: %d", 294 status, req->scan_req.scan_id); 295 /* notify event handler about scan cancellation */ 296 scm_post_internal_scan_complete_event(req, SCAN_REASON_CANCELLED); 297 298 return status; 299 } 300 301 static QDF_STATUS 302 scm_scan_serialize_callback(struct wlan_serialization_command *cmd, 303 enum wlan_serialization_cb_reason reason) 304 { 305 struct scan_start_request *req; 306 QDF_STATUS status; 307 308 if (!cmd) { 309 scm_err("cmd is NULL, reason: %d", reason); 310 QDF_ASSERT(0); 311 return QDF_STATUS_E_NULL_VALUE; 312 } 313 314 if (!cmd->umac_cmd) { 315 scm_err("cmd->umac_cmd is NULL , reason: %d", reason); 316 QDF_ASSERT(0); 317 return QDF_STATUS_E_NULL_VALUE; 318 } 319 320 req = cmd->umac_cmd; 321 scm_debug("reason:%d, reqid:%d, scanid:%d, vdevid:%d, vdev:0x%pK", 322 reason, req->scan_req.scan_req_id, req->scan_req.scan_id, 323 req->scan_req.vdev_id, req->vdev); 324 325 if (!req->vdev) { 326 scm_err("NULL vdev. req:0x%pK, reason:%d\n", req, reason); 327 QDF_ASSERT(0); 328 return QDF_STATUS_E_NULL_VALUE; 329 } 330 331 qdf_mtrace(QDF_MODULE_ID_SERIALIZATION, QDF_MODULE_ID_SCAN, reason, 332 req->scan_req.vdev_id, req->scan_req.scan_id); 333 334 switch (reason) { 335 case WLAN_SER_CB_ACTIVATE_CMD: 336 /* command moved to active list 337 * modify the params if required for concurency case. 338 */ 339 status = scm_activate_scan_request(req); 340 break; 341 342 case WLAN_SER_CB_CANCEL_CMD: 343 /* command removed from pending list. 344 * notify registered scan event handlers with 345 * status completed and reason cancelled. 346 */ 347 status = scm_post_internal_scan_complete_event(req, 348 SCAN_REASON_CANCELLED); 349 break; 350 351 case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: 352 /* active command timed out. 353 * prepare internal scan cancel request 354 */ 355 status = scm_cancel_scan_request(req); 356 break; 357 358 case WLAN_SER_CB_RELEASE_MEM_CMD: 359 /* command successfully completed. 360 * Release vdev reference and free scan_start_request memory 361 */ 362 cmd->umac_cmd = NULL; 363 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 364 status = scm_scan_free_scan_request_mem(req); 365 break; 366 367 default: 368 /* Do nothing but logging */ 369 QDF_ASSERT(0); 370 status = QDF_STATUS_E_INVAL; 371 break; 372 } 373 374 return status; 375 } 376 377 bool scm_is_scan_allowed(struct wlan_objmgr_vdev *vdev) 378 { 379 struct wlan_scan_obj *scan_psoc_obj; 380 struct scan_vdev_obj *scan_vdev_obj; 381 382 if (!vdev) { 383 scm_err("vdev is NULL"); 384 return false; 385 } 386 387 scan_psoc_obj = wlan_vdev_get_scan_obj(vdev); 388 if (!scan_psoc_obj) { 389 scm_err("Couldn't find scan psoc object"); 390 return false; 391 } 392 393 if (scan_psoc_obj->scan_disabled) { 394 scm_err_rl("scan disabled %x, for psoc", 395 scan_psoc_obj->scan_disabled); 396 return false; 397 } 398 399 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 400 if (!scan_vdev_obj) { 401 scm_err("Couldn't find scan vdev object"); 402 return false; 403 } 404 405 if (scan_vdev_obj->scan_disabled) { 406 scm_err_rl("scan disabled %x on vdev_id:%d", 407 scan_vdev_obj->scan_disabled, 408 wlan_vdev_get_id(vdev)); 409 return false; 410 } 411 412 return true; 413 } 414 415 #ifdef WLAN_POLICY_MGR_ENABLE 416 /** 417 * scm_update_dbs_scan_ctrl_ext_flag() - update dbs scan ctrl flags 418 * @req: pointer to scan request 419 * 420 * This function sets scan_ctrl_flags_ext value depending on the type of 421 * scan and the channel lists. 422 * 423 * Non-DBS scan is requested if any of the below case is met: 424 * 1. HW is DBS incapable 425 * 2. A high accuracy scan request is sent by kernel. 426 * 427 * DBS scan is enabled for these conditions: 428 * 1. A low power or low span scan request is sent by kernel. 429 * For remaining cases DBS is enabled by default. 430 * Return: void 431 */ 432 static void 433 scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req) 434 { 435 struct wlan_objmgr_psoc *psoc; 436 uint32_t scan_dbs_policy = SCAN_DBS_POLICY_DEFAULT; 437 438 psoc = wlan_vdev_get_psoc(req->vdev); 439 440 if (!policy_mgr_is_hw_dbs_capable(psoc)) { 441 scm_debug("dbs disabled, going for non-dbs scan"); 442 scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS; 443 goto end; 444 } 445 446 if (!wlan_scan_cfg_honour_nl_scan_policy_flags(psoc)) { 447 scm_debug("nl scan policy flags not honoured, goto end"); 448 goto end; 449 } 450 451 if (req->scan_req.scan_policy_high_accuracy) { 452 scm_debug("high accuracy scan received, going for non-dbs scan"); 453 scan_dbs_policy = SCAN_DBS_POLICY_FORCE_NONDBS; 454 goto end; 455 } 456 if ((req->scan_req.scan_policy_low_power) || 457 (req->scan_req.scan_policy_low_span)) { 458 scm_debug("low power/span scan received, going for dbs scan"); 459 scan_dbs_policy = SCAN_DBS_POLICY_IGNORE_DUTY; 460 goto end; 461 } 462 463 end: 464 req->scan_req.scan_ctrl_flags_ext |= 465 ((scan_dbs_policy << SCAN_FLAG_EXT_DBS_SCAN_POLICY_BIT) 466 & SCAN_FLAG_EXT_DBS_SCAN_POLICY_MASK); 467 scm_debug("scan_ctrl_flags_ext: 0x%x", 468 req->scan_req.scan_ctrl_flags_ext); 469 } 470 471 /** 472 * scm_update_passive_dwell_time() - update dwell passive time 473 * @vdev: vdev object 474 * @req: scan request 475 * 476 * Return: None 477 */ 478 static void 479 scm_update_passive_dwell_time(struct wlan_objmgr_vdev *vdev, 480 struct scan_start_request *req) 481 { 482 struct wlan_objmgr_psoc *psoc; 483 484 psoc = wlan_vdev_get_psoc(vdev); 485 if (!psoc) 486 return; 487 488 if (policy_mgr_is_sta_connected_2g(psoc) && 489 !policy_mgr_is_hw_dbs_capable(psoc) && 490 ucfg_scan_get_bt_activity(psoc)) 491 req->scan_req.dwell_time_passive = 492 PASSIVE_DWELL_TIME_BT_A2DP_ENABLED; 493 } 494 495 static const struct probe_time_dwell_time 496 scan_probe_time_dwell_time_map[SCAN_DWELL_TIME_PROBE_TIME_MAP_SIZE] = { 497 {28, 11}, /* 0 SSID */ 498 {28, 20}, /* 1 SSID */ 499 {28, 20}, /* 2 SSID */ 500 {28, 20}, /* 3 SSID */ 501 {28, 20}, /* 4 SSID */ 502 {28, 20}, /* 5 SSID */ 503 {28, 20}, /* 6 SSID */ 504 {28, 11}, /* 7 SSID */ 505 {28, 11}, /* 8 SSID */ 506 {28, 11}, /* 9 SSID */ 507 {28, 8} /* 10 SSID */ 508 }; 509 510 /** 511 * scm_scan_get_burst_duration() - get burst duration depending on max chan 512 * and miracast. 513 * @max_ch_time: max channel time 514 * @miracast_enabled: if miracast is enabled 515 * 516 * Return: burst_duration 517 */ 518 static inline 519 int scm_scan_get_burst_duration(int max_ch_time, bool miracast_enabled) 520 { 521 int burst_duration = 0; 522 523 if (miracast_enabled) { 524 /* 525 * When miracast is running, burst 526 * duration needs to be minimum to avoid 527 * any stutter or glitch in miracast 528 * during station scan 529 */ 530 if (max_ch_time <= SCAN_GO_MIN_ACTIVE_SCAN_BURST_DURATION) 531 burst_duration = max_ch_time; 532 else 533 burst_duration = SCAN_GO_MIN_ACTIVE_SCAN_BURST_DURATION; 534 } else { 535 /* 536 * If miracast is not running, accommodate max 537 * stations to make the scans faster 538 */ 539 burst_duration = SCAN_GO_BURST_SCAN_MAX_NUM_OFFCHANNELS * 540 max_ch_time; 541 542 if (burst_duration > SCAN_GO_MAX_ACTIVE_SCAN_BURST_DURATION) { 543 uint8_t channels = SCAN_P2P_SCAN_MAX_BURST_DURATION / 544 max_ch_time; 545 546 if (channels) 547 burst_duration = channels * max_ch_time; 548 else 549 burst_duration = 550 SCAN_GO_MAX_ACTIVE_SCAN_BURST_DURATION; 551 } 552 } 553 return burst_duration; 554 } 555 556 /** 557 * scm_req_update_concurrency_params() - update scan req params depending on 558 * concurrent mode present. 559 * @vdev: vdev object pointer 560 * @req: scan request 561 * @scan_obj: scan object 562 * 563 * Return: void 564 */ 565 static void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev, 566 struct scan_start_request *req, 567 struct wlan_scan_obj *scan_obj) 568 { 569 bool ap_present, go_present, sta_active, p2p_cli_present, ndi_present; 570 struct wlan_objmgr_psoc *psoc; 571 uint16_t sap_peer_count = 0; 572 uint16_t go_peer_count = 0; 573 struct wlan_objmgr_pdev *pdev; 574 575 psoc = wlan_vdev_get_psoc(vdev); 576 pdev = wlan_vdev_get_pdev(vdev); 577 578 if (!psoc || !pdev) 579 return; 580 581 ap_present = policy_mgr_mode_specific_connection_count( 582 psoc, PM_SAP_MODE, NULL); 583 go_present = policy_mgr_mode_specific_connection_count( 584 psoc, PM_P2P_GO_MODE, NULL); 585 p2p_cli_present = policy_mgr_mode_specific_connection_count( 586 psoc, PM_P2P_CLIENT_MODE, NULL); 587 sta_active = policy_mgr_mode_specific_connection_count( 588 psoc, PM_STA_MODE, NULL); 589 ndi_present = policy_mgr_mode_specific_connection_count( 590 psoc, PM_NDI_MODE, NULL); 591 if (ap_present) 592 sap_peer_count = 593 wlan_util_get_peer_count_for_mode(pdev, QDF_SAP_MODE); 594 if (go_present) 595 go_peer_count = 596 wlan_util_get_peer_count_for_mode(pdev, QDF_P2P_GO_MODE); 597 598 if (!req->scan_req.scan_f_passive) 599 scm_update_passive_dwell_time(vdev, req); 600 601 if (policy_mgr_get_connection_count(psoc)) { 602 if (req->scan_req.scan_f_passive) 603 req->scan_req.dwell_time_passive = 604 scan_obj->scan_def.conc_passive_dwell; 605 else 606 req->scan_req.dwell_time_active = 607 scan_obj->scan_def.conc_active_dwell; 608 req->scan_req.max_rest_time = 609 scan_obj->scan_def.conc_max_rest_time; 610 req->scan_req.min_rest_time = 611 scan_obj->scan_def.conc_min_rest_time; 612 req->scan_req.idle_time = scan_obj->scan_def.conc_idle_time; 613 } 614 615 if (wlan_vdev_is_up(req->vdev) != QDF_STATUS_SUCCESS) 616 req->scan_req.adaptive_dwell_time_mode = 617 scan_obj->scan_def.adaptive_dwell_time_mode_nc; 618 /* 619 * If AP/GO is active and has connected clients set min rest time 620 * same as max rest time, so that firmware spends more time on home 621 * channel which will increase the probability of sending beacon at TBTT 622 */ 623 if ((ap_present && sap_peer_count) || 624 (go_present && go_peer_count)) { 625 req->scan_req.dwell_time_active_2g = 0; 626 req->scan_req.min_rest_time = req->scan_req.max_rest_time; 627 } 628 629 /* 630 * If scan req for SAP (ACS Sacn) use dwell_time_active_def as dwell 631 * time for 2g channels instead of dwell_time_active_2g 632 */ 633 if (vdev->vdev_mlme.vdev_opmode == QDF_SAP_MODE) 634 req->scan_req.dwell_time_active_2g = 0; 635 636 if (req->scan_req.scan_type == SCAN_TYPE_DEFAULT) { 637 /* 638 * Decide burst_duration and dwell_time_active based on 639 * what type of devices are active. 640 */ 641 do { 642 if (ap_present && go_present && sta_active) { 643 if (req->scan_req.dwell_time_active <= 644 SCAN_3PORT_CONC_SCAN_MAX_BURST_DURATION) 645 req->scan_req.burst_duration = 646 req->scan_req.dwell_time_active; 647 else 648 req->scan_req.burst_duration = 649 SCAN_3PORT_CONC_SCAN_MAX_BURST_DURATION; 650 651 break; 652 } 653 654 if (scan_obj->miracast_enabled && 655 policy_mgr_is_mcc_in_24G(psoc)) 656 req->scan_req.max_rest_time = 657 scan_obj->scan_def.sta_miracast_mcc_rest_time; 658 659 if (go_present) { 660 /* 661 * Background scan while GO is sending beacons. 662 * Every off-channel transition has overhead of 663 * 2 beacon intervals for NOA. Maximize number 664 * of channels in every transition by using 665 * burst scan. 666 */ 667 if (scan_obj->scan_def.go_scan_burst_duration) 668 req->scan_req.burst_duration = 669 scan_obj-> 670 scan_def.go_scan_burst_duration; 671 else 672 req->scan_req.burst_duration = 673 scm_scan_get_burst_duration( 674 req->scan_req. 675 dwell_time_active, 676 scan_obj-> 677 miracast_enabled); 678 break; 679 } 680 if ((sta_active || p2p_cli_present)) { 681 if (scan_obj->scan_def.sta_scan_burst_duration) 682 req->scan_req.burst_duration = 683 scan_obj->scan_def. 684 sta_scan_burst_duration; 685 break; 686 } 687 688 if (ndi_present) { 689 req->scan_req.burst_duration = 690 scm_scan_get_burst_duration( 691 req->scan_req.dwell_time_active, 692 scan_obj->miracast_enabled); 693 break; 694 } 695 } while (0); 696 697 if (ap_present) { 698 uint8_t ssid_num; 699 700 ssid_num = req->scan_req.num_ssids * 701 req->scan_req.num_bssid; 702 req->scan_req.repeat_probe_time = 703 scan_probe_time_dwell_time_map[ 704 QDF_MIN(ssid_num, 705 SCAN_DWELL_TIME_PROBE_TIME_MAP_SIZE 706 - 1)].probe_time; 707 req->scan_req.n_probes = 708 (req->scan_req.repeat_probe_time > 0) ? 709 req->scan_req.dwell_time_active / 710 req->scan_req.repeat_probe_time : 0; 711 } 712 } 713 714 if (ap_present) { 715 uint8_t ap_chan; 716 struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); 717 718 ap_chan = policy_mgr_get_channel(psoc, PM_SAP_MODE, NULL); 719 /* 720 * P2P/STA scan while SoftAP is sending beacons. 721 * Max duration of CTS2self is 32 ms, which limits the 722 * dwell time. If DBS is supported and if SAP is on 2G channel 723 * then keep passive dwell time default. 724 */ 725 if (sap_peer_count) { 726 req->scan_req.dwell_time_active = 727 QDF_MIN(req->scan_req.dwell_time_active, 728 (SCAN_CTS_DURATION_MS_MAX - 729 SCAN_ROAM_SCAN_CHANNEL_SWITCH_TIME)); 730 if (!policy_mgr_is_hw_dbs_capable(psoc) || 731 (policy_mgr_is_hw_dbs_capable(psoc) && 732 WLAN_CHAN_IS_5GHZ(ap_chan))) { 733 req->scan_req.dwell_time_passive = 734 req->scan_req.dwell_time_active; 735 } 736 } 737 if (scan_obj->scan_def.ap_scan_burst_duration) { 738 req->scan_req.burst_duration = 739 scan_obj->scan_def.ap_scan_burst_duration; 740 } else { 741 req->scan_req.burst_duration = 0; 742 if (utils_is_dfs_ch(pdev, ap_chan)) 743 req->scan_req.burst_duration = 744 SCAN_BURST_SCAN_MAX_NUM_OFFCHANNELS * 745 req->scan_req.dwell_time_active; 746 } 747 } 748 } 749 750 #else 751 static inline 752 void scm_req_update_concurrency_params(struct wlan_objmgr_vdev *vdev, 753 struct scan_start_request *req, 754 struct wlan_scan_obj *scan_obj) 755 { 756 } 757 758 static inline void 759 scm_update_dbs_scan_ctrl_ext_flag(struct scan_start_request *req) 760 { 761 } 762 #endif 763 764 /** 765 * scm_update_channel_list() - update scan req params depending on dfs inis 766 * and initial scan request. 767 * @req: scan request 768 * @scan_obj: scan object 769 * 770 * Return: void 771 */ 772 static void 773 scm_update_channel_list(struct scan_start_request *req, 774 struct wlan_scan_obj *scan_obj) 775 { 776 uint8_t i; 777 uint8_t num_scan_channels = 0; 778 struct scan_vdev_obj *scan_vdev_obj; 779 struct wlan_objmgr_pdev *pdev; 780 bool first_scan_done = true; 781 bool p2p_search = false; 782 bool skip_dfs_ch = true; 783 784 pdev = wlan_vdev_get_pdev(req->vdev); 785 786 scan_vdev_obj = wlan_get_vdev_scan_obj(req->vdev); 787 if (!scan_vdev_obj) { 788 scm_err("null scan_vdev_obj"); 789 return; 790 } 791 792 if (!scan_vdev_obj->first_scan_done) { 793 first_scan_done = false; 794 scan_vdev_obj->first_scan_done = true; 795 } 796 797 if (req->scan_req.scan_type == SCAN_TYPE_P2P_SEARCH) 798 p2p_search = true; 799 /* 800 * No need to update channels if req is single channel* ie ROC, 801 * Preauth or a single channel scan etc. 802 * If the single chan in the scan channel list is an NOL channel,it is 803 * not removed as it would reduce the number of scan channels to 0 804 * and FW would scan all chans which is unexpected in this scenerio. 805 */ 806 if (req->scan_req.chan_list.num_chan == 1) 807 return; 808 809 /* do this only for STA and P2P-CLI mode */ 810 if ((!(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_STA_MODE) && 811 !(wlan_vdev_mlme_get_opmode(req->vdev) == QDF_P2P_CLIENT_MODE)) && 812 !p2p_search) 813 skip_dfs_ch = false; 814 815 if ((scan_obj->scan_def.allow_dfs_chan_in_scan && 816 (scan_obj->scan_def.allow_dfs_chan_in_first_scan || 817 first_scan_done)) && 818 !(scan_obj->scan_def.skip_dfs_chan_in_p2p_search && p2p_search)) 819 skip_dfs_ch = false; 820 821 for (i = 0; i < req->scan_req.chan_list.num_chan; i++) { 822 uint32_t freq; 823 824 freq = req->scan_req.chan_list.chan[i].freq; 825 if (skip_dfs_ch && 826 wlan_reg_is_dfs_ch(pdev, wlan_reg_freq_to_chan(pdev, freq))) 827 continue; 828 if (utils_dfs_is_freq_in_nol(pdev, freq)) 829 continue; 830 req->scan_req.chan_list.chan[num_scan_channels++] = 831 req->scan_req.chan_list.chan[i]; 832 } 833 req->scan_req.chan_list.num_chan = num_scan_channels; 834 } 835 836 /** 837 * scm_scan_req_update_params() - update scan req params depending on modes 838 * and scan type. 839 * @vdev: vdev object pointer 840 * @req: scan request 841 * @scan_obj: scan object 842 * 843 * Return: void 844 */ 845 static void 846 scm_scan_req_update_params(struct wlan_objmgr_vdev *vdev, 847 struct scan_start_request *req, 848 struct wlan_scan_obj *scan_obj) 849 { 850 struct chan_list *custom_chan_list; 851 struct wlan_objmgr_pdev *pdev; 852 uint8_t pdev_id; 853 854 /* Ensure correct number of probes are sent on active channel */ 855 if (!req->scan_req.repeat_probe_time) 856 req->scan_req.repeat_probe_time = 857 req->scan_req.dwell_time_active / SCAN_NPROBES_DEFAULT; 858 859 if (req->scan_req.scan_f_passive) 860 req->scan_req.scan_ctrl_flags_ext |= 861 SCAN_FLAG_EXT_FILTER_PUBLIC_ACTION_FRAME; 862 863 if (!req->scan_req.n_probes) 864 req->scan_req.n_probes = (req->scan_req.repeat_probe_time > 0) ? 865 req->scan_req.dwell_time_active / 866 req->scan_req.repeat_probe_time : 0; 867 868 if (req->scan_req.scan_type == SCAN_TYPE_P2P_SEARCH || 869 req->scan_req.scan_type == SCAN_TYPE_P2P_LISTEN) { 870 req->scan_req.adaptive_dwell_time_mode = SCAN_DWELL_MODE_STATIC; 871 req->scan_req.dwell_time_active_2g = 0; 872 if (req->scan_req.scan_type == SCAN_TYPE_P2P_LISTEN) { 873 req->scan_req.repeat_probe_time = 0; 874 } else { 875 req->scan_req.scan_f_filter_prb_req = true; 876 if (!req->scan_req.num_ssids) 877 req->scan_req.scan_f_bcast_probe = true; 878 879 req->scan_req.dwell_time_active += 880 P2P_SEARCH_DWELL_TIME_INC; 881 /* 882 * 3 channels with default max dwell time 40 ms. 883 * Cap limit will be set by 884 * P2P_SCAN_MAX_BURST_DURATION. Burst duration 885 * should be such that no channel is scanned less 886 * than the dwell time in normal scenarios. 887 */ 888 if (req->scan_req.chan_list.num_chan == 889 WLAN_P2P_SOCIAL_CHANNELS && 890 !scan_obj->miracast_enabled) 891 req->scan_req.repeat_probe_time = 892 req->scan_req.dwell_time_active / 5; 893 else 894 req->scan_req.repeat_probe_time = 895 req->scan_req.dwell_time_active / 3; 896 if (scan_obj->scan_def.p2p_scan_burst_duration) { 897 req->scan_req.burst_duration = 898 scan_obj->scan_def. 899 p2p_scan_burst_duration; 900 } else { 901 req->scan_req.burst_duration = 902 BURST_SCAN_MAX_NUM_OFFCHANNELS * 903 req->scan_req.dwell_time_active; 904 if (req->scan_req.burst_duration > 905 P2P_SCAN_MAX_BURST_DURATION) { 906 uint8_t channels = 907 P2P_SCAN_MAX_BURST_DURATION / 908 req->scan_req.dwell_time_active; 909 if (channels) 910 req->scan_req.burst_duration = 911 channels * 912 req->scan_req.dwell_time_active; 913 else 914 req->scan_req.burst_duration = 915 P2P_SCAN_MAX_BURST_DURATION; 916 } 917 } 918 req->scan_req.scan_ev_bss_chan = false; 919 } 920 } else { 921 req->scan_req.scan_f_cck_rates = true; 922 if (!req->scan_req.num_ssids) 923 req->scan_req.scan_f_bcast_probe = true; 924 req->scan_req.scan_f_add_ds_ie_in_probe = true; 925 req->scan_req.scan_f_filter_prb_req = true; 926 req->scan_req.scan_f_add_tpc_ie_in_probe = true; 927 } 928 929 scm_update_dbs_scan_ctrl_ext_flag(req); 930 931 /* 932 * No need to update conncurrency parmas if req is passive scan on 933 * single channel ie ROC, Preauth etc 934 */ 935 if (!(req->scan_req.scan_f_passive && 936 req->scan_req.chan_list.num_chan == 1) && 937 req->scan_req.scan_type != SCAN_TYPE_RRM) 938 scm_req_update_concurrency_params(vdev, req, scan_obj); 939 940 /* 941 * Set wide band flag if enabled. This will cause 942 * phymode TLV being sent to FW. 943 */ 944 pdev = wlan_vdev_get_pdev(vdev); 945 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 946 if (ucfg_scan_get_wide_band_scan(pdev)) 947 req->scan_req.scan_f_wide_band = true; 948 else 949 req->scan_req.scan_f_wide_band = false; 950 951 /* 952 * Overwrite scan channles with custom scan channel 953 * list if configured. 954 */ 955 custom_chan_list = &scan_obj->pdev_info[pdev_id].custom_chan_list; 956 if (custom_chan_list->num_chan) 957 qdf_mem_copy(&req->scan_req.chan_list, custom_chan_list, 958 sizeof(struct chan_list)); 959 else if (!req->scan_req.chan_list.num_chan) 960 ucfg_scan_init_chanlist_params(req, 0, NULL, NULL); 961 962 scm_update_channel_list(req, scan_obj); 963 scm_debug("dwell time: active %d, passive %d, repeat_probe_time %d n_probes %d flags_ext %x, wide_bw_scan: %d priority: %d", 964 req->scan_req.dwell_time_active, 965 req->scan_req.dwell_time_passive, 966 req->scan_req.repeat_probe_time, req->scan_req.n_probes, 967 req->scan_req.scan_ctrl_flags_ext, 968 req->scan_req.scan_f_wide_band, 969 req->scan_req.scan_priority); 970 } 971 972 QDF_STATUS 973 scm_scan_start_req(struct scheduler_msg *msg) 974 { 975 struct wlan_serialization_command cmd = {0, }; 976 enum wlan_serialization_status ser_cmd_status; 977 struct scan_start_request *req = NULL; 978 struct wlan_scan_obj *scan_obj; 979 QDF_STATUS status = QDF_STATUS_SUCCESS; 980 uint8_t idx; 981 982 if (!msg) { 983 scm_err("msg received is NULL"); 984 QDF_ASSERT(0); 985 return QDF_STATUS_E_NULL_VALUE; 986 } 987 if (!msg->bodyptr) { 988 scm_err("bodyptr is NULL"); 989 QDF_ASSERT(0); 990 return QDF_STATUS_E_NULL_VALUE; 991 } 992 993 req = msg->bodyptr; 994 995 if (!scm_is_scan_allowed(req->vdev)) { 996 scm_err("scan disabled, rejecting the scan req"); 997 status = QDF_STATUS_E_NULL_VALUE; 998 goto err; 999 } 1000 1001 scan_obj = wlan_vdev_get_scan_obj(req->vdev); 1002 if (!scan_obj) { 1003 scm_debug("Couldn't find scan object"); 1004 status = QDF_STATUS_E_NULL_VALUE; 1005 goto err; 1006 } 1007 1008 scm_scan_req_update_params(req->vdev, req, scan_obj); 1009 1010 if (!req->scan_req.chan_list.num_chan) { 1011 scm_err("Scan Aborted, 0 channel to scan"); 1012 status = QDF_STATUS_E_NULL_VALUE; 1013 goto err; 1014 } 1015 1016 scm_info("request to scan %d channels", 1017 req->scan_req.chan_list.num_chan); 1018 1019 for (idx = 0; idx < req->scan_req.chan_list.num_chan; idx++) 1020 scm_debug("chan[%d]: freq:%d, phymode:%d", idx, 1021 req->scan_req.chan_list.chan[idx].freq, 1022 req->scan_req.chan_list.chan[idx].phymode); 1023 1024 cmd.cmd_type = WLAN_SER_CMD_SCAN; 1025 cmd.cmd_id = req->scan_req.scan_id; 1026 cmd.cmd_cb = scm_scan_serialize_callback; 1027 cmd.umac_cmd = req; 1028 cmd.source = WLAN_UMAC_COMP_SCAN; 1029 cmd.is_high_priority = false; 1030 cmd.cmd_timeout_duration = req->scan_req.max_scan_time + 1031 SCAN_TIMEOUT_GRACE_PERIOD; 1032 cmd.vdev = req->vdev; 1033 1034 if (scan_obj->disable_timeout) 1035 cmd.cmd_timeout_duration = 0; 1036 1037 scm_debug("req: 0x%pK, reqid: %d, scanid: %d, vdevid: %d", 1038 req, req->scan_req.scan_req_id, req->scan_req.scan_id, 1039 req->scan_req.vdev_id); 1040 1041 qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SERIALIZATION, 1042 WLAN_SER_CMD_SCAN, req->vdev->vdev_objmgr.vdev_id, 1043 req->scan_req.scan_id); 1044 1045 ser_cmd_status = wlan_serialization_request(&cmd); 1046 scm_debug("wlan_serialization_request status:%d", ser_cmd_status); 1047 1048 switch (ser_cmd_status) { 1049 case WLAN_SER_CMD_PENDING: 1050 /* command moved to pending list.Do nothing */ 1051 break; 1052 case WLAN_SER_CMD_ACTIVE: 1053 /* command moved to active list. Do nothing */ 1054 break; 1055 case WLAN_SER_CMD_DENIED_LIST_FULL: 1056 case WLAN_SER_CMD_DENIED_RULES_FAILED: 1057 case WLAN_SER_CMD_DENIED_UNSPECIFIED: 1058 goto err; 1059 default: 1060 QDF_ASSERT(0); 1061 status = QDF_STATUS_E_INVAL; 1062 goto err; 1063 } 1064 1065 return status; 1066 err: 1067 /* 1068 * notify registered scan event handlers 1069 * about internal error 1070 */ 1071 scm_post_internal_scan_complete_event(req, 1072 SCAN_REASON_INTERNAL_FAILURE); 1073 /* 1074 * cmd can't be serviced. 1075 * release vdev reference and free scan_start_request memory 1076 */ 1077 if (req) { 1078 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 1079 scm_scan_free_scan_request_mem(req); 1080 } 1081 1082 return status; 1083 } 1084 1085 static inline enum wlan_serialization_cancel_type 1086 get_serialization_cancel_type(enum scan_cancel_req_type type) 1087 { 1088 enum wlan_serialization_cancel_type serialization_type; 1089 1090 switch (type) { 1091 case WLAN_SCAN_CANCEL_SINGLE: 1092 serialization_type = WLAN_SER_CANCEL_SINGLE_SCAN; 1093 break; 1094 case WLAN_SCAN_CANCEL_VDEV_ALL: 1095 serialization_type = WLAN_SER_CANCEL_VDEV_SCANS; 1096 break; 1097 case WLAN_SCAN_CANCEL_PDEV_ALL: 1098 serialization_type = WLAN_SER_CANCEL_PDEV_SCANS; 1099 break; 1100 default: 1101 QDF_ASSERT(0); 1102 scm_warn("invalid scan_cancel_req_type: %d", type); 1103 serialization_type = WLAN_SER_CANCEL_PDEV_SCANS; 1104 break; 1105 } 1106 1107 return serialization_type; 1108 } 1109 1110 QDF_STATUS 1111 scm_scan_cancel_req(struct scheduler_msg *msg) 1112 { 1113 struct wlan_serialization_queued_cmd_info cmd = {0,}; 1114 struct wlan_serialization_command ser_cmd = {0,}; 1115 enum wlan_serialization_cmd_status ser_cmd_status; 1116 struct scan_cancel_request *req; 1117 QDF_STATUS status = QDF_STATUS_SUCCESS; 1118 1119 if (!msg) { 1120 scm_err("msg received is NULL"); 1121 QDF_ASSERT(0); 1122 return QDF_STATUS_E_NULL_VALUE; 1123 } 1124 if (!msg->bodyptr) { 1125 scm_err("Bodyptr is NULL"); 1126 QDF_ASSERT(0); 1127 return QDF_STATUS_E_NULL_VALUE; 1128 } 1129 1130 req = msg->bodyptr; 1131 /* 1132 * If requester wants to wait for target scan cancel event 1133 * instead of internally generated cancel event, just check 1134 * which queue this scan request belongs to and send scan 1135 * cancel request to FW accordingly. 1136 * Else generate internal scan cancel event and notify 1137 * handlers and free scan request resources. 1138 */ 1139 if (req->wait_tgt_cancel && 1140 (req->cancel_req.req_type == WLAN_SCAN_CANCEL_SINGLE)) { 1141 ser_cmd.cmd_type = WLAN_SER_CMD_SCAN; 1142 ser_cmd.cmd_id = req->cancel_req.scan_id; 1143 ser_cmd.cmd_cb = NULL; 1144 ser_cmd.umac_cmd = NULL; 1145 ser_cmd.source = WLAN_UMAC_COMP_SCAN; 1146 ser_cmd.is_high_priority = false; 1147 ser_cmd.vdev = req->vdev; 1148 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, &ser_cmd)) 1149 ser_cmd_status = WLAN_SER_CMD_IN_ACTIVE_LIST; 1150 else if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, &ser_cmd)) 1151 ser_cmd_status = WLAN_SER_CMD_IN_PENDING_LIST; 1152 else 1153 ser_cmd_status = WLAN_SER_CMD_NOT_FOUND; 1154 } else { 1155 cmd.requestor = 0; 1156 cmd.cmd_type = WLAN_SER_CMD_SCAN; 1157 cmd.cmd_id = req->cancel_req.scan_id; 1158 cmd.vdev = req->vdev; 1159 cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE | 1160 WLAN_SERIALIZATION_PENDING_QUEUE; 1161 cmd.req_type = get_serialization_cancel_type(req->cancel_req.req_type); 1162 1163 ser_cmd_status = wlan_serialization_cancel_request(&cmd); 1164 } 1165 1166 scm_debug("status: %d, reqid: %d, scanid: %d, vdevid: %d, type: %d", 1167 ser_cmd_status, req->cancel_req.requester, 1168 req->cancel_req.scan_id, req->cancel_req.vdev_id, 1169 req->cancel_req.req_type); 1170 1171 switch (ser_cmd_status) { 1172 case WLAN_SER_CMD_IN_PENDING_LIST: 1173 /* do nothing */ 1174 break; 1175 case WLAN_SER_CMD_IN_ACTIVE_LIST: 1176 case WLAN_SER_CMDS_IN_ALL_LISTS: 1177 /* send wmi scan cancel to fw */ 1178 status = tgt_scan_cancel(req); 1179 break; 1180 case WLAN_SER_CMD_NOT_FOUND: 1181 /* do nothing */ 1182 break; 1183 default: 1184 QDF_ASSERT(0); 1185 status = QDF_STATUS_E_INVAL; 1186 break; 1187 } 1188 1189 /* Release vdev reference and scan cancel request 1190 * processing is complete 1191 */ 1192 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 1193 /* Free cancel request memory */ 1194 qdf_mem_free(req); 1195 1196 return status; 1197 } 1198 1199 #ifdef FEATURE_WLAN_SCAN_PNO 1200 static QDF_STATUS 1201 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev, 1202 struct scan_event *event) 1203 { 1204 struct scan_vdev_obj *scan_vdev_obj; 1205 struct wlan_scan_obj *scan_psoc_obj; 1206 scan_event_handler pno_cb; 1207 void *cb_arg; 1208 1209 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 1210 scan_psoc_obj = wlan_vdev_get_scan_obj(vdev); 1211 if (!scan_vdev_obj || !scan_psoc_obj) { 1212 scm_err("null scan_vdev_obj %pK scan_obj %pK", 1213 scan_vdev_obj, scan_psoc_obj); 1214 return QDF_STATUS_E_INVAL; 1215 } 1216 1217 switch (event->type) { 1218 case SCAN_EVENT_TYPE_NLO_COMPLETE: 1219 if (!scan_vdev_obj->pno_match_evt_received) 1220 return QDF_STATUS_SUCCESS; 1221 qdf_wake_lock_release(&scan_psoc_obj->pno_cfg.pno_wake_lock, 1222 WIFI_POWER_EVENT_WAKELOCK_PNO); 1223 qdf_wake_lock_timeout_acquire( 1224 &scan_psoc_obj->pno_cfg.pno_wake_lock, 1225 SCAN_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT); 1226 scan_vdev_obj->pno_match_evt_received = false; 1227 break; 1228 case SCAN_EVENT_TYPE_NLO_MATCH: 1229 scan_vdev_obj->pno_match_evt_received = true; 1230 qdf_wake_lock_timeout_acquire( 1231 &scan_psoc_obj->pno_cfg.pno_wake_lock, 1232 SCAN_PNO_MATCH_WAKE_LOCK_TIMEOUT); 1233 return QDF_STATUS_SUCCESS; 1234 default: 1235 return QDF_STATUS_E_INVAL; 1236 } 1237 qdf_spin_lock_bh(&scan_psoc_obj->lock); 1238 pno_cb = scan_psoc_obj->pno_cfg.pno_cb.func; 1239 cb_arg = scan_psoc_obj->pno_cfg.pno_cb.arg; 1240 qdf_spin_unlock_bh(&scan_psoc_obj->lock); 1241 1242 if (pno_cb) 1243 pno_cb(vdev, event, cb_arg); 1244 1245 return QDF_STATUS_SUCCESS; 1246 } 1247 #else 1248 1249 static QDF_STATUS 1250 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev, 1251 struct scan_event *event) 1252 { 1253 return QDF_STATUS_SUCCESS; 1254 } 1255 #endif 1256 1257 /** 1258 * scm_scan_update_scan_event() - update scan event 1259 * @scan: scan object 1260 * @event: scan event 1261 * @scan_start_req: scan_start_req used for triggering scan 1262 * 1263 * update scan params in scan event 1264 * 1265 * Return: QDF_STATUS 1266 */ 1267 static QDF_STATUS 1268 scm_scan_update_scan_event(struct wlan_scan_obj *scan, 1269 struct scan_event *event, 1270 struct scan_start_request *scan_start_req) 1271 { 1272 if (!event) 1273 return QDF_STATUS_E_NULL_VALUE; 1274 1275 if (!scan || !scan_start_req) { 1276 event->scan_start_req = NULL; 1277 return QDF_STATUS_E_NULL_VALUE; 1278 } 1279 /* copy scan start request to pass back buffer */ 1280 qdf_mem_copy(&scan->scan_start_request_buff, scan_start_req, 1281 sizeof(struct scan_start_request)); 1282 /* reset all pointers */ 1283 scan->scan_start_request_buff.scan_req.extraie.ptr = NULL; 1284 scan->scan_start_request_buff.scan_req.extraie.len = 0; 1285 scan->scan_start_request_buff.scan_req.htcap.ptr = NULL; 1286 scan->scan_start_request_buff.scan_req.htcap.len = 0; 1287 scan->scan_start_request_buff.scan_req.vhtcap.ptr = NULL; 1288 scan->scan_start_request_buff.scan_req.vhtcap.len = 0; 1289 1290 event->scan_start_req = &scan->scan_start_request_buff; 1291 1292 return QDF_STATUS_SUCCESS; 1293 } 1294 1295 QDF_STATUS 1296 scm_scan_event_handler(struct scheduler_msg *msg) 1297 { 1298 struct wlan_objmgr_vdev *vdev; 1299 struct scan_event *event; 1300 struct scan_event_info *event_info; 1301 struct wlan_serialization_command cmd = {0,}; 1302 struct wlan_serialization_command *queued_cmd; 1303 struct scan_start_request *scan_start_req; 1304 struct wlan_scan_obj *scan; 1305 1306 if (!msg) { 1307 scm_err("NULL msg received "); 1308 QDF_ASSERT(0); 1309 return QDF_STATUS_E_NULL_VALUE; 1310 } 1311 if (!msg->bodyptr) { 1312 scm_err("NULL scan event received"); 1313 QDF_ASSERT(0); 1314 return QDF_STATUS_E_NULL_VALUE; 1315 } 1316 1317 event_info = msg->bodyptr; 1318 vdev = event_info->vdev; 1319 event = &(event_info->event); 1320 1321 scm_debug("vdevid:%d, type:%d, reason:%d, freq:%d, reqstr:%d, scanid:%d", 1322 event->vdev_id, event->type, event->reason, event->chan_freq, 1323 event->requester, event->scan_id); 1324 /* 1325 * NLO requests are never queued, so post NLO events 1326 * without checking for their presence in active queue. 1327 */ 1328 switch (event->type) { 1329 case SCAN_EVENT_TYPE_NLO_COMPLETE: 1330 case SCAN_EVENT_TYPE_NLO_MATCH: 1331 scm_pno_event_handler(vdev, event); 1332 goto exit; 1333 default: 1334 break; 1335 } 1336 1337 cmd.cmd_type = WLAN_SER_CMD_SCAN; 1338 cmd.cmd_id = event->scan_id; 1339 cmd.cmd_cb = NULL; 1340 cmd.umac_cmd = NULL; 1341 cmd.source = WLAN_UMAC_COMP_SCAN; 1342 cmd.is_high_priority = false; 1343 cmd.vdev = vdev; 1344 if (!wlan_serialization_is_cmd_present_in_active_queue(NULL, &cmd)) { 1345 /* 1346 * We received scan event for an already completed/cancelled 1347 * scan request. Drop this event. 1348 */ 1349 scm_debug("Received scan event while request not in active queue"); 1350 goto exit; 1351 } 1352 1353 /* Fill scan_start_request used to trigger this scan */ 1354 queued_cmd = wlan_serialization_get_scan_cmd_using_scan_id( 1355 wlan_vdev_get_psoc(vdev), wlan_vdev_get_id(vdev), 1356 event->scan_id, true); 1357 1358 if (!queued_cmd) { 1359 scm_err("NULL queued_cmd"); 1360 goto exit; 1361 } 1362 if (!queued_cmd->umac_cmd) { 1363 scm_err("NULL umac_cmd"); 1364 goto exit; 1365 } 1366 scan_start_req = queued_cmd->umac_cmd; 1367 1368 if (scan_start_req->scan_req.scan_req_id != event->requester) { 1369 scm_err("req ID mismatch, scan_req_id:%d, event_req_id:%d", 1370 scan_start_req->scan_req.scan_req_id, 1371 event->requester); 1372 goto exit; 1373 } 1374 1375 scan = wlan_vdev_get_scan_obj(vdev); 1376 if (scan) 1377 scm_scan_update_scan_event(scan, event, scan_start_req); 1378 1379 switch (event->type) { 1380 case SCAN_EVENT_TYPE_COMPLETED: 1381 if (event->reason == SCAN_REASON_COMPLETED) 1382 scm_11d_decide_country_code(vdev); 1383 /* fall through to release the command */ 1384 case SCAN_EVENT_TYPE_START_FAILED: 1385 case SCAN_EVENT_TYPE_DEQUEUED: 1386 scm_release_serialization_command(vdev, event->scan_id); 1387 break; 1388 default: 1389 break; 1390 } 1391 1392 /* Notify all interested parties */ 1393 scm_scan_post_event(vdev, event); 1394 1395 exit: 1396 /* free event info memory */ 1397 qdf_mem_free(event_info); 1398 wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID); 1399 1400 return QDF_STATUS_SUCCESS; 1401 } 1402 1403 QDF_STATUS scm_scan_event_flush_callback(struct scheduler_msg *msg) 1404 { 1405 struct wlan_objmgr_vdev *vdev; 1406 struct scan_event_info *event_info; 1407 1408 if (!msg || !msg->bodyptr) { 1409 scm_err("msg or msg->bodyptr is NULL"); 1410 return QDF_STATUS_E_NULL_VALUE; 1411 } 1412 1413 event_info = msg->bodyptr; 1414 vdev = event_info->vdev; 1415 1416 /* free event info memory */ 1417 qdf_mem_free(event_info); 1418 wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID); 1419 1420 return QDF_STATUS_SUCCESS; 1421 } 1422 1423 QDF_STATUS scm_bcn_probe_flush_callback(struct scheduler_msg *msg) 1424 { 1425 struct scan_bcn_probe_event *bcn; 1426 1427 bcn = msg->bodyptr; 1428 1429 if (!bcn) { 1430 scm_err("bcn is NULL"); 1431 return QDF_STATUS_E_NULL_VALUE; 1432 } 1433 if (bcn->psoc) 1434 wlan_objmgr_psoc_release_ref(bcn->psoc, WLAN_SCAN_ID); 1435 if (bcn->rx_data) 1436 qdf_mem_free(bcn->rx_data); 1437 if (bcn->buf) 1438 qdf_nbuf_free(bcn->buf); 1439 qdf_mem_free(bcn); 1440 1441 return QDF_STATUS_SUCCESS; 1442 } 1443 1444 QDF_STATUS scm_scan_start_flush_callback(struct scheduler_msg *msg) 1445 { 1446 struct scan_start_request *req; 1447 1448 if (!msg || !msg->bodyptr) { 1449 scm_err("msg or msg->bodyptr is NULL"); 1450 return QDF_STATUS_E_NULL_VALUE; 1451 } 1452 1453 req = msg->bodyptr; 1454 scm_post_internal_scan_complete_event(req, SCAN_REASON_CANCELLED); 1455 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 1456 scm_scan_free_scan_request_mem(req); 1457 1458 return QDF_STATUS_SUCCESS; 1459 } 1460 1461 QDF_STATUS scm_scan_cancel_flush_callback(struct scheduler_msg *msg) 1462 { 1463 struct scan_cancel_request *req; 1464 1465 if (!msg || !msg->bodyptr) { 1466 scm_err("msg or msg->bodyptr is NULL"); 1467 return QDF_STATUS_E_NULL_VALUE; 1468 } 1469 1470 req = msg->bodyptr; 1471 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 1472 /* Free cancel request memory */ 1473 qdf_mem_free(req); 1474 1475 return QDF_STATUS_SUCCESS; 1476 } 1477