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