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