1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 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: wma_nan_datapath.c
22  *
23  * WMA NAN Data path API implementation
24  */
25 
26 #include "wma.h"
27 #include "wma_api.h"
28 #include "wmi_unified_api.h"
29 #include "wmi_unified.h"
30 #include "wma_nan_datapath.h"
31 #include "wma_internal.h"
32 #include "cds_utils.h"
33 #include "cdp_txrx_peer_ops.h"
34 #include "cdp_txrx_tx_delay.h"
35 #include "cdp_txrx_misc.h"
36 #include <cdp_txrx_handle.h>
37 
wma_add_sta_ndi_mode(tp_wma_handle wma,tpAddStaParams add_sta)38 QDF_STATUS wma_add_sta_ndi_mode(tp_wma_handle wma, tpAddStaParams add_sta)
39 {
40 	enum ol_txrx_peer_state state = OL_TXRX_PEER_STATE_CONN;
41 	uint8_t pdev_id = WMI_PDEV_ID_SOC;
42 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
43 	QDF_STATUS status;
44 	struct wma_txrx_node *iface;
45 
46 	iface = &wma->interfaces[add_sta->smesessionId];
47 	wma_debug("vdev: %d, peer_mac_addr: "QDF_MAC_ADDR_FMT,
48 		add_sta->smesessionId, QDF_MAC_ADDR_REF(add_sta->staMac));
49 
50 	if (cdp_find_peer_exist_on_vdev(soc, add_sta->smesessionId,
51 					add_sta->staMac)) {
52 		wma_err("NDI peer already exists, peer_addr "QDF_MAC_ADDR_FMT,
53 			 QDF_MAC_ADDR_REF(add_sta->staMac));
54 		add_sta->status = QDF_STATUS_E_EXISTS;
55 		goto send_rsp;
56 	}
57 
58 	/*
59 	 * The code above only checks the peer existence on its own vdev.
60 	 * Need to check whether the peer exists on other vDevs because firmware
61 	 * can't create the peer if the peer with same MAC address already
62 	 * exists on the pDev. As this peer belongs to other vDevs, just return
63 	 * here.
64 	 */
65 	if (cdp_find_peer_exist(soc, pdev_id, add_sta->staMac)) {
66 		wma_err("peer exists on other vdev with peer_addr "QDF_MAC_ADDR_FMT,
67 			 QDF_MAC_ADDR_REF(add_sta->staMac));
68 		add_sta->status = QDF_STATUS_E_EXISTS;
69 		goto send_rsp;
70 	}
71 
72 	status = wma_create_peer(wma, add_sta->staMac,
73 				 WMI_PEER_TYPE_NAN_DATA, add_sta->smesessionId,
74 				 NULL, false);
75 	if (status != QDF_STATUS_SUCCESS) {
76 		wma_err("Failed to create peer for "QDF_MAC_ADDR_FMT,
77 			 QDF_MAC_ADDR_REF(add_sta->staMac));
78 		add_sta->status = status;
79 		goto send_rsp;
80 	}
81 
82 	if (!cdp_find_peer_exist_on_vdev(soc, add_sta->smesessionId,
83 					 add_sta->staMac)) {
84 		wma_err("Failed to find peer handle using peer mac "QDF_MAC_ADDR_FMT,
85 			 QDF_MAC_ADDR_REF(add_sta->staMac));
86 		add_sta->status = QDF_STATUS_E_FAILURE;
87 		wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId,
88 				false);
89 		goto send_rsp;
90 	}
91 
92 	wma_debug("Moving peer "QDF_MAC_ADDR_FMT" to state %d",
93 		  QDF_MAC_ADDR_REF(add_sta->staMac), state);
94 	cdp_peer_state_update(soc, add_sta->staMac, state);
95 
96 	add_sta->nss    = iface->nss;
97 	add_sta->status = QDF_STATUS_SUCCESS;
98 send_rsp:
99 	status = add_sta->status;
100 	wma_debug("Sending add sta rsp to umac (mac:"QDF_MAC_ADDR_FMT", status:%d)",
101 		  QDF_MAC_ADDR_REF(add_sta->staMac), add_sta->status);
102 
103 	wma_send_msg_high_priority(wma, WMA_ADD_STA_RSP, (void *)add_sta, 0);
104 
105 	return status;
106 }
107 
wma_delete_sta_req_ndi_mode(tp_wma_handle wma,tpDeleteStaParams del_sta)108 QDF_STATUS wma_delete_sta_req_ndi_mode(tp_wma_handle wma,
109 				       tpDeleteStaParams del_sta)
110 {
111 	QDF_STATUS status;
112 
113 	status = wma_remove_peer(wma, del_sta->staMac,
114 				 del_sta->smesessionId, false);
115 	del_sta->status = QDF_STATUS_SUCCESS;
116 
117 	if (del_sta->respReqd) {
118 		wma_debug("Sending del rsp to umac (status: %d)",
119 				del_sta->status);
120 		wma_send_msg_high_priority(wma, WMA_DELETE_STA_RSP, del_sta, 0);
121 	} else {
122 		wma_debug("NDI Del Sta resp not needed");
123 		qdf_mem_free(del_sta);
124 	}
125 
126 	return status;
127 }
128