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