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