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