xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_tgt_api.c (revision 6ecd284e5a94a1c96e26d571dd47419ac305990d)
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: contains scan south bound interface definitions
21  */
22 
23 #include <wlan_cmn.h>
24 #include <qdf_list.h>
25 #include "../../core/src/wlan_scan_main.h"
26 #include <wlan_scan_utils_api.h>
27 #include <wlan_scan_ucfg_api.h>
28 #include <wlan_scan_tgt_api.h>
29 #include <wlan_objmgr_cmn.h>
30 #include <wlan_lmac_if_def.h>
31 #include <wlan_objmgr_psoc_obj.h>
32 #include <wlan_objmgr_pdev_obj.h>
33 #include <wlan_objmgr_vdev_obj.h>
34 #include <../../core/src/wlan_scan_manager.h>
35 
36 static inline struct wlan_lmac_if_scan_tx_ops *
37 wlan_psoc_get_scan_txops(struct wlan_objmgr_psoc *psoc)
38 {
39 	return &((psoc->soc_cb.tx_ops.scan));
40 }
41 
42 static inline struct wlan_lmac_if_scan_tx_ops *
43 wlan_vdev_get_scan_txops(struct wlan_objmgr_vdev *vdev)
44 {
45 	struct wlan_objmgr_psoc *psoc = NULL;
46 
47 	psoc = wlan_vdev_get_psoc(vdev);
48 	if (!psoc) {
49 		scm_err("NULL psoc");
50 		return NULL;
51 	}
52 
53 	return wlan_psoc_get_scan_txops(psoc);
54 }
55 
56 static inline struct wlan_lmac_if_scan_rx_ops *
57 wlan_vdev_get_scan_rxops(struct wlan_objmgr_vdev *vdev)
58 {
59 	struct wlan_objmgr_psoc *psoc = NULL;
60 
61 	psoc = wlan_vdev_get_psoc(vdev);
62 	if (!psoc) {
63 		scm_err("NULL psoc");
64 		return NULL;
65 	}
66 
67 	return &((psoc->soc_cb.rx_ops.scan));
68 }
69 
70 #ifdef FEATURE_WLAN_SCAN_PNO
71 
72 QDF_STATUS tgt_scan_pno_start(struct wlan_objmgr_vdev *vdev,
73 	struct pno_scan_req_params *req)
74 {
75 	struct wlan_lmac_if_scan_tx_ops *scan_ops;
76 	struct wlan_objmgr_psoc *psoc;
77 
78 	psoc = wlan_vdev_get_psoc(vdev);
79 
80 	scan_ops = wlan_psoc_get_scan_txops(psoc);
81 	/* invoke wmi_unified_pno_start_cmd() */
82 	QDF_ASSERT(scan_ops->pno_start);
83 	if (scan_ops->pno_start)
84 		return scan_ops->pno_start(psoc, req);
85 
86 	return QDF_STATUS_SUCCESS;
87 }
88 
89 QDF_STATUS tgt_scan_pno_stop(struct wlan_objmgr_vdev *vdev,
90 	uint8_t vdev_id)
91 {
92 	struct wlan_lmac_if_scan_tx_ops *scan_ops;
93 	struct wlan_objmgr_psoc *psoc;
94 
95 	psoc = wlan_vdev_get_psoc(vdev);
96 
97 	scan_ops = wlan_psoc_get_scan_txops(psoc);
98 	/* invoke wmi_unified_pno_stop_cmd() */
99 	QDF_ASSERT(scan_ops->pno_stop);
100 	if (scan_ops->pno_stop)
101 		return scan_ops->pno_stop(psoc, vdev_id);
102 
103 	return QDF_STATUS_SUCCESS;
104 }
105 #endif
106 
107 QDF_STATUS
108 tgt_scan_start(struct scan_start_request *req)
109 {
110 	struct wlan_lmac_if_scan_tx_ops *scan_ops;
111 	struct wlan_objmgr_psoc *psoc;
112 	struct wlan_objmgr_pdev *pdev;
113 	struct wlan_objmgr_vdev *vdev = req->vdev;
114 
115 	psoc = wlan_vdev_get_psoc(vdev);
116 	pdev = wlan_vdev_get_pdev(vdev);
117 
118 	scan_ops = wlan_psoc_get_scan_txops(psoc);
119 	/* invoke wmi_unified_scan_start_cmd_send() */
120 	QDF_ASSERT(scan_ops->scan_start);
121 	if (scan_ops->scan_start)
122 		return scan_ops->scan_start(pdev, req);
123 	else
124 		return QDF_STATUS_SUCCESS;
125 }
126 
127 
128 QDF_STATUS
129 tgt_scan_cancel(struct scan_cancel_request *req)
130 {
131 	struct wlan_lmac_if_scan_tx_ops *scan_ops;
132 	struct wlan_objmgr_psoc *psoc;
133 	struct wlan_objmgr_pdev *pdev;
134 	struct wlan_objmgr_vdev *vdev = req->vdev;
135 
136 	psoc = wlan_vdev_get_psoc(vdev);
137 	pdev = wlan_vdev_get_pdev(vdev);
138 
139 	scan_ops = wlan_psoc_get_scan_txops(psoc);
140 	/* invoke wmi_unified_scan_stop_cmd_send() */
141 	QDF_ASSERT(scan_ops->scan_cancel);
142 	if (scan_ops->scan_cancel)
143 		return scan_ops->scan_cancel(pdev, &req->cancel_req);
144 	else
145 		return QDF_STATUS_SUCCESS;
146 }
147 
148 QDF_STATUS
149 tgt_scan_register_ev_handler(struct wlan_objmgr_psoc *psoc)
150 {
151 	struct wlan_lmac_if_scan_tx_ops *scan_ops = NULL;
152 
153 	scan_ops = wlan_psoc_get_scan_txops(psoc);
154 	/* invoke wmi_unified_register_event_handler()
155 	 * since event id, handler function and context is
156 	 * already known to offload lmac, passing NULL as argument.
157 	 * DA can pass necessary arguments by clubing then into
158 	 * some structure.
159 	 */
160 	QDF_ASSERT(scan_ops->scan_reg_ev_handler);
161 	if (scan_ops->scan_reg_ev_handler)
162 		return scan_ops->scan_reg_ev_handler(psoc, NULL);
163 	else
164 		return QDF_STATUS_SUCCESS;
165 }
166 
167 QDF_STATUS
168 tgt_scan_unregister_ev_handler(struct wlan_objmgr_psoc *psoc)
169 {
170 	struct wlan_lmac_if_scan_tx_ops *scan_ops = NULL;
171 
172 	scan_ops = wlan_psoc_get_scan_txops(psoc);
173 	/* invoke wmi_unified_register_event_handler()
174 	 * since event id, handler function and context is
175 	 * already known to offload lmac, passing NULL as argument.
176 	 * DA can pass necessary arguments by clubing then into
177 	 * some structure.
178 	 */
179 	QDF_ASSERT(scan_ops->scan_unreg_ev_handler);
180 	if (scan_ops->scan_unreg_ev_handler)
181 		return scan_ops->scan_unreg_ev_handler(psoc, NULL);
182 	else
183 		return QDF_STATUS_SUCCESS;
184 }
185 
186 QDF_STATUS
187 tgt_scan_event_handler(struct wlan_objmgr_psoc *psoc,
188 		struct scan_event_info *event_info)
189 {
190 	struct scheduler_msg msg = {0};
191 	struct scan_event *event = &event_info->event;
192 	uint8_t vdev_id = event->vdev_id;
193 	QDF_STATUS status;
194 
195 	if (!psoc || !event_info) {
196 		scm_err("psoc: 0x%pK, event_info: 0x%pK", psoc, event_info);
197 		return QDF_STATUS_E_NULL_VALUE;
198 	}
199 	scm_info("vdev: %d, type: %d, reason: %d, freq: %d, req: %d, scanid: %d",
200 		vdev_id, event->type, event->reason, event->chan_freq,
201 		event->requester, event->scan_id);
202 
203 	event_info->vdev =
204 		wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
205 				vdev_id, WLAN_SCAN_ID);
206 	if (!event_info->vdev) {
207 		scm_err("null vdev, vdev_id: %d, psoc: 0x%pK", vdev_id, psoc);
208 		return QDF_STATUS_E_INVAL;
209 	}
210 	msg.bodyptr = event_info;
211 	msg.callback = scm_scan_event_handler;
212 	msg.flush_callback = scm_scan_event_flush_callback;
213 
214 	status = scheduler_post_msg(QDF_MODULE_ID_SCAN, &msg);
215 	if (QDF_IS_STATUS_ERROR(status)) {
216 		wlan_objmgr_vdev_release_ref(event_info->vdev, WLAN_SCAN_ID);
217 	}
218 
219 	return status;
220 }
221 
222 QDF_STATUS tgt_scan_bcn_probe_rx_callback(struct wlan_objmgr_psoc *psoc,
223 	struct wlan_objmgr_peer *peer, qdf_nbuf_t buf,
224 	struct mgmt_rx_event_params *rx_param,
225 	enum mgmt_frame_type frm_type)
226 {
227 	struct scheduler_msg msg = {0};
228 	struct scan_bcn_probe_event *bcn;
229 	QDF_STATUS status;
230 
231 	if ((frm_type != MGMT_PROBE_RESP) &&
232 	   (frm_type != MGMT_BEACON)) {
233 		scm_err("frame is not beacon or probe resp");
234 		qdf_nbuf_free(buf);
235 		return QDF_STATUS_E_INVAL;
236 	}
237 	bcn = qdf_mem_malloc(sizeof(*bcn));
238 
239 	if (!bcn) {
240 		scm_err("Failed to allocate memory for bcn");
241 		qdf_nbuf_free(buf);
242 		return QDF_STATUS_E_NOMEM;
243 	}
244 	bcn->rx_data =
245 		qdf_mem_malloc(sizeof(*rx_param));
246 	if (!bcn->rx_data) {
247 		scm_err("Failed to allocate memory for rx_data");
248 		qdf_mem_free(bcn);
249 		qdf_nbuf_free(buf);
250 		return QDF_STATUS_E_NOMEM;
251 	}
252 
253 	if (frm_type == MGMT_PROBE_RESP)
254 		bcn->frm_type = MGMT_SUBTYPE_PROBE_RESP;
255 	else
256 		bcn->frm_type = MGMT_SUBTYPE_BEACON;
257 
258 	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_SCAN_ID);
259 	if (QDF_IS_STATUS_ERROR(status)) {
260 		scm_info("unable to get reference");
261 		qdf_mem_free(bcn->rx_data);
262 		qdf_mem_free(bcn);
263 		qdf_nbuf_free(buf);
264 		return status;
265 	}
266 
267 	bcn->psoc = psoc;
268 	bcn->buf = buf;
269 	qdf_mem_copy(bcn->rx_data, rx_param, sizeof(*rx_param));
270 
271 	msg.bodyptr = bcn;
272 	msg.callback = scm_handle_bcn_probe;
273 	msg.flush_callback = scm_bcn_probe_flush_callback;
274 
275 	status = scheduler_post_msg(QDF_MODULE_ID_SCAN, &msg);
276 
277 	if (!QDF_IS_STATUS_SUCCESS(status)) {
278 		wlan_objmgr_psoc_release_ref(psoc, WLAN_SCAN_ID);
279 		scm_err("failed to post to QDF_MODULE_ID_SCAN");
280 		qdf_mem_free(bcn->rx_data);
281 		qdf_mem_free(bcn);
282 		qdf_nbuf_free(buf);
283 	}
284 
285 	return status;
286 }
287 
288 QDF_STATUS
289 tgt_scan_set_max_active_scans(struct wlan_objmgr_psoc *psoc,
290 		uint32_t max_active_scans)
291 {
292 	struct scan_default_params *scan_params = NULL;
293 
294 	if (!psoc) {
295 		scm_err("null psoc");
296 		return QDF_STATUS_E_NULL_VALUE;
297 	}
298 
299 	scan_params = wlan_scan_psoc_get_def_params(psoc);
300 	if (!scan_params) {
301 		scm_err("wlan_scan_psoc_get_def_params returned NULL");
302 		return QDF_STATUS_E_NULL_VALUE;
303 	}
304 
305 	scan_params->max_active_scans_allowed = max_active_scans;
306 
307 	return QDF_STATUS_SUCCESS;
308 }
309