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