1 /*
2  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  *  DOC: wma_pasn_peer_api.c
19  *  This file contains PASN peer related operations.
20  */
21 
22 #include "wma.h"
23 #include "wma_api.h"
24 #include "wmi_unified_api.h"
25 #include "wmi_unified.h"
26 #include "qdf_types.h"
27 #include "qdf_mem.h"
28 #include "wma_types.h"
29 #include "wma_internal.h"
30 #include "wma_pasn_peer_api.h"
31 #include "wifi_pos_pasn_api.h"
32 #include "wifi_pos_api.h"
33 #include "init_deinit_lmac.h"
34 
35 QDF_STATUS
wma_pasn_peer_remove(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_addr,uint8_t vdev_id,bool no_fw_peer_delete)36 wma_pasn_peer_remove(struct wlan_objmgr_psoc *psoc,
37 		     struct qdf_mac_addr *peer_addr,
38 		     uint8_t vdev_id,  bool no_fw_peer_delete)
39 {
40 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
41 	struct peer_delete_cmd_params del_param = {0};
42 	QDF_STATUS qdf_status;
43 	uint8_t peer_vdev_id;
44 
45 	if (!wma) {
46 		wma_err("wma_handle is NULL");
47 		return QDF_STATUS_E_INVAL;
48 	}
49 
50 	if (!wma_objmgr_peer_exist(wma, peer_addr->bytes, &peer_vdev_id)) {
51 		wma_err("peer doesn't exist peer_addr " QDF_MAC_ADDR_FMT " vdevid %d",
52 			QDF_MAC_ADDR_REF(peer_addr->bytes), vdev_id);
53 		return QDF_STATUS_E_INVAL;
54 	}
55 
56 	if (peer_vdev_id != vdev_id) {
57 		wma_err("peer " QDF_MAC_ADDR_FMT " is on vdev id %d but delete req on vdevid %d",
58 			QDF_MAC_ADDR_REF(peer_addr->bytes),
59 			peer_vdev_id, vdev_id);
60 		return QDF_STATUS_E_INVAL;
61 	}
62 
63 	del_param.vdev_id = vdev_id;
64 	qdf_status = wmi_unified_peer_delete_send(wma->wmi_handle,
65 						  peer_addr->bytes,
66 						  &del_param);
67 	if (QDF_IS_STATUS_ERROR(qdf_status)) {
68 		wma_err("Peer delete could not be sent to firmware %d",
69 			qdf_status);
70 		qdf_status = QDF_STATUS_E_FAILURE;
71 	}
72 
73 	wma_remove_objmgr_peer(wma, wma->interfaces[vdev_id].vdev,
74 			       peer_addr->bytes);
75 
76 	return qdf_status;
77 }
78 
79 QDF_STATUS
wma_pasn_peer_create(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_addr,uint8_t vdev_id)80 wma_pasn_peer_create(struct wlan_objmgr_psoc *psoc,
81 		     struct qdf_mac_addr *peer_addr,
82 		     uint8_t vdev_id)
83 {
84 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
85 	target_resource_config *wlan_res_cfg;
86 	struct wlan_objmgr_peer *obj_peer;
87 	struct wma_target_req *wma_req;
88 	struct peer_create_rsp_params *peer_create_rsp;
89 	struct peer_create_params param;
90 	QDF_STATUS status = QDF_STATUS_SUCCESS;
91 	bool is_tgt_peer_conf_supported;
92 
93 	if (!wma) {
94 		wma_err("wma_handle is NULL");
95 		return QDF_STATUS_E_INVAL;
96 	}
97 
98 	wlan_res_cfg = lmac_get_tgt_res_cfg(psoc);
99 	if (!wlan_res_cfg) {
100 		wma_err("psoc target res cfg is null");
101 		return QDF_STATUS_E_INVAL;
102 	}
103 
104 	if (wma->interfaces[vdev_id].peer_count >=
105 	    wlan_res_cfg->num_peers) {
106 		wma_err("the peer count exceeds the limit %d",
107 			wma->interfaces[vdev_id].peer_count);
108 		return QDF_STATUS_E_FAILURE;
109 	}
110 
111 	if (qdf_is_macaddr_group(peer_addr) ||
112 	    qdf_is_macaddr_zero(peer_addr)) {
113 		wma_err("Invalid peer address received reject it");
114 		return QDF_STATUS_E_FAILURE;
115 	}
116 
117 	wma_acquire_wakelock(&wma->wmi_cmd_rsp_wake_lock,
118 			     WMA_PEER_CREATE_RESPONSE_TIMEOUT);
119 	/*
120 	 * The peer object should be created before sending the WMI peer
121 	 * create command to firmware.
122 	 */
123 	obj_peer = wma_create_objmgr_peer(wma, vdev_id, peer_addr->bytes,
124 					  WMI_PEER_TYPE_PASN, NULL);
125 	if (!obj_peer) {
126 		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
127 		return QDF_STATUS_E_FAILURE;
128 	}
129 
130 	param.peer_addr = peer_addr->bytes;
131 	param.peer_type = WMI_PEER_TYPE_PASN;
132 	param.vdev_id = vdev_id;
133 	if (wmi_unified_peer_create_send(wma->wmi_handle,
134 					 &param) != QDF_STATUS_SUCCESS) {
135 		wma_err("Unable to create peer in Target");
136 		wlan_objmgr_peer_obj_delete(obj_peer);
137 		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
138 
139 		return QDF_STATUS_E_FAILURE;
140 	}
141 
142 	/*
143 	 * If fw doesn't advertise peer create confirm event support,
144 	 * use the legacy peer create API
145 	 */
146 	is_tgt_peer_conf_supported =
147 		wlan_psoc_nif_fw_ext_cap_get(wma->psoc,
148 					     WLAN_SOC_F_PEER_CREATE_RESP);
149 	if (!is_tgt_peer_conf_supported) {
150 		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
151 		return QDF_STATUS_SUCCESS;
152 	}
153 
154 	peer_create_rsp = qdf_mem_malloc(sizeof(*peer_create_rsp));
155 	if (!peer_create_rsp) {
156 		wlan_objmgr_peer_obj_delete(obj_peer);
157 		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
158 		return QDF_STATUS_E_NOMEM;
159 	}
160 
161 	qdf_mem_copy(peer_create_rsp->peer_mac.bytes, peer_addr->bytes,
162 		     QDF_MAC_ADDR_SIZE);
163 	wma_req = wma_fill_hold_req(wma, vdev_id, WMA_PEER_CREATE_REQ,
164 				    WMA_PASN_PEER_CREATE_RESPONSE,
165 				    peer_create_rsp,
166 				    WMA_PEER_CREATE_RESPONSE_TIMEOUT);
167 	if (!wma_req) {
168 		wma_err("vdev:%d failed to fill peer create req", vdev_id);
169 		wma_remove_peer_req(wma, vdev_id, WMA_PASN_PEER_CREATE_RESPONSE,
170 				    peer_addr);
171 		wma_pasn_peer_remove(psoc, peer_addr, vdev_id, false);
172 		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
173 		qdf_mem_free(peer_create_rsp);
174 		return QDF_STATUS_E_FAILURE;
175 	}
176 
177 	wma_debug("Created ranging peer peer_addr " QDF_MAC_ADDR_FMT " vdev_id %d",
178 		  QDF_MAC_ADDR_REF(peer_addr->bytes), vdev_id);
179 
180 	return status;
181 }
182 
183 QDF_STATUS
wma_pasn_handle_peer_create_conf(tp_wma_handle wma,struct qdf_mac_addr * peer_mac,QDF_STATUS status,uint8_t vdev_id)184 wma_pasn_handle_peer_create_conf(tp_wma_handle wma,
185 				 struct qdf_mac_addr *peer_mac,
186 				 QDF_STATUS status, uint8_t vdev_id)
187 {
188 	struct wlan_lmac_if_wifi_pos_rx_ops *rx_ops;
189 	struct wlan_objmgr_vdev *vdev;
190 	enum QDF_OPMODE mode;
191 
192 	if (status)
193 		wma_pasn_peer_remove(wma->psoc, peer_mac, vdev_id,
194 				     QDF_IS_STATUS_ERROR(status));
195 
196 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
197 						    WLAN_LEGACY_WMA_ID);
198 	if (!vdev) {
199 		wma_err("Vdev is NULL");
200 		return QDF_STATUS_E_NULL_VALUE;
201 	}
202 
203 	mode = wlan_vdev_mlme_get_opmode(vdev);
204 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
205 
206 	/*
207 	 * Only in I-sta case update the wifi pos module to
208 	 * track the peer to initiate PASN authentication.
209 	 * For R-STA, return from here.
210 	 */
211 	if (mode != QDF_STA_MODE) {
212 		wma_debug("PASN opmode:%d is not sta", mode);
213 		return QDF_STATUS_SUCCESS;
214 	}
215 
216 	rx_ops = wifi_pos_get_rx_ops(wma->psoc);
217 	if (!rx_ops || !rx_ops->wifi_pos_ranging_peer_create_rsp_cb) {
218 		wma_err("%s is null",
219 			!rx_ops ? "rx_ops" : "rx_ops->ranging_peer_cb");
220 		return QDF_STATUS_E_NULL_VALUE;
221 	}
222 
223 	rx_ops->wifi_pos_ranging_peer_create_rsp_cb(wma->psoc, vdev_id,
224 						    peer_mac, status);
225 
226 	return QDF_STATUS_SUCCESS;
227 }
228 
229 QDF_STATUS
wma_resume_vdev_delete(tp_wma_handle wma,uint8_t vdev_id)230 wma_resume_vdev_delete(tp_wma_handle wma, uint8_t vdev_id)
231 {
232 	struct wlan_objmgr_vdev *vdev;
233 	struct mac_context *mac = wma->mac_context;
234 
235 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
236 						    WLAN_LEGACY_WMA_ID);
237 	if (!vdev) {
238 		wma_err("Vdev is NULL");
239 		return QDF_STATUS_E_NULL_VALUE;
240 	}
241 
242 	lim_pasn_peer_del_all_resp_vdev_delete_resume(mac, vdev);
243 
244 	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
245 
246 	return QDF_STATUS_SUCCESS;
247 }
248 
249 QDF_STATUS
wma_pasn_peer_delete_all_complete(struct wlan_objmgr_vdev * vdev)250 wma_pasn_peer_delete_all_complete(struct wlan_objmgr_vdev *vdev)
251 {
252 	tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
253 	struct wma_target_req *req_msg;
254 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
255 
256 	if (!wma) {
257 		wma_err("wma_handle is NULL");
258 		return QDF_STATUS_E_FAILURE;
259 	}
260 
261 	req_msg = wma_find_remove_req_msgtype(wma, vdev_id,
262 					      WMA_PASN_PEER_DELETE_REQUEST);
263 	if (!req_msg) {
264 		wma_debug("vdev:%d Failed to lookup pasn peer del req",
265 			  vdev_id);
266 		return QDF_STATUS_E_FAILURE;
267 	}
268 
269 	qdf_mc_timer_stop(&req_msg->event_timeout);
270 	qdf_mc_timer_destroy(&req_msg->event_timeout);
271 
272 	qdf_mem_free(req_msg);
273 
274 	wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
275 
276 	return wma_resume_vdev_delete(wma, vdev_id);
277 }
278 
279 QDF_STATUS
wma_delete_all_pasn_peers(tp_wma_handle wma,struct wlan_objmgr_vdev * vdev)280 wma_delete_all_pasn_peers(tp_wma_handle wma, struct wlan_objmgr_vdev *vdev)
281 {
282 	struct wlan_lmac_if_wifi_pos_rx_ops *rx_ops;
283 	struct wma_target_req *msg;
284 	QDF_STATUS status = QDF_STATUS_SUCCESS;
285 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
286 
287 	rx_ops = wifi_pos_get_rx_ops(wma->psoc);
288 	if (!rx_ops || !rx_ops->wifi_pos_vdev_delete_all_ranging_peers_cb) {
289 		wma_err("rx_ops is NULL");
290 		return QDF_STATUS_E_INVAL;
291 	}
292 
293 	wma_acquire_wakelock(&wma->wmi_cmd_rsp_wake_lock,
294 			     WMA_PEER_DELETE_RESPONSE_TIMEOUT);
295 	wma_err("Delete all ranging peers vdev:%d",
296 		wlan_vdev_get_id(vdev));
297 	status = rx_ops->wifi_pos_vdev_delete_all_ranging_peers_cb(vdev);
298 	if (QDF_IS_STATUS_ERROR(status)) {
299 		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
300 		wma_err("Delete all ranging peers failed");
301 		return status;
302 	}
303 
304 	msg = wma_fill_hold_req(wma, vdev_id,
305 				WMA_PASN_PEER_DELETE_REQUEST,
306 				WMA_PASN_PEER_DELETE_RESPONSE, NULL,
307 				WMA_PEER_DELETE_RESPONSE_TIMEOUT);
308 	if (!msg) {
309 		wma_err("Failed to allocate request for vdev_id %d", vdev_id);
310 		wma_remove_req(wma, vdev_id, WMA_PASN_PEER_DELETE_RESPONSE);
311 		wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
312 		wma_resume_vdev_delete(wma, vdev_id);
313 		return QDF_STATUS_E_FAILURE;
314 	}
315 
316 	return status;
317 }
318