1 /* 2 * Copyright (c) 2017 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%p, data: 0x%p\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%p, data: 0x%p", 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%p, data: 0x%p", 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 return wmi_unified_pno_start_cmd(GET_WMI_HDL_FROM_PSOC(psoc), req); 243 } 244 245 static QDF_STATUS 246 target_if_pno_stop(struct wlan_objmgr_psoc *psoc, 247 uint8_t vdev_id) 248 { 249 return wmi_unified_pno_stop_cmd(GET_WMI_HDL_FROM_PSOC(psoc), vdev_id); 250 } 251 252 #else 253 254 static inline QDF_STATUS 255 target_if_scan_register_pno_event_handler(struct wlan_objmgr_psoc *psoc, 256 void *arg) 257 { 258 return QDF_STATUS_SUCCESS; 259 } 260 261 static inline QDF_STATUS 262 target_if_scan_unregister_pno_event_handler(struct wlan_objmgr_psoc *psoc, 263 void *arg) 264 { 265 return QDF_STATUS_SUCCESS; 266 } 267 268 static inline QDF_STATUS 269 target_if_pno_start(struct wlan_objmgr_psoc *psoc, 270 struct pno_scan_req_params *req) 271 { 272 return QDF_STATUS_SUCCESS; 273 } 274 275 static inline QDF_STATUS 276 target_if_pno_stop(struct wlan_objmgr_psoc *psoc, 277 uint8_t vdev_id) 278 { 279 return QDF_STATUS_SUCCESS; 280 } 281 #endif 282 283 284 QDF_STATUS 285 target_if_scan_register_event_handler(struct wlan_objmgr_psoc *psoc, void *arg) 286 { 287 QDF_STATUS status; 288 289 status = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc), 290 wmi_scan_event_id, target_if_scan_event_handler); 291 if (status) { 292 target_if_err("Failed to register Scan match event cb"); 293 return QDF_STATUS_E_FAILURE; 294 } 295 296 status = target_if_scan_register_pno_event_handler(psoc, arg); 297 298 return status; 299 } 300 301 QDF_STATUS 302 target_if_scan_unregister_event_handler(struct wlan_objmgr_psoc *psoc, 303 void *arg) 304 { 305 QDF_STATUS status; 306 307 status = wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc), 308 wmi_scan_event_id); 309 if (status) { 310 target_if_err("Failed to unregister Scan match event cb"); 311 return QDF_STATUS_E_FAILURE; 312 } 313 314 status = target_if_scan_unregister_pno_event_handler(psoc, arg); 315 316 return status; 317 } 318 319 QDF_STATUS 320 target_if_scan_start(struct wlan_objmgr_psoc *psoc, 321 struct scan_start_request *req) 322 { 323 return wmi_unified_scan_start_cmd_send(GET_WMI_HDL_FROM_PSOC(psoc), 324 &req->scan_req); 325 } 326 327 QDF_STATUS 328 target_if_scan_cancel(struct wlan_objmgr_psoc *psoc, 329 struct scan_cancel_param *req) 330 { 331 return wmi_unified_scan_stop_cmd_send(GET_WMI_HDL_FROM_PSOC(psoc), req); 332 } 333 334 QDF_STATUS 335 target_if_register_scan_tx_ops(struct wlan_lmac_if_scan_tx_ops *scan) 336 { 337 scan->scan_start = target_if_scan_start; 338 scan->scan_cancel = target_if_scan_cancel; 339 scan->pno_start = target_if_pno_start; 340 scan->pno_stop = target_if_pno_stop; 341 scan->scan_reg_ev_handler = target_if_scan_register_event_handler; 342 scan->scan_unreg_ev_handler = target_if_scan_unregister_event_handler; 343 344 return QDF_STATUS_SUCCESS; 345 } 346 347 QDF_STATUS 348 target_if_scan_set_max_active_scans(struct wlan_objmgr_psoc *psoc, 349 uint32_t max_active_scans) 350 { 351 struct wlan_lmac_if_scan_rx_ops *scan_rx_ops; 352 QDF_STATUS status; 353 354 scan_rx_ops = target_if_scan_get_rx_ops(psoc); 355 if (scan_rx_ops->scan_set_max_active_scans) { 356 status = scan_rx_ops->scan_set_max_active_scans(psoc, 357 max_active_scans); 358 } else { 359 target_if_err("scan_set_max_active_scans uninitialized"); 360 status = QDF_STATUS_E_FAULT; 361 } 362 363 return status; 364 } 365