1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: This file contains p2p south bound interface definitions
22  */
23 
24 #include <wlan_objmgr_psoc_obj.h>
25 #include <wlan_mgmt_txrx_utils_api.h>
26 #include <scheduler_api.h>
27 #include <wlan_objmgr_psoc_obj.h>
28 #include <wlan_objmgr_global_obj.h>
29 #include <wlan_objmgr_pdev_obj.h>
30 #include <wlan_objmgr_vdev_obj.h>
31 #include <wlan_objmgr_peer_obj.h>
32 #include "wlan_p2p_tgt_api.h"
33 #include "wlan_p2p_public_struct.h"
34 #include "../../core/src/wlan_p2p_main.h"
35 #include "../../core/src/wlan_p2p_roc.h"
36 #include "../../core/src/wlan_p2p_off_chan_tx.h"
37 
38 #define IEEE80211_FC0_TYPE_MASK              0x0c
39 #define P2P_NOISE_FLOOR_DBM_DEFAULT          (-96)
40 
41 static inline struct wlan_lmac_if_p2p_tx_ops *
wlan_psoc_get_p2p_tx_ops(struct wlan_objmgr_psoc * psoc)42 wlan_psoc_get_p2p_tx_ops(struct wlan_objmgr_psoc *psoc)
43 {
44 	return &(psoc->soc_cb.tx_ops->p2p);
45 }
46 
47 #ifdef FEATURE_P2P_LISTEN_OFFLOAD
tgt_p2p_register_lo_ev_handler(struct wlan_objmgr_psoc * psoc)48 QDF_STATUS tgt_p2p_register_lo_ev_handler(
49 	struct wlan_objmgr_psoc *psoc)
50 {
51 	struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
52 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
53 
54 	p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
55 	if (p2p_ops && p2p_ops->reg_lo_ev_handler) {
56 		status = p2p_ops->reg_lo_ev_handler(psoc, NULL);
57 		p2p_debug("register lo event, status:%d", status);
58 	}
59 
60 	return status;
61 }
62 
tgt_p2p_unregister_lo_ev_handler(struct wlan_objmgr_psoc * psoc)63 QDF_STATUS tgt_p2p_unregister_lo_ev_handler(
64 	struct wlan_objmgr_psoc *psoc)
65 {
66 	struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
67 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
68 
69 	p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
70 	if (p2p_ops && p2p_ops->unreg_lo_ev_handler) {
71 		status = p2p_ops->unreg_lo_ev_handler(psoc, NULL);
72 		p2p_debug("unregister lo event, status:%d", status);
73 	}
74 
75 	return status;
76 }
77 
tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc * psoc,struct p2p_lo_event * event_info)78 QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc,
79 			       struct p2p_lo_event *event_info)
80 {
81 	struct p2p_lo_stop_event *lo_stop_event;
82 	struct scheduler_msg msg = {0};
83 	struct p2p_soc_priv_obj *p2p_soc_obj;
84 	QDF_STATUS status;
85 
86 	p2p_debug("soc:%pK, event_info:%pK", psoc, event_info);
87 
88 	if (!psoc) {
89 		p2p_err("psoc context passed is NULL");
90 		if (event_info)
91 			qdf_mem_free(event_info);
92 		return QDF_STATUS_E_INVAL;
93 	}
94 
95 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
96 						WLAN_UMAC_COMP_P2P);
97 	if (!p2p_soc_obj) {
98 		p2p_err("p2p soc object is NULL");
99 		if (event_info)
100 			qdf_mem_free(event_info);
101 		return QDF_STATUS_E_INVAL;
102 	}
103 
104 	if (!event_info) {
105 		p2p_err("invalid lo stop event information");
106 		return QDF_STATUS_E_INVAL;
107 	}
108 
109 	lo_stop_event = qdf_mem_malloc(sizeof(*lo_stop_event));
110 	if (!lo_stop_event) {
111 		qdf_mem_free(event_info);
112 		return QDF_STATUS_E_NOMEM;
113 	}
114 
115 	lo_stop_event->p2p_soc_obj = p2p_soc_obj;
116 	lo_stop_event->lo_event = event_info;
117 	msg.type = P2P_EVENT_LO_STOPPED;
118 	msg.bodyptr = lo_stop_event;
119 	msg.callback = p2p_process_evt;
120 	msg.flush_callback = p2p_event_flush_callback;
121 	status = scheduler_post_message(QDF_MODULE_ID_P2P,
122 					QDF_MODULE_ID_P2P,
123 					QDF_MODULE_ID_TARGET_IF,
124 					&msg);
125 	if (QDF_IS_STATUS_ERROR(status)) {
126 		qdf_mem_free(lo_stop_event->lo_event);
127 		qdf_mem_free(lo_stop_event);
128 		p2p_err("post msg fail:%d", status);
129 	}
130 
131 	return status;
132 }
133 #endif /* FEATURE_P2P_LISTEN_OFFLOAD */
134 
135 QDF_STATUS
tgt_p2p_add_mac_addr_status_event_cb(struct wlan_objmgr_psoc * psoc,struct p2p_set_mac_filter_evt * event_info)136 tgt_p2p_add_mac_addr_status_event_cb(struct wlan_objmgr_psoc *psoc,
137 				     struct p2p_set_mac_filter_evt *event_info)
138 {
139 	struct p2p_mac_filter_rsp *mac_filter_rsp;
140 	struct scheduler_msg msg = {0};
141 	struct p2p_soc_priv_obj *p2p_soc_obj;
142 	QDF_STATUS status;
143 
144 	if (!psoc) {
145 		p2p_err("random_mac:psoc context passed is NULL");
146 		return QDF_STATUS_E_INVAL;
147 	}
148 	if (!event_info) {
149 		p2p_err("random_mac:invalid event_info");
150 		return QDF_STATUS_E_INVAL;
151 	}
152 
153 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(
154 				psoc, WLAN_UMAC_COMP_P2P);
155 	if (!p2p_soc_obj) {
156 		p2p_err("random_mac:p2p soc object is NULL");
157 		return QDF_STATUS_E_INVAL;
158 	}
159 
160 	mac_filter_rsp = qdf_mem_malloc(sizeof(*mac_filter_rsp));
161 	if (!mac_filter_rsp)
162 		return QDF_STATUS_E_NOMEM;
163 
164 	mac_filter_rsp->p2p_soc_obj = p2p_soc_obj;
165 	mac_filter_rsp->vdev_id = event_info->vdev_id;
166 	mac_filter_rsp->status = event_info->status;
167 
168 	msg.type = P2P_EVENT_ADD_MAC_RSP;
169 	msg.bodyptr = mac_filter_rsp;
170 	msg.callback = p2p_process_evt;
171 	status = scheduler_post_message(QDF_MODULE_ID_P2P, QDF_MODULE_ID_P2P,
172 					QDF_MODULE_ID_TARGET_IF, &msg);
173 	if (QDF_IS_STATUS_ERROR(status))
174 		qdf_mem_free(mac_filter_rsp);
175 
176 	return status;
177 }
178 
tgt_p2p_register_macaddr_rx_filter_evt_handler(struct wlan_objmgr_psoc * psoc,bool reg)179 QDF_STATUS tgt_p2p_register_macaddr_rx_filter_evt_handler(
180 	struct wlan_objmgr_psoc *psoc, bool reg)
181 {
182 	struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
183 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
184 
185 	p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
186 	if (p2p_ops && p2p_ops->reg_mac_addr_rx_filter_handler) {
187 		status = p2p_ops->reg_mac_addr_rx_filter_handler(psoc, reg);
188 		p2p_debug("register mac addr rx filter event,  register %d status:%d",
189 			  reg, status);
190 	}
191 
192 	return status;
193 }
194 
tgt_p2p_register_noa_ev_handler(struct wlan_objmgr_psoc * psoc)195 QDF_STATUS tgt_p2p_register_noa_ev_handler(
196 	struct wlan_objmgr_psoc *psoc)
197 {
198 	struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
199 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
200 
201 	p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
202 	if (p2p_ops && p2p_ops->reg_noa_ev_handler) {
203 		status = p2p_ops->reg_noa_ev_handler(psoc, NULL);
204 		p2p_debug("register noa event, status:%d", status);
205 	}
206 
207 	return status;
208 }
209 
tgt_p2p_unregister_noa_ev_handler(struct wlan_objmgr_psoc * psoc)210 QDF_STATUS tgt_p2p_unregister_noa_ev_handler(
211 	struct wlan_objmgr_psoc *psoc)
212 {
213 	struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
214 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
215 
216 	p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
217 	if (p2p_ops && p2p_ops->unreg_noa_ev_handler) {
218 		status = p2p_ops->unreg_noa_ev_handler(psoc, NULL);
219 		p2p_debug("unregister noa event, status:%d", status);
220 	}
221 
222 	return status;
223 }
224 
tgt_p2p_scan_event_cb(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)225 void tgt_p2p_scan_event_cb(struct wlan_objmgr_vdev *vdev,
226 	struct scan_event *event, void *arg)
227 {
228 	p2p_scan_event_cb(vdev, event, arg);
229 }
230 
tgt_p2p_mgmt_download_comp_cb(void * context,qdf_nbuf_t buf,bool free)231 QDF_STATUS tgt_p2p_mgmt_download_comp_cb(void *context,
232 	qdf_nbuf_t buf, bool free)
233 {
234 	p2p_debug("context:%pK, buf:%pK, free:%d", context,
235 		qdf_nbuf_data(buf), free);
236 
237 	qdf_nbuf_free(buf);
238 
239 	return QDF_STATUS_SUCCESS;
240 }
241 
tgt_p2p_mgmt_ota_comp_cb(void * context,qdf_nbuf_t buf,uint32_t status,void * tx_compl_params)242 QDF_STATUS tgt_p2p_mgmt_ota_comp_cb(void *context, qdf_nbuf_t buf,
243 	uint32_t status, void *tx_compl_params)
244 {
245 	struct p2p_tx_conf_event *tx_conf_event;
246 	struct scheduler_msg msg = {0};
247 	QDF_STATUS ret;
248 
249 	p2p_debug("context:%pK, buf:%pK, status:%d, tx complete params:%pK",
250 		context, buf, status, tx_compl_params);
251 
252 	if (!context) {
253 		p2p_err("invalid context");
254 		qdf_nbuf_free(buf);
255 		return QDF_STATUS_E_INVAL;
256 	}
257 
258 	tx_conf_event = qdf_mem_malloc(sizeof(*tx_conf_event));
259 	if (!tx_conf_event) {
260 		qdf_nbuf_free(buf);
261 		return QDF_STATUS_E_NOMEM;
262 	}
263 
264 	tx_conf_event->status = status;
265 	tx_conf_event->nbuf = buf;
266 	tx_conf_event->p2p_soc_obj = (struct p2p_soc_priv_obj *)context;
267 	msg.type = P2P_EVENT_MGMT_TX_ACK_CNF;
268 	msg.bodyptr = tx_conf_event;
269 	msg.callback = p2p_process_evt;
270 	msg.flush_callback = p2p_event_flush_callback;
271 	ret = scheduler_post_message(QDF_MODULE_ID_P2P,
272 				     QDF_MODULE_ID_P2P,
273 				     QDF_MODULE_ID_TARGET_IF,
274 				     &msg);
275 	if (QDF_IS_STATUS_ERROR(ret)) {
276 		qdf_mem_free(tx_conf_event);
277 		qdf_nbuf_free(buf);
278 		p2p_err("post msg fail:%d", status);
279 	}
280 
281 	return ret;
282 }
283 
tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_peer * peer,qdf_nbuf_t buf,struct mgmt_rx_event_params * mgmt_rx_params,enum mgmt_frame_type frm_type)284 QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
285 	struct wlan_objmgr_peer *peer, qdf_nbuf_t buf,
286 	struct mgmt_rx_event_params *mgmt_rx_params,
287 	enum mgmt_frame_type frm_type)
288 {
289 	struct p2p_rx_mgmt_frame *rx_mgmt;
290 	struct p2p_rx_mgmt_event *rx_mgmt_event;
291 	struct p2p_soc_priv_obj *p2p_soc_obj;
292 	struct scheduler_msg msg = {0};
293 	struct wlan_objmgr_vdev *vdev;
294 	uint32_t vdev_id;
295 	uint8_t *pdata;
296 	QDF_STATUS status;
297 
298 	p2p_debug("psoc:%pK, peer:%pK, type:%d", psoc, peer, frm_type);
299 
300 	if (!mgmt_rx_params) {
301 		p2p_err("mgmt rx params is NULL");
302 		qdf_nbuf_free(buf);
303 		return QDF_STATUS_E_INVAL;
304 	}
305 
306 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
307 			WLAN_UMAC_COMP_P2P);
308 	if (!p2p_soc_obj) {
309 		p2p_err("p2p ctx is NULL, drop this frame");
310 		qdf_nbuf_free(buf);
311 		return QDF_STATUS_E_FAILURE;
312 	}
313 
314 	if (!peer) {
315 		if (p2p_soc_obj->cur_roc_vdev_id == P2P_INVALID_VDEV_ID) {
316 			p2p_debug("vdev id of current roc invalid");
317 			qdf_nbuf_free(buf);
318 			return QDF_STATUS_E_FAILURE;
319 		} else {
320 			vdev_id = p2p_soc_obj->cur_roc_vdev_id;
321 		}
322 	} else {
323 		vdev = wlan_peer_get_vdev(peer);
324 		if (!vdev) {
325 			p2p_err("vdev is NULL in peer, drop this frame");
326 			qdf_nbuf_free(buf);
327 			return QDF_STATUS_E_FAILURE;
328 		}
329 		vdev_id = wlan_vdev_get_id(vdev);
330 	}
331 
332 	rx_mgmt_event = qdf_mem_malloc_atomic(sizeof(*rx_mgmt_event));
333 	if (!rx_mgmt_event) {
334 		p2p_debug_rl("Failed to allocate rx mgmt event");
335 		qdf_nbuf_free(buf);
336 		return QDF_STATUS_E_NOMEM;
337 	}
338 
339 	rx_mgmt = qdf_mem_malloc_atomic(sizeof(*rx_mgmt) +
340 			mgmt_rx_params->buf_len);
341 	if (!rx_mgmt) {
342 		p2p_debug_rl("Failed to allocate rx mgmt frame");
343 		qdf_nbuf_free(buf);
344 		return QDF_STATUS_E_NOMEM;
345 	}
346 
347 	pdata = (uint8_t *)qdf_nbuf_data(buf);
348 	rx_mgmt->frame_len = mgmt_rx_params->buf_len;
349 	rx_mgmt->rx_freq = mgmt_rx_params->chan_freq;
350 	rx_mgmt->vdev_id = vdev_id;
351 	rx_mgmt->frm_type = frm_type;
352 	rx_mgmt->rx_rssi = mgmt_rx_params->snr +
353 				P2P_NOISE_FLOOR_DBM_DEFAULT;
354 	rx_mgmt_event->rx_mgmt = rx_mgmt;
355 	rx_mgmt_event->p2p_soc_obj = p2p_soc_obj;
356 	qdf_mem_copy(rx_mgmt->buf, pdata, mgmt_rx_params->buf_len);
357 	msg.type = P2P_EVENT_RX_MGMT;
358 	msg.bodyptr = rx_mgmt_event;
359 	msg.callback = p2p_process_evt;
360 	msg.flush_callback = p2p_event_flush_callback;
361 	status = scheduler_post_message(QDF_MODULE_ID_P2P,
362 					QDF_MODULE_ID_P2P,
363 					QDF_MODULE_ID_TARGET_IF,
364 					&msg);
365 	if (QDF_IS_STATUS_ERROR(status)) {
366 		qdf_mem_free(rx_mgmt_event->rx_mgmt);
367 		qdf_mem_free(rx_mgmt_event);
368 		p2p_err("post msg fail:%d", status);
369 	}
370 	qdf_nbuf_free(buf);
371 
372 	return status;
373 }
374 
tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc * psoc,struct p2p_noa_info * event_info)375 QDF_STATUS  tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
376 		struct p2p_noa_info *event_info)
377 {
378 	struct p2p_noa_event *noa_event;
379 	struct scheduler_msg msg = {0};
380 	struct p2p_soc_priv_obj *p2p_soc_obj;
381 	QDF_STATUS status;
382 
383 	p2p_debug("soc:%pK, event_info:%pK", psoc, event_info);
384 
385 	if (!psoc) {
386 		p2p_err("psoc context passed is NULL");
387 		if (event_info)
388 			qdf_mem_free(event_info);
389 		return QDF_STATUS_E_INVAL;
390 	}
391 
392 	p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
393 			WLAN_UMAC_COMP_P2P);
394 	if (!p2p_soc_obj) {
395 		p2p_err("p2p soc object is NULL");
396 		if (event_info)
397 			qdf_mem_free(event_info);
398 		return QDF_STATUS_E_INVAL;
399 	}
400 
401 	if (!event_info) {
402 		p2p_err("invalid noa event information");
403 		return QDF_STATUS_E_INVAL;
404 	}
405 
406 	noa_event = qdf_mem_malloc(sizeof(*noa_event));
407 	if (!noa_event) {
408 		qdf_mem_free(event_info);
409 		return QDF_STATUS_E_NOMEM;
410 	}
411 
412 	noa_event->p2p_soc_obj = p2p_soc_obj;
413 	noa_event->noa_info = event_info;
414 	msg.type = P2P_EVENT_NOA;
415 	msg.bodyptr = noa_event;
416 	msg.callback = p2p_process_evt;
417 	msg.flush_callback = p2p_event_flush_callback;
418 	status = scheduler_post_message(QDF_MODULE_ID_P2P,
419 					QDF_MODULE_ID_P2P,
420 					QDF_MODULE_ID_TARGET_IF,
421 					&msg);
422 	if (QDF_IS_STATUS_ERROR(status)) {
423 		qdf_mem_free(noa_event->noa_info);
424 		qdf_mem_free(noa_event);
425 		p2p_err("post msg fail:%d", status);
426 	}
427 
428 	return status;
429 }
430