1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: offload lmac interface APIs definitions for scan 22 */ 23 24 #include <qdf_mem.h> 25 #include <qdf_status.h> 26 #include <target_if_scan.h> 27 #include <wmi_unified_priv.h> 28 #include <wmi_unified_param.h> 29 #include <wlan_objmgr_psoc_obj.h> 30 #include <wlan_scan_tgt_api.h> 31 #include <target_if.h> 32 33 static inline struct wlan_lmac_if_scan_rx_ops * 34 target_if_scan_get_rx_ops(struct wlan_objmgr_psoc *psoc) 35 { 36 struct wlan_lmac_if_rx_ops *rx_ops; 37 38 rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); 39 if (!rx_ops) { 40 target_if_err("rx_ops is NULL"); 41 return NULL; 42 } 43 44 return &rx_ops->scan; 45 } 46 47 QDF_STATUS target_if_update_aux_support(struct wlan_objmgr_psoc *psoc) 48 { 49 struct wmi_unified *wmi_handle; 50 struct wlan_scan_obj *scan_obj; 51 52 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 53 54 if (!wmi_handle) { 55 target_if_err("null wmi handle"); 56 return QDF_STATUS_E_FAILURE; 57 } 58 scan_obj = wlan_psoc_get_scan_obj(psoc); 59 60 if (!scan_obj) { 61 target_if_err("Failed to get scan object"); 62 return QDF_STATUS_E_FAILURE; 63 } 64 if (wmi_service_enabled(wmi_handle, wmi_service_aux_mac_support)) 65 scan_obj->aux_mac_support = true; 66 else 67 scan_obj->aux_mac_support = false; 68 69 target_if_debug("aux_mac_support:%d", scan_obj->aux_mac_support); 70 return QDF_STATUS_SUCCESS; 71 } 72 73 static int 74 target_if_scan_event_handler(ol_scn_t scn, uint8_t *data, uint32_t datalen) 75 { 76 struct scan_event_info *event_info; 77 struct wlan_objmgr_psoc *psoc; 78 struct wmi_unified *wmi_handle; 79 struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; 80 QDF_STATUS status; 81 82 if (!scn || !data) { 83 target_if_err("scn: 0x%pK, data: 0x%pK\n", scn, data); 84 return -EINVAL; 85 } 86 psoc = target_if_get_psoc_from_scn_hdl(scn); 87 if (!psoc) { 88 target_if_err("null psoc\n"); 89 return -EINVAL; 90 } 91 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 92 93 if (!wmi_handle) { 94 target_if_err("wmi_handle is NULL"); 95 return -EINVAL; 96 } 97 98 event_info = qdf_mem_malloc(sizeof(*event_info)); 99 100 if (!event_info) 101 return -ENOMEM; 102 103 if (wmi_extract_vdev_scan_ev_param(wmi_handle, data, 104 &(event_info->event))) { 105 target_if_err("Failed to extract wmi scan event"); 106 qdf_mem_free(event_info); 107 return -EINVAL; 108 } 109 110 scan_rx_ops = target_if_scan_get_rx_ops(psoc); 111 if (!scan_rx_ops) { 112 target_if_err("scan_rx_ops is NULL"); 113 return -EINVAL; 114 } 115 116 if (scan_rx_ops->scan_ev_handler) { 117 status = scan_rx_ops->scan_ev_handler(psoc, event_info); 118 if (status != QDF_STATUS_SUCCESS) { 119 qdf_mem_free(event_info); 120 return -EINVAL; 121 } 122 } else { 123 qdf_mem_free(event_info); 124 return -EINVAL; 125 } 126 127 return 0; 128 } 129 130 #ifdef FEATURE_WLAN_SCAN_PNO 131 132 int target_if_nlo_complete_handler(ol_scn_t scn, uint8_t *data, 133 uint32_t len) 134 { 135 struct scan_event_info *event_info; 136 struct wlan_objmgr_psoc *psoc; 137 struct wmi_unified *wmi_handle; 138 struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; 139 QDF_STATUS status; 140 141 if (!scn || !data) { 142 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 143 return -EINVAL; 144 } 145 146 psoc = target_if_get_psoc_from_scn_hdl(scn); 147 if (!psoc) { 148 target_if_err("null psoc"); 149 return -EINVAL; 150 } 151 152 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 153 if (!wmi_handle) { 154 target_if_err("wmi_handle is NULL"); 155 return -EINVAL; 156 } 157 158 event_info = qdf_mem_malloc(sizeof(*event_info)); 159 if (!event_info) 160 return -ENOMEM; 161 162 if (wmi_extract_nlo_complete_ev_param(wmi_handle, data, 163 &event_info->event)) { 164 target_if_err("Failed to extract WMI PNO complete event"); 165 qdf_mem_free(event_info); 166 return -EINVAL; 167 } 168 169 target_if_debug("PNO complete event received for vdev %d", 170 event_info->event.vdev_id); 171 172 scan_rx_ops = target_if_scan_get_rx_ops(psoc); 173 if (!scan_rx_ops) { 174 target_if_err("scan_rx_ops is NULL"); 175 return -EINVAL; 176 } 177 178 if (scan_rx_ops->scan_ev_handler) { 179 status = scan_rx_ops->scan_ev_handler(psoc, event_info); 180 if (status != QDF_STATUS_SUCCESS) { 181 qdf_mem_free(event_info); 182 return -EINVAL; 183 } 184 } else { 185 qdf_mem_free(event_info); 186 return -EINVAL; 187 } 188 189 return 0; 190 } 191 192 int target_if_nlo_match_event_handler(ol_scn_t scn, uint8_t *data, 193 uint32_t len) 194 { 195 struct scan_event_info *event_info; 196 struct wlan_objmgr_psoc *psoc; 197 struct wmi_unified *wmi_handle; 198 struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; 199 QDF_STATUS status; 200 201 if (!scn || !data) { 202 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 203 return -EINVAL; 204 } 205 206 psoc = target_if_get_psoc_from_scn_hdl(scn); 207 if (!psoc) { 208 target_if_err("null psoc"); 209 return -EINVAL; 210 } 211 212 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 213 if (!wmi_handle) { 214 target_if_err("wmi_handle is NULL"); 215 return -EINVAL; 216 } 217 218 event_info = qdf_mem_malloc(sizeof(*event_info)); 219 if (!event_info) 220 return -ENOMEM; 221 222 if (wmi_extract_nlo_match_ev_param(wmi_handle, data, 223 &event_info->event)) { 224 target_if_err("Failed to extract WMI PNO match event"); 225 qdf_mem_free(event_info); 226 return -EINVAL; 227 } 228 229 target_if_debug("PNO match event received for vdev %d", 230 event_info->event.vdev_id); 231 232 scan_rx_ops = target_if_scan_get_rx_ops(psoc); 233 if (!scan_rx_ops) { 234 target_if_err("scan_rx_ops is NULL"); 235 return -EINVAL; 236 } 237 238 if (scan_rx_ops->scan_ev_handler) { 239 status = scan_rx_ops->scan_ev_handler(psoc, event_info); 240 if (status != QDF_STATUS_SUCCESS) { 241 qdf_mem_free(event_info); 242 return -EINVAL; 243 } 244 } else { 245 qdf_mem_free(event_info); 246 return -EINVAL; 247 } 248 249 return 0; 250 } 251 252 static QDF_STATUS 253 target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc, 254 void *arg) 255 { 256 QDF_STATUS status; 257 struct wmi_unified *wmi_handle; 258 259 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 260 if (!wmi_handle) { 261 target_if_err("Invalid WMI handle"); 262 return QDF_STATUS_E_FAILURE; 263 } 264 265 status = wmi_unified_register_event( 266 wmi_handle, 267 wmi_nlo_match_event_id, 268 target_if_nlo_match_event_handler); 269 if (status) { 270 target_if_err("Failed to register nlo match event cb"); 271 return QDF_STATUS_E_FAILURE; 272 } 273 274 status = wmi_unified_register_event( 275 wmi_handle, 276 wmi_nlo_scan_complete_event_id, 277 target_if_nlo_complete_handler); 278 if (status) { 279 target_if_err("Failed to register nlo scan comp event cb"); 280 return QDF_STATUS_E_FAILURE; 281 } 282 283 return QDF_STATUS_SUCCESS; 284 } 285 286 static QDF_STATUS 287 target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc, 288 void *arg) 289 { 290 QDF_STATUS status; 291 struct wmi_unified *wmi_handle; 292 293 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 294 if (!wmi_handle) { 295 target_if_err("Invalid WMI handle"); 296 return QDF_STATUS_E_FAILURE; 297 } 298 299 status = wmi_unified_unregister_event( 300 wmi_handle, 301 wmi_nlo_match_event_id); 302 if (status) { 303 target_if_err("Failed to unregister nlo match event cb"); 304 return QDF_STATUS_E_FAILURE; 305 } 306 307 status = wmi_unified_unregister_event( 308 wmi_handle, 309 wmi_nlo_scan_complete_event_id); 310 if (status) { 311 target_if_err("Failed to unregister nlo scan comp event cb"); 312 return QDF_STATUS_E_FAILURE; 313 } 314 315 return QDF_STATUS_SUCCESS; 316 } 317 318 static QDF_STATUS 319 target_if_pno_start(struct wlan_objmgr_psoc *psoc, 320 struct pno_scan_req_params *req) 321 { 322 QDF_STATUS status; 323 struct wmi_unified *wmi_handle; 324 325 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 326 if (!wmi_handle) { 327 target_if_err("Invalid WMI handle"); 328 return QDF_STATUS_E_FAILURE; 329 } 330 331 status = wmi_unified_pno_start_cmd(wmi_handle, req); 332 if (status == QDF_STATUS_SUCCESS) { 333 if (req->mawc_params.enable) 334 status = wmi_unified_nlo_mawc_cmd(wmi_handle, 335 &req->mawc_params); 336 } 337 338 return status; 339 } 340 341 static QDF_STATUS 342 target_if_pno_stop(struct wlan_objmgr_psoc *psoc, 343 uint8_t vdev_id) 344 { 345 struct wmi_unified *wmi_handle; 346 347 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 348 if (!wmi_handle) { 349 target_if_err("Invalid WMI handle"); 350 return QDF_STATUS_E_FAILURE; 351 } 352 353 return wmi_unified_pno_stop_cmd(wmi_handle, vdev_id); 354 } 355 356 #else 357 358 static inline QDF_STATUS 359 target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc, 360 void *arg) 361 { 362 return QDF_STATUS_SUCCESS; 363 } 364 365 static inline QDF_STATUS 366 target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc, 367 void *arg) 368 { 369 return QDF_STATUS_SUCCESS; 370 } 371 372 static inline QDF_STATUS 373 target_if_pno_start(struct wlan_objmgr_psoc *psoc, 374 struct pno_scan_req_params *req) 375 { 376 return QDF_STATUS_SUCCESS; 377 } 378 379 static inline QDF_STATUS 380 target_if_pno_stop(struct wlan_objmgr_psoc *psoc, 381 uint8_t vdev_id) 382 { 383 return QDF_STATUS_SUCCESS; 384 } 385 #endif 386 387 static QDF_STATUS 388 target_if_obss_scan_disable(struct wlan_objmgr_psoc *psoc, 389 uint8_t vdev_id) 390 { 391 struct wmi_unified *wmi_handle; 392 393 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 394 if (!wmi_handle) { 395 target_if_err("Invalid WMI handle"); 396 return QDF_STATUS_E_FAILURE; 397 } 398 399 return wmi_unified_obss_disable_cmd(wmi_handle, vdev_id); 400 } 401 402 QDF_STATUS 403 target_if_scan_register_event_handler(struct wlan_objmgr_psoc *psoc, void *arg) 404 { 405 QDF_STATUS status; 406 struct wmi_unified *wmi_handle; 407 408 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 409 if (!wmi_handle) { 410 target_if_err("Invalid WMI handle"); 411 return QDF_STATUS_E_FAILURE; 412 } 413 414 status = wmi_unified_register_event( 415 wmi_handle, 416 wmi_scan_event_id, 417 target_if_scan_event_handler); 418 if (status) { 419 target_if_err("Failed to register Scan match event cb"); 420 return QDF_STATUS_E_FAILURE; 421 } 422 423 status = target_if_scan_register_pno_event_handler(psoc, arg); 424 425 return status; 426 } 427 428 QDF_STATUS 429 target_if_scan_unregister_event_handler(struct wlan_objmgr_psoc *psoc, 430 void *arg) 431 { 432 QDF_STATUS status; 433 struct wmi_unified *wmi_handle; 434 435 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 436 if (!wmi_handle) { 437 target_if_err("Invalid WMI handle"); 438 return QDF_STATUS_E_FAILURE; 439 } 440 441 status = wmi_unified_unregister_event( 442 wmi_handle, 443 wmi_scan_event_id); 444 if (status) { 445 target_if_err("Failed to unregister Scan match event cb"); 446 return QDF_STATUS_E_FAILURE; 447 } 448 449 status = target_if_scan_unregister_pno_event_handler(psoc, arg); 450 451 return status; 452 } 453 454 QDF_STATUS 455 target_if_scan_start(struct wlan_objmgr_pdev *pdev, 456 struct scan_start_request *req) 457 { 458 wmi_unified_t pdev_wmi_handle; 459 460 pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); 461 if (!pdev_wmi_handle) { 462 target_if_err("Invalid PDEV WMI handle"); 463 return QDF_STATUS_E_FAILURE; 464 } 465 return wmi_unified_scan_start_cmd_send(pdev_wmi_handle, &req->scan_req); 466 } 467 468 QDF_STATUS 469 target_if_scan_cancel(struct wlan_objmgr_pdev *pdev, 470 struct scan_cancel_param *req) 471 { 472 wmi_unified_t pdev_wmi_handle; 473 474 pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); 475 if (!pdev_wmi_handle) { 476 target_if_err("Invalid PDEV WMI handle"); 477 return QDF_STATUS_E_NULL_VALUE; 478 } 479 return wmi_unified_scan_stop_cmd_send(pdev_wmi_handle, req); 480 } 481 482 #if defined(WLAN_FEATURE_11BE) && defined(WLAN_FEATURE_11BE_MLO_MBSSID) 483 bool target_if_is_platform_eht_capable(struct wlan_objmgr_psoc *psoc, 484 uint8_t pdev_id) 485 { 486 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr, *mac_phy_cap; 487 488 if (psoc->tgt_if_handle) { 489 mac_phy_cap_arr = 490 target_psoc_get_mac_phy_cap(psoc->tgt_if_handle); 491 if (!mac_phy_cap_arr) 492 return false; 493 494 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 495 if (mac_phy_cap && mac_phy_cap->supports_11be) 496 return true; 497 } 498 499 return false; 500 } 501 #else 502 bool target_if_is_platform_eht_capable(struct wlan_objmgr_psoc *psoc, 503 uint8_t pdev_id) 504 { 505 return false; 506 } 507 #endif 508 509 QDF_STATUS 510 target_if_scan_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 511 { 512 struct wlan_lmac_if_scan_tx_ops *scan; 513 514 scan = &tx_ops->scan; 515 if (!scan) { 516 target_if_err("Scan txops NULL"); 517 return QDF_STATUS_E_FAILURE; 518 } 519 520 scan->scan_start = target_if_scan_start; 521 scan->scan_cancel = target_if_scan_cancel; 522 scan->pno_start = target_if_pno_start; 523 scan->pno_stop = target_if_pno_stop; 524 scan->obss_disable = target_if_obss_scan_disable; 525 scan->scan_reg_ev_handler = target_if_scan_register_event_handler; 526 scan->scan_unreg_ev_handler = target_if_scan_unregister_event_handler; 527 scan->is_platform_eht_capable = target_if_is_platform_eht_capable; 528 529 return QDF_STATUS_SUCCESS; 530 } 531 532 QDF_STATUS 533 target_if_scan_set_max_active_scans(struct wlan_objmgr_psoc *psoc, 534 uint32_t max_active_scans) 535 { 536 struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; 537 QDF_STATUS status; 538 539 scan_rx_ops = target_if_scan_get_rx_ops(psoc); 540 if (!scan_rx_ops) { 541 target_if_err("scan_rx_ops is NULL"); 542 return QDF_STATUS_E_FAILURE; 543 } 544 545 if (scan_rx_ops->scan_set_max_active_scans) { 546 status = scan_rx_ops->scan_set_max_active_scans(psoc, 547 max_active_scans); 548 } else { 549 target_if_err("scan_set_max_active_scans uninitialized"); 550 status = QDF_STATUS_E_FAULT; 551 } 552 553 return status; 554 } 555