1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 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 static int 48 target_if_scan_event_handler(ol_scn_t scn, uint8_t *data, uint32_t datalen) 49 { 50 struct scan_event_info *event_info; 51 struct wlan_objmgr_psoc *psoc; 52 struct wmi_unified *wmi_handle; 53 struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; 54 QDF_STATUS status; 55 56 if (!scn || !data) { 57 target_if_err("scn: 0x%pK, data: 0x%pK\n", scn, data); 58 return -EINVAL; 59 } 60 psoc = target_if_get_psoc_from_scn_hdl(scn); 61 if (!psoc) { 62 target_if_err("null psoc\n"); 63 return -EINVAL; 64 } 65 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 66 67 if (!wmi_handle) { 68 target_if_err("wmi_handle is NULL"); 69 return -EINVAL; 70 } 71 72 event_info = qdf_mem_malloc(sizeof(*event_info)); 73 74 if (!event_info) 75 return -ENOMEM; 76 77 if (wmi_extract_vdev_scan_ev_param(wmi_handle, data, 78 &(event_info->event))) { 79 target_if_err("Failed to extract wmi scan event"); 80 qdf_mem_free(event_info); 81 return -EINVAL; 82 } 83 84 scan_rx_ops = target_if_scan_get_rx_ops(psoc); 85 if (!scan_rx_ops) { 86 target_if_err("scan_rx_ops is NULL"); 87 return -EINVAL; 88 } 89 90 if (scan_rx_ops->scan_ev_handler) { 91 status = scan_rx_ops->scan_ev_handler(psoc, event_info); 92 if (status != QDF_STATUS_SUCCESS) { 93 qdf_mem_free(event_info); 94 return -EINVAL; 95 } 96 } else { 97 qdf_mem_free(event_info); 98 return -EINVAL; 99 } 100 101 return 0; 102 } 103 104 #ifdef FEATURE_WLAN_SCAN_PNO 105 106 int target_if_nlo_complete_handler(ol_scn_t scn, uint8_t *data, 107 uint32_t len) 108 { 109 struct scan_event_info *event_info; 110 struct wlan_objmgr_psoc *psoc; 111 struct wmi_unified *wmi_handle; 112 struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; 113 QDF_STATUS status; 114 115 if (!scn || !data) { 116 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 117 return -EINVAL; 118 } 119 120 psoc = target_if_get_psoc_from_scn_hdl(scn); 121 if (!psoc) { 122 target_if_err("null psoc"); 123 return -EINVAL; 124 } 125 126 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 127 if (!wmi_handle) { 128 target_if_err("wmi_handle is NULL"); 129 return -EINVAL; 130 } 131 132 event_info = qdf_mem_malloc(sizeof(*event_info)); 133 if (!event_info) 134 return -ENOMEM; 135 136 if (wmi_extract_nlo_complete_ev_param(wmi_handle, data, 137 &event_info->event)) { 138 target_if_err("Failed to extract WMI PNO complete event"); 139 qdf_mem_free(event_info); 140 return -EINVAL; 141 } 142 143 target_if_debug("PNO complete event received for vdev %d", 144 event_info->event.vdev_id); 145 146 scan_rx_ops = target_if_scan_get_rx_ops(psoc); 147 if (!scan_rx_ops) { 148 target_if_err("scan_rx_ops is NULL"); 149 return -EINVAL; 150 } 151 152 if (scan_rx_ops->scan_ev_handler) { 153 status = scan_rx_ops->scan_ev_handler(psoc, event_info); 154 if (status != QDF_STATUS_SUCCESS) { 155 qdf_mem_free(event_info); 156 return -EINVAL; 157 } 158 } else { 159 qdf_mem_free(event_info); 160 return -EINVAL; 161 } 162 163 return 0; 164 } 165 166 int target_if_nlo_match_event_handler(ol_scn_t scn, uint8_t *data, 167 uint32_t len) 168 { 169 struct scan_event_info *event_info; 170 struct wlan_objmgr_psoc *psoc; 171 struct wmi_unified *wmi_handle; 172 struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; 173 QDF_STATUS status; 174 175 if (!scn || !data) { 176 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 177 return -EINVAL; 178 } 179 180 psoc = target_if_get_psoc_from_scn_hdl(scn); 181 if (!psoc) { 182 target_if_err("null psoc"); 183 return -EINVAL; 184 } 185 186 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 187 if (!wmi_handle) { 188 target_if_err("wmi_handle is NULL"); 189 return -EINVAL; 190 } 191 192 event_info = qdf_mem_malloc(sizeof(*event_info)); 193 if (!event_info) 194 return -ENOMEM; 195 196 if (wmi_extract_nlo_match_ev_param(wmi_handle, data, 197 &event_info->event)) { 198 target_if_err("Failed to extract WMI PNO match event"); 199 qdf_mem_free(event_info); 200 return -EINVAL; 201 } 202 203 target_if_debug("PNO match event received for vdev %d", 204 event_info->event.vdev_id); 205 206 scan_rx_ops = target_if_scan_get_rx_ops(psoc); 207 if (!scan_rx_ops) { 208 target_if_err("scan_rx_ops is NULL"); 209 return -EINVAL; 210 } 211 212 if (scan_rx_ops->scan_ev_handler) { 213 status = scan_rx_ops->scan_ev_handler(psoc, event_info); 214 if (status != QDF_STATUS_SUCCESS) { 215 qdf_mem_free(event_info); 216 return -EINVAL; 217 } 218 } else { 219 qdf_mem_free(event_info); 220 return -EINVAL; 221 } 222 223 return 0; 224 } 225 226 static QDF_STATUS 227 target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc, 228 void *arg) 229 { 230 QDF_STATUS status; 231 struct wmi_unified *wmi_handle; 232 233 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 234 if (!wmi_handle) { 235 target_if_err("Invalid WMI handle"); 236 return QDF_STATUS_E_FAILURE; 237 } 238 239 status = wmi_unified_register_event( 240 wmi_handle, 241 wmi_nlo_match_event_id, 242 target_if_nlo_match_event_handler); 243 if (status) { 244 target_if_err("Failed to register nlo match event cb"); 245 return QDF_STATUS_E_FAILURE; 246 } 247 248 status = wmi_unified_register_event( 249 wmi_handle, 250 wmi_nlo_scan_complete_event_id, 251 target_if_nlo_complete_handler); 252 if (status) { 253 target_if_err("Failed to register nlo scan comp event cb"); 254 return QDF_STATUS_E_FAILURE; 255 } 256 257 return QDF_STATUS_SUCCESS; 258 } 259 260 static QDF_STATUS 261 target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc, 262 void *arg) 263 { 264 QDF_STATUS status; 265 struct wmi_unified *wmi_handle; 266 267 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 268 if (!wmi_handle) { 269 target_if_err("Invalid WMI handle"); 270 return QDF_STATUS_E_FAILURE; 271 } 272 273 status = wmi_unified_unregister_event( 274 wmi_handle, 275 wmi_nlo_match_event_id); 276 if (status) { 277 target_if_err("Failed to unregister nlo match event cb"); 278 return QDF_STATUS_E_FAILURE; 279 } 280 281 status = wmi_unified_unregister_event( 282 wmi_handle, 283 wmi_nlo_scan_complete_event_id); 284 if (status) { 285 target_if_err("Failed to unregister nlo scan comp event cb"); 286 return QDF_STATUS_E_FAILURE; 287 } 288 289 return QDF_STATUS_SUCCESS; 290 } 291 292 static QDF_STATUS 293 target_if_pno_start(struct wlan_objmgr_psoc *psoc, 294 struct pno_scan_req_params *req) 295 { 296 QDF_STATUS status; 297 struct wmi_unified *wmi_handle; 298 299 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 300 if (!wmi_handle) { 301 target_if_err("Invalid WMI handle"); 302 return QDF_STATUS_E_FAILURE; 303 } 304 305 status = wmi_unified_pno_start_cmd(wmi_handle, req); 306 if (status == QDF_STATUS_SUCCESS) { 307 if (req->mawc_params.enable) 308 status = wmi_unified_nlo_mawc_cmd(wmi_handle, 309 &req->mawc_params); 310 } 311 312 return status; 313 } 314 315 static QDF_STATUS 316 target_if_pno_stop(struct wlan_objmgr_psoc *psoc, 317 uint8_t vdev_id) 318 { 319 struct wmi_unified *wmi_handle; 320 321 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 322 if (!wmi_handle) { 323 target_if_err("Invalid WMI handle"); 324 return QDF_STATUS_E_FAILURE; 325 } 326 327 return wmi_unified_pno_stop_cmd(wmi_handle, vdev_id); 328 } 329 330 #else 331 332 static inline QDF_STATUS 333 target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc, 334 void *arg) 335 { 336 return QDF_STATUS_SUCCESS; 337 } 338 339 static inline QDF_STATUS 340 target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc, 341 void *arg) 342 { 343 return QDF_STATUS_SUCCESS; 344 } 345 346 static inline QDF_STATUS 347 target_if_pno_start(struct wlan_objmgr_psoc *psoc, 348 struct pno_scan_req_params *req) 349 { 350 return QDF_STATUS_SUCCESS; 351 } 352 353 static inline QDF_STATUS 354 target_if_pno_stop(struct wlan_objmgr_psoc *psoc, 355 uint8_t vdev_id) 356 { 357 return QDF_STATUS_SUCCESS; 358 } 359 #endif 360 361 static QDF_STATUS 362 target_if_obss_scan_disable(struct wlan_objmgr_psoc *psoc, 363 uint8_t vdev_id) 364 { 365 struct wmi_unified *wmi_handle; 366 367 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 368 if (!wmi_handle) { 369 target_if_err("Invalid WMI handle"); 370 return QDF_STATUS_E_FAILURE; 371 } 372 373 return wmi_unified_obss_disable_cmd(wmi_handle, vdev_id); 374 } 375 376 QDF_STATUS 377 target_if_scan_register_event_handler(struct wlan_objmgr_psoc *psoc, void *arg) 378 { 379 QDF_STATUS status; 380 struct wmi_unified *wmi_handle; 381 382 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 383 if (!wmi_handle) { 384 target_if_err("Invalid WMI handle"); 385 return QDF_STATUS_E_FAILURE; 386 } 387 388 status = wmi_unified_register_event( 389 wmi_handle, 390 wmi_scan_event_id, 391 target_if_scan_event_handler); 392 if (status) { 393 target_if_err("Failed to register Scan match event cb"); 394 return QDF_STATUS_E_FAILURE; 395 } 396 397 status = target_if_scan_register_pno_event_handler(psoc, arg); 398 399 return status; 400 } 401 402 QDF_STATUS 403 target_if_scan_unregister_event_handler(struct wlan_objmgr_psoc *psoc, 404 void *arg) 405 { 406 QDF_STATUS status; 407 struct wmi_unified *wmi_handle; 408 409 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 410 if (!wmi_handle) { 411 target_if_err("Invalid WMI handle"); 412 return QDF_STATUS_E_FAILURE; 413 } 414 415 status = wmi_unified_unregister_event( 416 wmi_handle, 417 wmi_scan_event_id); 418 if (status) { 419 target_if_err("Failed to unregister Scan match event cb"); 420 return QDF_STATUS_E_FAILURE; 421 } 422 423 status = target_if_scan_unregister_pno_event_handler(psoc, arg); 424 425 return status; 426 } 427 428 QDF_STATUS 429 target_if_scan_start(struct wlan_objmgr_pdev *pdev, 430 struct scan_start_request *req) 431 { 432 wmi_unified_t pdev_wmi_handle; 433 434 pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); 435 if (!pdev_wmi_handle) { 436 target_if_err("Invalid PDEV WMI handle"); 437 return QDF_STATUS_E_FAILURE; 438 } 439 return wmi_unified_scan_start_cmd_send(pdev_wmi_handle, &req->scan_req); 440 } 441 442 QDF_STATUS 443 target_if_scan_cancel(struct wlan_objmgr_pdev *pdev, 444 struct scan_cancel_param *req) 445 { 446 wmi_unified_t pdev_wmi_handle; 447 448 pdev_wmi_handle = GET_WMI_HDL_FROM_PDEV(pdev); 449 if (!pdev_wmi_handle) { 450 target_if_err("Invalid PDEV WMI handle"); 451 return QDF_STATUS_E_NULL_VALUE; 452 } 453 return wmi_unified_scan_stop_cmd_send(pdev_wmi_handle, req); 454 } 455 456 #if defined(WLAN_FEATURE_11BE) && defined(WLAN_FEATURE_11BE_MLO_MBSSID) 457 bool target_if_is_platform_eht_capable(struct wlan_objmgr_psoc *psoc, 458 uint8_t pdev_id) 459 { 460 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap_arr, *mac_phy_cap; 461 462 if (psoc->tgt_if_handle) { 463 mac_phy_cap_arr = 464 target_psoc_get_mac_phy_cap(psoc->tgt_if_handle); 465 if (!mac_phy_cap_arr) 466 return false; 467 468 mac_phy_cap = &mac_phy_cap_arr[pdev_id]; 469 if (mac_phy_cap && mac_phy_cap->supports_11be) 470 return true; 471 } 472 473 return false; 474 } 475 #else 476 bool target_if_is_platform_eht_capable(struct wlan_objmgr_psoc *psoc, 477 uint8_t pdev_id) 478 { 479 return false; 480 } 481 #endif 482 483 QDF_STATUS 484 target_if_scan_tx_ops_register(struct wlan_lmac_if_tx_ops *tx_ops) 485 { 486 struct wlan_lmac_if_scan_tx_ops *scan; 487 488 scan = &tx_ops->scan; 489 if (!scan) { 490 target_if_err("Scan txops NULL"); 491 return QDF_STATUS_E_FAILURE; 492 } 493 494 scan->scan_start = target_if_scan_start; 495 scan->scan_cancel = target_if_scan_cancel; 496 scan->pno_start = target_if_pno_start; 497 scan->pno_stop = target_if_pno_stop; 498 scan->obss_disable = target_if_obss_scan_disable; 499 scan->scan_reg_ev_handler = target_if_scan_register_event_handler; 500 scan->scan_unreg_ev_handler = target_if_scan_unregister_event_handler; 501 scan->is_platform_eht_capable = target_if_is_platform_eht_capable; 502 503 return QDF_STATUS_SUCCESS; 504 } 505 506 QDF_STATUS 507 target_if_scan_set_max_active_scans(struct wlan_objmgr_psoc *psoc, 508 uint32_t max_active_scans) 509 { 510 struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; 511 QDF_STATUS status; 512 513 scan_rx_ops = target_if_scan_get_rx_ops(psoc); 514 if (!scan_rx_ops) { 515 target_if_err("scan_rx_ops is NULL"); 516 return QDF_STATUS_E_FAILURE; 517 } 518 519 if (scan_rx_ops->scan_set_max_active_scans) { 520 status = scan_rx_ops->scan_set_max_active_scans(psoc, 521 max_active_scans); 522 } else { 523 target_if_err("scan_set_max_active_scans uninitialized"); 524 status = QDF_STATUS_E_FAULT; 525 } 526 527 return status; 528 } 529