1 /* 2 * Copyright (c) 2017-2018 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 #ifdef FEATURE_WLAN_SCAN_PNO 30 #include <host_diag_core_event.h> 31 #endif 32 33 QDF_STATUS 34 scm_scan_free_scan_request_mem(struct scan_start_request *req) 35 { 36 void *ie; 37 38 if (!req) { 39 scm_err("null request"); 40 QDF_ASSERT(0); 41 return QDF_STATUS_E_FAILURE; 42 } 43 scm_debug("freed scan request: 0x%pK, scan_id: %d, requester: %d", 44 req, req->scan_req.scan_id, req->scan_req.scan_req_id); 45 /* Free vendor(extra) ie */ 46 ie = req->scan_req.extraie.ptr; 47 if (ie) { 48 req->scan_req.extraie.ptr = NULL; 49 req->scan_req.extraie.len = 0; 50 qdf_mem_free(ie); 51 } 52 53 /* Free htcap ie */ 54 ie = req->scan_req.htcap.ptr; 55 if (ie) { 56 req->scan_req.htcap.len = 0; 57 req->scan_req.htcap.ptr = NULL; 58 qdf_mem_free(ie); 59 } 60 61 /* Free vhtcap ie */ 62 ie = req->scan_req.vhtcap.ptr; 63 if (ie) { 64 req->scan_req.vhtcap.len = 0; 65 req->scan_req.vhtcap.ptr = NULL; 66 qdf_mem_free(ie); 67 } 68 /* free scan_start_request memory */ 69 qdf_mem_free(req); 70 71 return QDF_STATUS_SUCCESS; 72 } 73 74 static QDF_STATUS 75 scm_scan_get_pdev_global_event_handlers(struct scan_event_listeners *listeners, 76 struct pdev_scan_ev_handler *pdev_ev_handler) 77 { 78 uint32_t i; 79 struct cb_handler *cb_handlers = &(pdev_ev_handler->cb_handlers[0]); 80 81 for (i = 0; i < MAX_SCAN_EVENT_HANDLERS_PER_PDEV; i++, cb_handlers++) { 82 if ((cb_handlers->func) && 83 (listeners->count < MAX_SCAN_EVENT_LISTENERS)) { 84 listeners->cb[listeners->count].func = 85 cb_handlers->func; 86 listeners->cb[listeners->count].arg = 87 cb_handlers->arg; 88 listeners->count++; 89 } 90 } 91 92 return QDF_STATUS_SUCCESS; 93 } 94 95 static QDF_STATUS 96 scm_scan_get_requester_event_handler(struct scan_event_listeners *listeners, 97 struct scan_requester_info *requesters, 98 wlan_scan_requester requester_id) 99 { 100 uint32_t idx; 101 struct cb_handler *ev_handler; 102 103 idx = requester_id & WLAN_SCAN_REQUESTER_ID_PREFIX; 104 if (idx != WLAN_SCAN_REQUESTER_ID_PREFIX) 105 return QDF_STATUS_SUCCESS; 106 107 idx = requester_id & WLAN_SCAN_REQUESTER_ID_MASK; 108 if (idx < WLAN_MAX_REQUESTORS) { 109 ev_handler = &(requesters[idx].ev_handler); 110 if (ev_handler->func) { 111 if (listeners->count < MAX_SCAN_EVENT_LISTENERS) { 112 listeners->cb[listeners->count].func = 113 ev_handler->func; 114 listeners->cb[listeners->count].arg = 115 ev_handler->arg; 116 listeners->count++; 117 } 118 } 119 return QDF_STATUS_SUCCESS; 120 } else { 121 scm_err("invalid requester id"); 122 return QDF_STATUS_E_INVAL; 123 } 124 125 } 126 127 static void scm_scan_post_event(struct wlan_objmgr_vdev *vdev, 128 struct scan_event *event) 129 { 130 uint32_t i = 0; 131 struct wlan_scan_obj *scan; 132 struct pdev_scan_ev_handler *pdev_ev_handler; 133 struct cb_handler *cb_handlers; 134 struct scan_requester_info *requesters; 135 struct scan_event_listeners *listeners; 136 137 if (!vdev || !event) { 138 scm_err("vdev: 0x%pK, event: 0x%pK", vdev, event); 139 return; 140 } 141 if (!event->requester) { 142 scm_err("invalid requester id"); 143 QDF_ASSERT(0); 144 } 145 scan = wlan_vdev_get_scan_obj(vdev); 146 pdev_ev_handler = wlan_vdev_get_pdev_scan_ev_handlers(vdev); 147 cb_handlers = &(pdev_ev_handler->cb_handlers[0]); 148 requesters = scan->requesters; 149 150 scm_debug("vdev: %d, type: %d, reason: %d, freq: %d, req: %d, scanid: %d", 151 event->vdev_id, event->type, event->reason, event->chan_freq, 152 event->requester, event->scan_id); 153 154 listeners = qdf_mem_malloc_atomic(sizeof(*listeners)); 155 if (!listeners) { 156 scm_warn("couldn't allocate listeners list"); 157 return; 158 } 159 160 /* initialize number of listeners */ 161 listeners->count = 0; 162 163 /* 164 * Initiator of scan request decides which all scan events 165 * he is interested in and FW will send only those scan events 166 * to host driver. 167 * All the events received by scan module will be notified 168 * to all registered handlers. 169 */ 170 171 qdf_spin_lock_bh(&scan->lock); 172 /* find all global scan event handlers on this pdev */ 173 scm_scan_get_pdev_global_event_handlers(listeners, pdev_ev_handler); 174 /* find owner who triggered this scan request */ 175 scm_scan_get_requester_event_handler(listeners, requesters, 176 event->requester); 177 qdf_spin_unlock_bh(&scan->lock); 178 179 /* notify all interested handlers */ 180 for (i = 0; i < listeners->count; i++) { 181 scm_debug("func: 0x%pK, arg: 0x%pK", 182 listeners->cb[i].func, listeners->cb[i].arg); 183 listeners->cb[i].func(vdev, event, listeners->cb[i].arg); 184 } 185 qdf_mem_free(listeners); 186 } 187 188 static QDF_STATUS 189 scm_release_serialization_command(struct wlan_objmgr_vdev *vdev, 190 uint32_t scan_id) 191 { 192 struct wlan_serialization_queued_cmd_info cmd = {0}; 193 194 cmd.requestor = WLAN_UMAC_COMP_SCAN; 195 cmd.cmd_type = WLAN_SER_CMD_SCAN; 196 cmd.cmd_id = scan_id; 197 cmd.req_type = WLAN_SER_CANCEL_SINGLE_SCAN; 198 cmd.vdev = vdev; 199 cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE; 200 201 /* Inform serialization for command completion */ 202 wlan_serialization_remove_cmd(&cmd); 203 204 return QDF_STATUS_SUCCESS; 205 } 206 207 static QDF_STATUS 208 scm_post_internal_scan_complete_event(struct scan_start_request *req, 209 enum scan_completion_reason reason) 210 { 211 struct scan_event event = {0, }; 212 213 /* prepare internal scan complete event */ 214 event.type = SCAN_EVENT_TYPE_COMPLETED; 215 event.reason = reason; 216 event.chan_freq = 0; /* Invalid frequency */ 217 event.vdev_id = req->scan_req.vdev_id; 218 event.requester = req->scan_req.scan_req_id; 219 event.scan_id = req->scan_req.scan_id; 220 /* Fill scan_start_request used to trigger this scan */ 221 event.scan_start_req = req; 222 /* post scan event to registered handlers */ 223 scm_scan_post_event(req->vdev, &event); 224 225 return QDF_STATUS_SUCCESS; 226 } 227 228 static inline struct pdev_scan_info * 229 scm_scan_get_pdev_priv_info(uint8_t pdev_id, struct wlan_scan_obj *scan_obj) 230 { 231 return &scan_obj->pdev_info[pdev_id]; 232 } 233 234 static QDF_STATUS 235 scm_update_last_scan_time(struct scan_start_request *req) 236 { 237 uint8_t pdev_id; 238 struct wlan_scan_obj *scan_obj; 239 struct pdev_scan_info *pdev_scan_info; 240 241 scan_obj = wlan_vdev_get_scan_obj(req->vdev); 242 pdev_id = wlan_scan_vdev_get_pdev_id(req->vdev); 243 pdev_scan_info = scm_scan_get_pdev_priv_info(pdev_id, scan_obj); 244 /* update last scan start time */ 245 pdev_scan_info->last_scan_time = qdf_system_ticks(); 246 247 return QDF_STATUS_SUCCESS; 248 } 249 250 static QDF_STATUS 251 scm_activate_scan_request(struct scan_start_request *req) 252 { 253 QDF_STATUS status; 254 255 status = tgt_scan_start(req); 256 if (status != QDF_STATUS_SUCCESS) { 257 scm_err("tgt_scan_start failed, status: %d", status); 258 /* scan could not be started and hence 259 * we will not receive any completions. 260 * post scan cancelled 261 */ 262 scm_post_internal_scan_complete_event(req, 263 SCAN_REASON_CANCELLED); 264 return status; 265 } 266 /* save last scan start time */ 267 status = scm_update_last_scan_time(req); 268 269 return status; 270 } 271 272 static QDF_STATUS 273 scm_cancel_scan_request(struct scan_start_request *req) 274 { 275 struct scan_cancel_request cancel_req = {0, }; 276 QDF_STATUS status; 277 278 cancel_req.vdev = req->vdev; 279 cancel_req.cancel_req.scan_id = req->scan_req.scan_id; 280 cancel_req.cancel_req.requester = req->scan_req.scan_req_id; 281 cancel_req.cancel_req.req_type = WLAN_SCAN_CANCEL_SINGLE; 282 cancel_req.cancel_req.vdev_id = req->scan_req.vdev_id; 283 /* send scan cancel to fw */ 284 status = tgt_scan_cancel(&cancel_req); 285 if (status != QDF_STATUS_SUCCESS) 286 scm_err("tgt_scan_cancel failed: status: %d, scanid: %d", 287 status, req->scan_req.scan_id); 288 /* notify event handler about scan cancellation */ 289 scm_post_internal_scan_complete_event(req, SCAN_REASON_CANCELLED); 290 291 return status; 292 } 293 294 static QDF_STATUS 295 scm_scan_serialize_callback(struct wlan_serialization_command *cmd, 296 enum wlan_serialization_cb_reason reason) 297 { 298 struct scan_start_request *req; 299 QDF_STATUS status; 300 301 if (!cmd) { 302 scm_err("cmd is NULL, reason: %d", reason); 303 QDF_ASSERT(0); 304 return QDF_STATUS_E_NULL_VALUE; 305 } 306 307 if (!cmd->umac_cmd) { 308 scm_err("cmd->umac_cmd is NULL , reason: %d", reason); 309 QDF_ASSERT(0); 310 return QDF_STATUS_E_NULL_VALUE; 311 } 312 313 req = cmd->umac_cmd; 314 scm_debug("reason:%d, reqid:%d, scanid:%d, vdevid:%d, vdev:0x%pK", 315 reason, req->scan_req.scan_req_id, req->scan_req.scan_id, 316 req->scan_req.vdev_id, req->vdev); 317 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 QDF_STATUS 409 scm_scan_start_req(struct scheduler_msg *msg) 410 { 411 struct wlan_serialization_command cmd = {0, }; 412 enum wlan_serialization_status ser_cmd_status; 413 struct scan_start_request *req = NULL; 414 struct wlan_scan_obj *scan_obj; 415 QDF_STATUS status = QDF_STATUS_SUCCESS; 416 417 if (!msg) { 418 scm_err("msg received is NULL"); 419 QDF_ASSERT(0); 420 return QDF_STATUS_E_NULL_VALUE; 421 } 422 if (!msg->bodyptr) { 423 scm_err("bodyptr is NULL"); 424 QDF_ASSERT(0); 425 return QDF_STATUS_E_NULL_VALUE; 426 } 427 428 req = msg->bodyptr; 429 430 if (!scm_is_scan_allowed(req->vdev)) { 431 scm_err("scan disabled, rejecting the scan req"); 432 status = QDF_STATUS_E_NULL_VALUE; 433 goto err; 434 } 435 436 scan_obj = wlan_vdev_get_scan_obj(req->vdev); 437 if (!scan_obj) { 438 scm_debug("Couldn't find scan object"); 439 status = QDF_STATUS_E_NULL_VALUE; 440 goto err; 441 } 442 443 cmd.cmd_type = WLAN_SER_CMD_SCAN; 444 cmd.cmd_id = req->scan_req.scan_id; 445 cmd.cmd_cb = (wlan_serialization_cmd_callback) 446 scm_scan_serialize_callback; 447 cmd.umac_cmd = req; 448 cmd.source = WLAN_UMAC_COMP_SCAN; 449 cmd.is_high_priority = false; 450 cmd.cmd_timeout_duration = req->scan_req.max_scan_time + 451 SCAN_TIMEOUT_GRACE_PERIOD; 452 cmd.vdev = req->vdev; 453 454 if (scan_obj->disable_timeout) 455 cmd.cmd_timeout_duration = 0; 456 457 scm_debug("req: 0x%pK, reqid: %d, scanid: %d, vdevid: %d", 458 req, req->scan_req.scan_req_id, req->scan_req.scan_id, 459 req->scan_req.vdev_id); 460 461 qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_SERIALIZATION, 462 WLAN_SER_CMD_SCAN, req->vdev->vdev_objmgr.vdev_id, 463 req->scan_req.scan_id); 464 465 ser_cmd_status = wlan_serialization_request(&cmd); 466 scm_debug("wlan_serialization_request status:%d", ser_cmd_status); 467 468 switch (ser_cmd_status) { 469 case WLAN_SER_CMD_PENDING: 470 /* command moved to pending list.Do nothing */ 471 break; 472 case WLAN_SER_CMD_ACTIVE: 473 /* command moved to active list. Do nothing */ 474 break; 475 case WLAN_SER_CMD_DENIED_LIST_FULL: 476 case WLAN_SER_CMD_DENIED_RULES_FAILED: 477 case WLAN_SER_CMD_DENIED_UNSPECIFIED: 478 goto err; 479 default: 480 QDF_ASSERT(0); 481 status = QDF_STATUS_E_INVAL; 482 goto err; 483 } 484 485 return status; 486 err: 487 /* 488 * notify registered scan event handlers 489 * about internal error 490 */ 491 scm_post_internal_scan_complete_event(req, 492 SCAN_REASON_INTERNAL_FAILURE); 493 /* 494 * cmd can't be serviced. 495 * release vdev reference and free scan_start_request memory 496 */ 497 if (req) { 498 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 499 scm_scan_free_scan_request_mem(req); 500 } 501 502 return status; 503 } 504 505 static inline enum wlan_serialization_cancel_type 506 get_serialization_cancel_type(enum scan_cancel_req_type type) 507 { 508 enum wlan_serialization_cancel_type serialization_type; 509 510 switch (type) { 511 case WLAN_SCAN_CANCEL_SINGLE: 512 serialization_type = WLAN_SER_CANCEL_SINGLE_SCAN; 513 break; 514 case WLAN_SCAN_CANCEL_VDEV_ALL: 515 serialization_type = WLAN_SER_CANCEL_VDEV_SCANS; 516 break; 517 case WLAN_SCAN_CANCEL_PDEV_ALL: 518 serialization_type = WLAN_SER_CANCEL_PDEV_SCANS; 519 break; 520 default: 521 QDF_ASSERT(0); 522 scm_warn("invalid scan_cancel_req_type: %d", type); 523 serialization_type = WLAN_SER_CANCEL_PDEV_SCANS; 524 break; 525 } 526 527 return serialization_type; 528 } 529 530 QDF_STATUS 531 scm_scan_cancel_req(struct scheduler_msg *msg) 532 { 533 struct wlan_serialization_queued_cmd_info cmd = {0,}; 534 struct wlan_serialization_command ser_cmd = {0,}; 535 enum wlan_serialization_cmd_status ser_cmd_status; 536 struct scan_cancel_request *req; 537 QDF_STATUS status = QDF_STATUS_SUCCESS; 538 539 if (!msg) { 540 scm_err("msg received is NULL"); 541 QDF_ASSERT(0); 542 return QDF_STATUS_E_NULL_VALUE; 543 } 544 if (!msg->bodyptr) { 545 scm_err("Bodyptr is NULL"); 546 QDF_ASSERT(0); 547 return QDF_STATUS_E_NULL_VALUE; 548 } 549 550 req = msg->bodyptr; 551 /* 552 * If requester wants to wait for target scan cancel event 553 * instead of internally generated cancel event, just check 554 * which queue this scan request belongs to and send scan 555 * cancel request to FW accordingly. 556 * Else generate internal scan cancel event and notify 557 * handlers and free scan request resources. 558 */ 559 if (req->wait_tgt_cancel && 560 (req->cancel_req.req_type == WLAN_SCAN_CANCEL_SINGLE)) { 561 ser_cmd.cmd_type = WLAN_SER_CMD_SCAN; 562 ser_cmd.cmd_id = req->cancel_req.scan_id; 563 ser_cmd.cmd_cb = NULL; 564 ser_cmd.umac_cmd = NULL; 565 ser_cmd.source = WLAN_UMAC_COMP_SCAN; 566 ser_cmd.is_high_priority = false; 567 ser_cmd.vdev = req->vdev; 568 if (wlan_serialization_is_cmd_present_in_active_queue(NULL, &ser_cmd)) 569 ser_cmd_status = WLAN_SER_CMD_IN_ACTIVE_LIST; 570 else if (wlan_serialization_is_cmd_present_in_pending_queue(NULL, &ser_cmd)) 571 ser_cmd_status = WLAN_SER_CMD_IN_PENDING_LIST; 572 else 573 ser_cmd_status = WLAN_SER_CMD_NOT_FOUND; 574 } else { 575 cmd.requestor = 0; 576 cmd.cmd_type = WLAN_SER_CMD_SCAN; 577 cmd.cmd_id = req->cancel_req.scan_id; 578 cmd.vdev = req->vdev; 579 cmd.queue_type = WLAN_SERIALIZATION_ACTIVE_QUEUE | 580 WLAN_SERIALIZATION_PENDING_QUEUE; 581 cmd.req_type = get_serialization_cancel_type(req->cancel_req.req_type); 582 583 ser_cmd_status = wlan_serialization_cancel_request(&cmd); 584 } 585 586 scm_debug("status: %d, reqid: %d, scanid: %d, vdevid: %d, type: %d", 587 ser_cmd_status, req->cancel_req.requester, 588 req->cancel_req.scan_id, req->cancel_req.vdev_id, 589 req->cancel_req.req_type); 590 591 switch (ser_cmd_status) { 592 case WLAN_SER_CMD_IN_PENDING_LIST: 593 /* do nothing */ 594 break; 595 case WLAN_SER_CMD_IN_ACTIVE_LIST: 596 case WLAN_SER_CMDS_IN_ALL_LISTS: 597 /* send wmi scan cancel to fw */ 598 status = tgt_scan_cancel(req); 599 break; 600 case WLAN_SER_CMD_NOT_FOUND: 601 /* do nothing */ 602 break; 603 default: 604 QDF_ASSERT(0); 605 status = QDF_STATUS_E_INVAL; 606 break; 607 } 608 609 /* Release vdev reference and scan cancel request 610 * processing is complete 611 */ 612 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 613 /* Free cancel request memory */ 614 qdf_mem_free(req); 615 616 return status; 617 } 618 619 #ifdef FEATURE_WLAN_SCAN_PNO 620 static QDF_STATUS 621 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev, 622 struct scan_event *event) 623 { 624 struct scan_vdev_obj *scan_vdev_obj; 625 struct wlan_scan_obj *scan_psoc_obj; 626 scan_event_handler pno_cb; 627 void *cb_arg; 628 629 scan_vdev_obj = wlan_get_vdev_scan_obj(vdev); 630 scan_psoc_obj = wlan_vdev_get_scan_obj(vdev); 631 if (!scan_vdev_obj || !scan_psoc_obj) { 632 scm_err("null scan_vdev_obj %pK scan_obj %pK", 633 scan_vdev_obj, scan_psoc_obj); 634 return QDF_STATUS_E_INVAL; 635 } 636 637 switch (event->type) { 638 case SCAN_EVENT_TYPE_NLO_COMPLETE: 639 if (!scan_vdev_obj->pno_match_evt_received) 640 return QDF_STATUS_SUCCESS; 641 qdf_wake_lock_release(&scan_psoc_obj->pno_cfg.pno_wake_lock, 642 WIFI_POWER_EVENT_WAKELOCK_PNO); 643 qdf_wake_lock_timeout_acquire( 644 &scan_psoc_obj->pno_cfg.pno_wake_lock, 645 SCAN_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT); 646 scan_vdev_obj->pno_match_evt_received = false; 647 break; 648 case SCAN_EVENT_TYPE_NLO_MATCH: 649 scan_vdev_obj->pno_match_evt_received = true; 650 qdf_wake_lock_timeout_acquire( 651 &scan_psoc_obj->pno_cfg.pno_wake_lock, 652 SCAN_PNO_MATCH_WAKE_LOCK_TIMEOUT); 653 return QDF_STATUS_SUCCESS; 654 default: 655 return QDF_STATUS_E_INVAL; 656 } 657 qdf_spin_lock_bh(&scan_psoc_obj->lock); 658 pno_cb = scan_psoc_obj->pno_cfg.pno_cb.func; 659 cb_arg = scan_psoc_obj->pno_cfg.pno_cb.arg; 660 qdf_spin_unlock_bh(&scan_psoc_obj->lock); 661 662 if (pno_cb) 663 pno_cb(vdev, event, cb_arg); 664 665 return QDF_STATUS_SUCCESS; 666 } 667 #else 668 669 static QDF_STATUS 670 scm_pno_event_handler(struct wlan_objmgr_vdev *vdev, 671 struct scan_event *event) 672 { 673 return QDF_STATUS_SUCCESS; 674 } 675 #endif 676 677 /** 678 * scm_scan_update_scan_event() - update scan event 679 * @scan: scan object 680 * @event: scan event 681 * @scan_start_req: scan_start_req used for triggering scan 682 * 683 * update scan params in scan event 684 * 685 * Return: QDF_STATUS 686 */ 687 static QDF_STATUS 688 scm_scan_update_scan_event(struct wlan_scan_obj *scan, 689 struct scan_event *event, 690 struct scan_start_request *scan_start_req) 691 { 692 if (!event) 693 return QDF_STATUS_E_NULL_VALUE; 694 695 if (!scan || !scan_start_req) { 696 event->scan_start_req = NULL; 697 return QDF_STATUS_E_NULL_VALUE; 698 } 699 /* copy scan start request to pass back buffer */ 700 qdf_mem_copy(&scan->scan_start_request_buff, scan_start_req, 701 sizeof(struct scan_start_request)); 702 /* reset all pointers */ 703 scan->scan_start_request_buff.scan_req.extraie.ptr = NULL; 704 scan->scan_start_request_buff.scan_req.extraie.len = 0; 705 scan->scan_start_request_buff.scan_req.htcap.ptr = NULL; 706 scan->scan_start_request_buff.scan_req.htcap.len = 0; 707 scan->scan_start_request_buff.scan_req.vhtcap.ptr = NULL; 708 scan->scan_start_request_buff.scan_req.vhtcap.len = 0; 709 710 event->scan_start_req = &scan->scan_start_request_buff; 711 712 return QDF_STATUS_SUCCESS; 713 } 714 715 QDF_STATUS 716 scm_scan_event_handler(struct scheduler_msg *msg) 717 { 718 struct wlan_objmgr_vdev *vdev; 719 struct scan_event *event; 720 struct scan_event_info *event_info; 721 struct wlan_serialization_command cmd = {0,}; 722 struct wlan_serialization_command *queued_cmd; 723 struct scan_start_request *scan_start_req; 724 struct wlan_scan_obj *scan; 725 726 if (!msg) { 727 scm_err("NULL msg received "); 728 QDF_ASSERT(0); 729 return QDF_STATUS_E_NULL_VALUE; 730 } 731 if (!msg->bodyptr) { 732 scm_err("NULL scan event received"); 733 QDF_ASSERT(0); 734 return QDF_STATUS_E_NULL_VALUE; 735 } 736 737 event_info = msg->bodyptr; 738 vdev = event_info->vdev; 739 event = &(event_info->event); 740 741 scm_debug("vdevid:%d, type:%d, reason:%d, freq:%d, reqstr:%d, scanid:%d", 742 event->vdev_id, event->type, event->reason, event->chan_freq, 743 event->requester, event->scan_id); 744 /* 745 * NLO requests are never queued, so post NLO events 746 * without checking for their presence in active queue. 747 */ 748 switch (event->type) { 749 case SCAN_EVENT_TYPE_NLO_COMPLETE: 750 case SCAN_EVENT_TYPE_NLO_MATCH: 751 scm_pno_event_handler(vdev, event); 752 goto exit; 753 default: 754 break; 755 } 756 757 cmd.cmd_type = WLAN_SER_CMD_SCAN; 758 cmd.cmd_id = event->scan_id; 759 cmd.cmd_cb = NULL; 760 cmd.umac_cmd = NULL; 761 cmd.source = WLAN_UMAC_COMP_SCAN; 762 cmd.is_high_priority = false; 763 cmd.vdev = vdev; 764 if (!wlan_serialization_is_cmd_present_in_active_queue(NULL, &cmd)) { 765 /* 766 * We received scan event for an already completed/cancelled 767 * scan request. Drop this event. 768 */ 769 scm_debug("Received scan event while request not in active queue"); 770 goto exit; 771 } 772 773 /* Fill scan_start_request used to trigger this scan */ 774 queued_cmd = wlan_serialization_get_scan_cmd_using_scan_id( 775 wlan_vdev_get_psoc(vdev), wlan_vdev_get_id(vdev), 776 event->scan_id, true); 777 778 if (!queued_cmd) { 779 scm_err("NULL queued_cmd"); 780 goto exit; 781 } 782 if (!queued_cmd->umac_cmd) { 783 scm_err("NULL umac_cmd"); 784 goto exit; 785 } 786 scan_start_req = queued_cmd->umac_cmd; 787 788 if (scan_start_req->scan_req.scan_req_id != event->requester) { 789 scm_err("req ID mismatch, scan_req_id:%d, event_req_id:%d", 790 scan_start_req->scan_req.scan_req_id, 791 event->requester); 792 goto exit; 793 } 794 795 scan = wlan_vdev_get_scan_obj(vdev); 796 if (scan) 797 scm_scan_update_scan_event(scan, event, scan_start_req); 798 799 switch (event->type) { 800 case SCAN_EVENT_TYPE_COMPLETED: 801 if (event->reason == SCAN_REASON_COMPLETED) 802 scm_11d_decide_country_code(vdev); 803 /* fall through to release the command */ 804 case SCAN_EVENT_TYPE_START_FAILED: 805 case SCAN_EVENT_TYPE_DEQUEUED: 806 scm_release_serialization_command(vdev, event->scan_id); 807 break; 808 default: 809 break; 810 } 811 812 /* Notify all interested parties */ 813 scm_scan_post_event(vdev, event); 814 815 exit: 816 /* free event info memory */ 817 qdf_mem_free(event_info); 818 wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID); 819 820 return QDF_STATUS_SUCCESS; 821 } 822 823 QDF_STATUS scm_scan_event_flush_callback(struct scheduler_msg *msg) 824 { 825 struct wlan_objmgr_vdev *vdev; 826 struct scan_event_info *event_info; 827 828 if (!msg || !msg->bodyptr) { 829 scm_err("msg or msg->bodyptr is NULL"); 830 return QDF_STATUS_E_NULL_VALUE; 831 } 832 833 event_info = msg->bodyptr; 834 vdev = event_info->vdev; 835 836 /* free event info memory */ 837 qdf_mem_free(event_info); 838 wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID); 839 840 return QDF_STATUS_SUCCESS; 841 } 842 843 QDF_STATUS scm_bcn_probe_flush_callback(struct scheduler_msg *msg) 844 { 845 struct scan_bcn_probe_event *bcn; 846 847 bcn = msg->bodyptr; 848 849 if (!bcn) { 850 scm_err("bcn is NULL"); 851 return QDF_STATUS_E_NULL_VALUE; 852 } 853 if (bcn->psoc) 854 wlan_objmgr_psoc_release_ref(bcn->psoc, WLAN_SCAN_ID); 855 if (bcn->rx_data) 856 qdf_mem_free(bcn->rx_data); 857 if (bcn->buf) 858 qdf_nbuf_free(bcn->buf); 859 qdf_mem_free(bcn); 860 861 return QDF_STATUS_SUCCESS; 862 } 863 864 QDF_STATUS scm_scan_start_flush_callback(struct scheduler_msg *msg) 865 { 866 struct scan_start_request *req; 867 868 if (!msg || !msg->bodyptr) { 869 scm_err("msg or msg->bodyptr is NULL"); 870 return QDF_STATUS_E_NULL_VALUE; 871 } 872 873 req = msg->bodyptr; 874 scm_post_internal_scan_complete_event(req, SCAN_REASON_CANCELLED); 875 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 876 scm_scan_free_scan_request_mem(req); 877 878 return QDF_STATUS_SUCCESS; 879 } 880 881 QDF_STATUS scm_scan_cancel_flush_callback(struct scheduler_msg *msg) 882 { 883 struct scan_cancel_request *req; 884 885 if (!msg || !msg->bodyptr) { 886 scm_err("msg or msg->bodyptr is NULL"); 887 return QDF_STATUS_E_NULL_VALUE; 888 } 889 890 req = msg->bodyptr; 891 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 892 /* Free cancel request memory */ 893 qdf_mem_free(req); 894 895 return QDF_STATUS_SUCCESS; 896 } 897