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