1 /* 2 * Copyright (c) 2017-2021 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: This file contains all SCAN component's APIs 21 */ 22 23 #include "cfg_ucfg_api.h" 24 #include "wlan_scan_api.h" 25 #include "../../core/src/wlan_scan_manager.h" 26 #ifdef WLAN_POLICY_MGR_ENABLE 27 #include <wlan_policy_mgr_api.h> 28 #include "wlan_policy_mgr_public_struct.h" 29 #endif 30 31 void wlan_scan_cfg_get_passive_dwelltime(struct wlan_objmgr_psoc *psoc, 32 uint32_t *dwell_time) 33 { 34 struct wlan_scan_obj *scan_obj; 35 36 scan_obj = wlan_psoc_get_scan_obj(psoc); 37 if (!scan_obj) 38 return; 39 *dwell_time = scan_obj->scan_def.passive_dwell; 40 } 41 42 void wlan_scan_cfg_set_passive_dwelltime(struct wlan_objmgr_psoc *psoc, 43 uint32_t dwell_time) 44 { 45 struct wlan_scan_obj *scan_obj; 46 47 scan_obj = wlan_psoc_get_scan_obj(psoc); 48 if (!scan_obj) 49 return; 50 scan_obj->scan_def.passive_dwell = dwell_time; 51 } 52 53 void wlan_scan_cfg_get_active_dwelltime(struct wlan_objmgr_psoc *psoc, 54 uint32_t *dwell_time) 55 { 56 struct wlan_scan_obj *scan_obj; 57 58 scan_obj = wlan_psoc_get_scan_obj(psoc); 59 if (!scan_obj) 60 return; 61 *dwell_time = scan_obj->scan_def.active_dwell; 62 } 63 64 void wlan_scan_cfg_set_active_dwelltime(struct wlan_objmgr_psoc *psoc, 65 uint32_t dwell_time) 66 { 67 struct wlan_scan_obj *scan_obj; 68 69 scan_obj = wlan_psoc_get_scan_obj(psoc); 70 if (!scan_obj) 71 return; 72 scan_obj->scan_def.active_dwell = dwell_time; 73 } 74 75 void wlan_scan_cfg_get_active_2g_dwelltime(struct wlan_objmgr_psoc *psoc, 76 uint32_t *dwell_time) 77 { 78 struct wlan_scan_obj *scan_obj; 79 80 scan_obj = wlan_psoc_get_scan_obj(psoc); 81 if (!scan_obj) 82 return; 83 84 *dwell_time = scan_obj->scan_def.active_dwell_2g; 85 } 86 87 void wlan_scan_cfg_set_active_2g_dwelltime(struct wlan_objmgr_psoc *psoc, 88 uint32_t dwell_time) 89 { 90 struct wlan_scan_obj *scan_obj; 91 92 scan_obj = wlan_psoc_get_scan_obj(psoc); 93 if (!scan_obj) 94 return; 95 scan_obj->scan_def.active_dwell_2g = dwell_time; 96 } 97 98 #ifdef CONFIG_BAND_6GHZ 99 QDF_STATUS wlan_scan_cfg_get_active_6g_dwelltime(struct wlan_objmgr_psoc *psoc, 100 uint32_t *dwell_time) 101 { 102 struct wlan_scan_obj *scan_obj; 103 104 scan_obj = wlan_psoc_get_scan_obj(psoc); 105 if (!scan_obj) 106 return QDF_STATUS_E_INVAL; 107 108 *dwell_time = scan_obj->scan_def.active_dwell_6g; 109 110 return QDF_STATUS_SUCCESS; 111 } 112 113 QDF_STATUS wlan_scan_cfg_set_active_6g_dwelltime(struct wlan_objmgr_psoc *psoc, 114 uint32_t dwell_time) 115 { 116 struct wlan_scan_obj *scan_obj; 117 118 scan_obj = wlan_psoc_get_scan_obj(psoc); 119 if (!scan_obj) 120 return QDF_STATUS_E_INVAL; 121 122 scan_obj->scan_def.active_dwell_6g = dwell_time; 123 124 return QDF_STATUS_SUCCESS; 125 } 126 127 QDF_STATUS wlan_scan_cfg_get_passive_6g_dwelltime(struct wlan_objmgr_psoc *psoc, 128 uint32_t *dwell_time) 129 { 130 struct wlan_scan_obj *scan_obj; 131 132 scan_obj = wlan_psoc_get_scan_obj(psoc); 133 if (!scan_obj) 134 return QDF_STATUS_E_INVAL; 135 136 *dwell_time = scan_obj->scan_def.passive_dwell_6g; 137 138 return QDF_STATUS_SUCCESS; 139 } 140 141 QDF_STATUS wlan_scan_cfg_set_passive_6g_dwelltime(struct wlan_objmgr_psoc *psoc, 142 uint32_t dwell_time) 143 { 144 struct wlan_scan_obj *scan_obj; 145 146 scan_obj = wlan_psoc_get_scan_obj(psoc); 147 if (!scan_obj) 148 return QDF_STATUS_E_INVAL; 149 150 scan_obj->scan_def.passive_dwell_6g = dwell_time; 151 152 return QDF_STATUS_SUCCESS; 153 } 154 #endif 155 156 #ifdef WLAN_POLICY_MGR_ENABLE 157 void wlan_scan_update_pno_dwell_time(struct wlan_objmgr_vdev *vdev, 158 struct pno_scan_req_params *req, 159 struct scan_default_params *scan_def) 160 { 161 bool sap_or_p2p_present; 162 struct wlan_objmgr_psoc *psoc; 163 164 psoc = wlan_vdev_get_psoc(vdev); 165 166 if (!psoc) 167 return; 168 169 sap_or_p2p_present = policy_mgr_mode_specific_connection_count 170 (psoc, 171 PM_SAP_MODE, NULL) || 172 policy_mgr_mode_specific_connection_count 173 (psoc, 174 PM_P2P_GO_MODE, NULL) || 175 policy_mgr_mode_specific_connection_count 176 (psoc, 177 PM_P2P_CLIENT_MODE, NULL); 178 179 if (sap_or_p2p_present) { 180 req->active_dwell_time = scan_def->conc_active_dwell; 181 req->passive_dwell_time = scan_def->conc_passive_dwell; 182 } 183 } 184 #endif 185 186 void wlan_scan_cfg_get_conc_active_dwelltime(struct wlan_objmgr_psoc *psoc, 187 uint32_t *dwell_time) 188 { 189 struct wlan_scan_obj *scan_obj; 190 191 scan_obj = wlan_psoc_get_scan_obj(psoc); 192 if (!scan_obj) 193 return; 194 195 *dwell_time = scan_obj->scan_def.conc_active_dwell; 196 } 197 198 void wlan_scan_cfg_set_conc_active_dwelltime(struct wlan_objmgr_psoc *psoc, 199 uint32_t dwell_time) 200 { 201 struct wlan_scan_obj *scan_obj; 202 203 scan_obj = wlan_psoc_get_scan_obj(psoc); 204 if (!scan_obj) 205 return; 206 207 scan_obj->scan_def.conc_active_dwell = dwell_time; 208 } 209 210 void wlan_scan_cfg_get_conc_passive_dwelltime(struct wlan_objmgr_psoc *psoc, 211 uint32_t *dwell_time) 212 { 213 struct wlan_scan_obj *scan_obj; 214 215 scan_obj = wlan_psoc_get_scan_obj(psoc); 216 if (!scan_obj) 217 return; 218 219 *dwell_time = scan_obj->scan_def.conc_passive_dwell; 220 } 221 222 void wlan_scan_cfg_set_conc_passive_dwelltime(struct wlan_objmgr_psoc *psoc, 223 uint32_t dwell_time) 224 { 225 struct wlan_scan_obj *scan_obj; 226 227 scan_obj = wlan_psoc_get_scan_obj(psoc); 228 if (!scan_obj) 229 return; 230 231 scan_obj->scan_def.conc_passive_dwell = dwell_time; 232 } 233 234 void 235 wlan_scan_cfg_get_dfs_chan_scan_allowed(struct wlan_objmgr_psoc *psoc, 236 bool *enable_dfs_scan) 237 { 238 struct wlan_scan_obj *scan_obj; 239 240 scan_obj = wlan_psoc_get_scan_obj(psoc); 241 if (!scan_obj) 242 return; 243 244 *enable_dfs_scan = scan_obj->scan_def.allow_dfs_chan_in_scan; 245 } 246 247 void 248 wlan_scan_cfg_set_dfs_chan_scan_allowed(struct wlan_objmgr_psoc *psoc, 249 bool enable_dfs_scan) 250 { 251 struct wlan_scan_obj *scan_obj; 252 253 scan_obj = wlan_psoc_get_scan_obj(psoc); 254 if (!scan_obj) 255 return; 256 257 scan_obj->scan_def.allow_dfs_chan_in_scan = enable_dfs_scan; 258 } 259 260 bool wlan_scan_cfg_honour_nl_scan_policy_flags(struct wlan_objmgr_psoc *psoc) 261 { 262 struct wlan_scan_obj *scan_obj; 263 264 scan_obj = wlan_psoc_get_scan_obj(psoc); 265 if (!scan_obj) 266 return false; 267 268 return scan_obj->scan_def.honour_nl_scan_policy_flags; 269 } 270 271 void wlan_scan_cfg_get_conc_max_resttime(struct wlan_objmgr_psoc *psoc, 272 uint32_t *rest_time) 273 { 274 struct wlan_scan_obj *scan_obj; 275 276 scan_obj = wlan_psoc_get_scan_obj(psoc); 277 if (!scan_obj) 278 return; 279 280 *rest_time = scan_obj->scan_def.conc_max_rest_time; 281 } 282 283 void wlan_scan_cfg_get_conc_min_resttime(struct wlan_objmgr_psoc *psoc, 284 uint32_t *rest_time) 285 { 286 struct wlan_scan_obj *scan_obj; 287 288 scan_obj = wlan_psoc_get_scan_obj(psoc); 289 if (!scan_obj) 290 return; 291 292 *rest_time = scan_obj->scan_def.conc_min_rest_time; 293 } 294 295 bool wlan_scan_is_snr_monitor_enabled(struct wlan_objmgr_psoc *psoc) 296 { 297 struct wlan_scan_obj *scan_obj; 298 299 scan_obj = wlan_psoc_get_scan_obj(psoc); 300 if (!scan_obj) 301 return cfg_default(CFG_ENABLE_SNR_MONITORING); 302 303 return scan_obj->scan_def.scan_f_chan_stat_evnt; 304 } 305 306 QDF_STATUS 307 wlan_scan_process_bcn_probe_rx_sync(struct wlan_objmgr_psoc *psoc, 308 qdf_nbuf_t buf, 309 struct mgmt_rx_event_params *rx_param, 310 enum mgmt_frame_type frm_type) 311 { 312 struct scan_bcn_probe_event *bcn = NULL; 313 QDF_STATUS status; 314 315 if ((frm_type != MGMT_PROBE_RESP) && 316 (frm_type != MGMT_BEACON)) { 317 scm_err("frame is not beacon or probe resp"); 318 status = QDF_STATUS_E_INVAL; 319 goto free; 320 } 321 322 bcn = qdf_mem_malloc_atomic(sizeof(*bcn)); 323 if (!bcn) { 324 status = QDF_STATUS_E_NOMEM; 325 goto free; 326 } 327 bcn->rx_data = 328 qdf_mem_malloc_atomic(sizeof(*rx_param)); 329 if (!bcn->rx_data) { 330 status = QDF_STATUS_E_NOMEM; 331 goto free; 332 } 333 334 if (frm_type == MGMT_PROBE_RESP) 335 bcn->frm_type = MGMT_SUBTYPE_PROBE_RESP; 336 else 337 bcn->frm_type = MGMT_SUBTYPE_BEACON; 338 339 status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_SCAN_ID); 340 if (QDF_IS_STATUS_ERROR(status)) { 341 scm_info("unable to get reference"); 342 goto free; 343 } 344 345 bcn->psoc = psoc; 346 bcn->buf = buf; 347 qdf_mem_copy(bcn->rx_data, rx_param, sizeof(*rx_param)); 348 349 return __scm_handle_bcn_probe(bcn); 350 free: 351 if (bcn && bcn->rx_data) 352 qdf_mem_free(bcn->rx_data); 353 if (bcn) 354 qdf_mem_free(bcn); 355 if (buf) 356 qdf_nbuf_free(buf); 357 358 return status; 359 } 360 361 qdf_time_t wlan_scan_get_aging_time(struct wlan_objmgr_psoc *psoc) 362 { 363 struct wlan_scan_obj *scan_obj; 364 365 scan_obj = wlan_psoc_get_scan_obj(psoc); 366 if (!scan_obj) 367 return cfg_default(CFG_SCAN_AGING_TIME) * 1000; 368 369 return scan_obj->scan_def.scan_cache_aging_time; 370 } 371 372 QDF_STATUS wlan_scan_set_aging_time(struct wlan_objmgr_psoc *psoc, 373 qdf_time_t time) 374 { 375 struct wlan_scan_obj *scan_obj; 376 QDF_STATUS status = QDF_STATUS_E_FAILURE; 377 378 scan_obj = wlan_psoc_get_scan_obj(psoc); 379 if (!scan_obj) 380 return status; 381 382 if (!cfg_in_range(CFG_SCAN_AGING_TIME, time / 1000)) { 383 status = QDF_STATUS_E_RANGE; 384 return status; 385 } 386 387 scan_obj->scan_def.scan_cache_aging_time = time; 388 status = QDF_STATUS_SUCCESS; 389 return status; 390 } 391 392 QDF_STATUS wlan_scan_start(struct scan_start_request *req) 393 { 394 struct scheduler_msg msg = {0}; 395 QDF_STATUS status; 396 397 if (!req || !req->vdev) { 398 scm_err("req or vdev within req is NULL"); 399 if (req) 400 scm_scan_free_scan_request_mem(req); 401 return QDF_STATUS_E_NULL_VALUE; 402 } 403 404 if (!scm_is_scan_allowed(req->vdev)) { 405 scm_err_rl("scan disabled, rejecting the scan req"); 406 scm_scan_free_scan_request_mem(req); 407 return QDF_STATUS_E_AGAIN; 408 } 409 410 /* 411 * Try to get vdev reference. Return if reference could 412 * not be taken. Reference will be released once scan 413 * request handling completes along with free of @req. 414 */ 415 status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID); 416 if (QDF_IS_STATUS_ERROR(status)) { 417 scm_info("unable to get reference"); 418 scm_scan_free_scan_request_mem(req); 419 return status; 420 } 421 422 msg.bodyptr = req; 423 msg.callback = scm_scan_start_req; 424 msg.flush_callback = scm_scan_start_flush_callback; 425 426 status = scheduler_post_message(QDF_MODULE_ID_OS_IF, 427 QDF_MODULE_ID_SCAN, 428 QDF_MODULE_ID_OS_IF, &msg); 429 if (QDF_IS_STATUS_ERROR(status)) { 430 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 431 scm_scan_free_scan_request_mem(req); 432 } 433 434 return status; 435 } 436 437 QDF_STATUS wlan_scan_cancel(struct scan_cancel_request *req) 438 { 439 struct scheduler_msg msg = {0}; 440 QDF_STATUS status; 441 442 if (!req || !req->vdev) { 443 scm_err("req or vdev within req is NULL"); 444 if (req) 445 qdf_mem_free(req); 446 return QDF_STATUS_E_NULL_VALUE; 447 } 448 449 status = wlan_objmgr_vdev_try_get_ref(req->vdev, WLAN_SCAN_ID); 450 if (QDF_IS_STATUS_ERROR(status)) { 451 scm_info("Failed to get vdev ref; status:%d", status); 452 goto req_free; 453 } 454 455 msg.bodyptr = req; 456 msg.callback = scm_scan_cancel_req; 457 msg.flush_callback = scm_scan_cancel_flush_callback; 458 459 status = scheduler_post_message(QDF_MODULE_ID_OS_IF, 460 QDF_MODULE_ID_SCAN, 461 QDF_MODULE_ID_OS_IF, &msg); 462 if (QDF_IS_STATUS_ERROR(status)) 463 goto vdev_put; 464 465 return QDF_STATUS_SUCCESS; 466 467 vdev_put: 468 wlan_objmgr_vdev_release_ref(req->vdev, WLAN_SCAN_ID); 469 470 req_free: 471 qdf_mem_free(req); 472 473 return status; 474 } 475 476 wlan_scan_id 477 wlan_scan_get_scan_id(struct wlan_objmgr_psoc *psoc) 478 { 479 wlan_scan_id id; 480 struct wlan_scan_obj *scan; 481 482 if (!psoc) { 483 QDF_ASSERT(0); 484 scm_err("null psoc"); 485 return 0; 486 } 487 488 scan = wlan_psoc_get_scan_obj(psoc); 489 if (!scan) { 490 scm_err("scan object null"); 491 return 0; 492 } 493 494 id = qdf_atomic_inc_return(&scan->scan_ids); 495 id = id & WLAN_SCAN_ID_MASK; 496 /* Mark this scan request as triggered by host 497 * by setting WLAN_HOST_SCAN_REQ_ID_PREFIX flag. 498 */ 499 id = id | WLAN_HOST_SCAN_REQ_ID_PREFIX; 500 scm_debug("scan_id: 0x%x", id); 501 502 return id; 503 } 504 505 QDF_STATUS 506 wlan_scan_init_default_params(struct wlan_objmgr_vdev *vdev, 507 struct scan_start_request *req) 508 { 509 struct scan_default_params *def; 510 511 if (!vdev | !req) { 512 scm_err("vdev: 0x%pK, req: 0x%pK", vdev, req); 513 return QDF_STATUS_E_INVAL; 514 } 515 def = wlan_vdev_get_def_scan_params(vdev); 516 if (!def) { 517 scm_err("wlan_vdev_get_def_scan_params returned NULL"); 518 return QDF_STATUS_E_NULL_VALUE; 519 } 520 521 /* Zero out everything and explicitly set fields as required */ 522 qdf_mem_zero(req, sizeof(*req)); 523 524 req->vdev = vdev; 525 req->scan_req.vdev_id = wlan_vdev_get_id(vdev); 526 req->scan_req.scan_type = SCAN_TYPE_DEFAULT; 527 req->scan_req.scan_priority = def->scan_priority; 528 req->scan_req.dwell_time_active = def->active_dwell; 529 req->scan_req.dwell_time_active_2g = def->active_dwell_2g; 530 req->scan_req.min_dwell_time_6g = def->min_dwell_time_6g; 531 req->scan_req.dwell_time_active_6g = def->active_dwell_6g; 532 req->scan_req.dwell_time_passive_6g = def->passive_dwell_6g; 533 req->scan_req.dwell_time_passive = def->passive_dwell; 534 req->scan_req.min_rest_time = def->min_rest_time; 535 req->scan_req.max_rest_time = def->max_rest_time; 536 req->scan_req.repeat_probe_time = def->repeat_probe_time; 537 req->scan_req.probe_spacing_time = def->probe_spacing_time; 538 req->scan_req.idle_time = def->idle_time; 539 req->scan_req.max_scan_time = def->max_scan_time; 540 req->scan_req.probe_delay = def->probe_delay; 541 req->scan_req.burst_duration = def->burst_duration; 542 req->scan_req.n_probes = def->num_probes; 543 req->scan_req.adaptive_dwell_time_mode = 544 def->adaptive_dwell_time_mode; 545 req->scan_req.scan_flags = def->scan_flags; 546 req->scan_req.scan_events = def->scan_events; 547 req->scan_req.scan_random.randomize = def->enable_mac_spoofing; 548 549 return QDF_STATUS_SUCCESS; 550 } 551 552 wlan_scan_requester 553 wlan_scan_register_requester(struct wlan_objmgr_psoc *psoc, 554 uint8_t *name, 555 scan_event_handler event_cb, 556 void *arg) 557 { 558 int i, j; 559 struct wlan_scan_obj *scan; 560 struct scan_requester_info *requesters; 561 wlan_scan_requester requester = {0}; 562 563 if (!psoc) { 564 scm_err("null psoc"); 565 return 0; 566 } 567 scan = wlan_psoc_get_scan_obj(psoc); 568 if (!scan) 569 return 0; 570 571 requesters = scan->requesters; 572 qdf_spin_lock_bh(&scan->lock); 573 for (i = 0; i < WLAN_MAX_REQUESTORS; ++i) { 574 if (requesters[i].requester == 0) { 575 requesters[i].requester = 576 WLAN_SCAN_REQUESTER_ID_PREFIX | i; 577 j = 0; 578 while (name[j] && (j < (WLAN_MAX_MODULE_NAME - 1))) { 579 requesters[i].module[j] = name[j]; 580 ++j; 581 } 582 requesters[i].module[j] = 0; 583 requesters[i].ev_handler.func = event_cb; 584 requesters[i].ev_handler.arg = arg; 585 requester = requesters[i].requester; 586 break; 587 } 588 } 589 qdf_spin_unlock_bh(&scan->lock); 590 scm_debug("module: %s, event_cb: 0x%pK, arg: 0x%pK, reqid: %d", 591 name, event_cb, arg, requester); 592 593 return requester; 594 } 595 596 void 597 wlan_scan_unregister_requester(struct wlan_objmgr_psoc *psoc, 598 wlan_scan_requester requester) 599 { 600 int idx; 601 struct wlan_scan_obj *scan; 602 struct scan_requester_info *requesters; 603 604 idx = requester & WLAN_SCAN_REQUESTER_ID_PREFIX; 605 if (idx != WLAN_SCAN_REQUESTER_ID_PREFIX) { 606 scm_err("prefix didn't match for requester id %d", requester); 607 return; 608 } 609 610 idx = requester & WLAN_SCAN_REQUESTER_ID_MASK; 611 if (idx >= WLAN_MAX_REQUESTORS) { 612 scm_err("requester id %d greater than max value", requester); 613 return; 614 } 615 616 if (!psoc) { 617 scm_err("null psoc"); 618 return; 619 } 620 scan = wlan_psoc_get_scan_obj(psoc); 621 if (!scan) 622 return; 623 requesters = scan->requesters; 624 scm_debug("reqid: %d", requester); 625 626 qdf_spin_lock_bh(&scan->lock); 627 requesters[idx].requester = 0; 628 requesters[idx].module[0] = 0; 629 requesters[idx].ev_handler.func = NULL; 630 requesters[idx].ev_handler.arg = NULL; 631 qdf_spin_unlock_bh(&scan->lock); 632 } 633 634