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