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