1 /*
2  * Copyright (c) 2022-2024 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  * DOC: wifi_pos_pasn_api.c
18  * This file defines the 11az PASN authentication related APIs for wifi_pos
19  * component.
20  */
21 
22 #include <wlan_lmac_if_def.h>
23 #include "wifi_pos_api.h"
24 #include "wifi_pos_pasn_api.h"
25 #include "wifi_pos_utils_i.h"
26 #include "wifi_pos_main_i.h"
27 #include "os_if_wifi_pos.h"
28 #include "os_if_wifi_pos_utils.h"
29 #include "target_if_wifi_pos.h"
30 #include "target_if_wifi_pos_rx_ops.h"
31 #include "wlan_objmgr_cmn.h"
32 #include "wlan_objmgr_global_obj.h"
33 #include "wlan_objmgr_psoc_obj.h"
34 #include "wlan_objmgr_peer_obj.h"
35 #include "wlan_lmac_if_def.h"
36 #include "wlan_vdev_mgr_tgt_if_tx_api.h"
37 
38 #if defined(WIFI_POS_CONVERGED) && defined(WLAN_FEATURE_RTT_11AZ_SUPPORT)
wifi_pos_get_pasn_peer_count(struct wlan_objmgr_vdev * vdev)39 uint8_t wifi_pos_get_pasn_peer_count(struct wlan_objmgr_vdev *vdev)
40 {
41 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
42 
43 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
44 	if (!vdev_pos_obj) {
45 		wifi_pos_err("Wifi pos vdev priv obj is null");
46 		return 0;
47 	}
48 
49 	return vdev_pos_obj->num_pasn_peers;
50 }
51 
wifi_pos_update_pasn_peer_count(struct wlan_objmgr_vdev * vdev,bool is_increment)52 void wifi_pos_update_pasn_peer_count(struct wlan_objmgr_vdev *vdev,
53 				     bool is_increment)
54 {
55 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
56 
57 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
58 	if (!vdev_pos_obj) {
59 		wifi_pos_err("Wifi pos vdev priv obj is null");
60 		return;
61 	}
62 
63 	if (is_increment)
64 		vdev_pos_obj->num_pasn_peers++;
65 	else if (vdev_pos_obj->num_pasn_peers)
66 		vdev_pos_obj->num_pasn_peers--;
67 
68 	wifi_pos_debug("Pasn peer count:%d", vdev_pos_obj->num_pasn_peers);
69 }
70 #endif
71 
wifi_pos_set_11az_failed_peers(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * mac_addr)72 void wifi_pos_set_11az_failed_peers(struct wlan_objmgr_vdev *vdev,
73 				    struct qdf_mac_addr *mac_addr)
74 {
75 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
76 	struct wifi_pos_11az_context *pasn_context;
77 	uint8_t i;
78 
79 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
80 	if (!vdev_pos_obj) {
81 		wifi_pos_err("Wifi pos vdev priv obj is null");
82 		return;
83 	}
84 
85 	pasn_context = &vdev_pos_obj->pasn_context;
86 	if (!pasn_context->num_failed_peers)
87 		goto add_failed_peer;
88 
89 	for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) {
90 		if (qdf_is_macaddr_equal(mac_addr,
91 					 &pasn_context->failed_peer_list[i])) {
92 			wifi_pos_debug("Peer: " QDF_MAC_ADDR_FMT " already exists in failed list",
93 				       QDF_MAC_ADDR_REF(mac_addr->bytes));
94 			return;
95 		}
96 	}
97 
98 add_failed_peer:
99 	for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) {
100 		if (qdf_is_macaddr_broadcast(
101 					&pasn_context->failed_peer_list[i])) {
102 			qdf_copy_macaddr(&pasn_context->failed_peer_list[i],
103 					 mac_addr);
104 			pasn_context->num_failed_peers++;
105 			wifi_pos_debug("Added failed peer: " QDF_MAC_ADDR_FMT " at idx[%d]",
106 				       QDF_MAC_ADDR_REF(mac_addr->bytes), i);
107 
108 			return;
109 		}
110 	}
111 
112 	wifi_pos_debug("Not able to set failed peer");
113 }
114 
wifi_pos_add_peer_to_list(struct wlan_objmgr_vdev * vdev,struct wlan_pasn_request * req,bool is_peer_create_required)115 void wifi_pos_add_peer_to_list(struct wlan_objmgr_vdev *vdev,
116 			       struct wlan_pasn_request *req,
117 			       bool is_peer_create_required)
118 {
119 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
120 	struct wifi_pos_11az_context *pasn_context;
121 	struct wlan_pasn_request *secure_list, *unsecure_list, *dst_entry;
122 	uint8_t i;
123 
124 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)
125 		return;
126 
127 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
128 	if (!vdev_pos_obj) {
129 		wifi_pos_err("Wifi pos vdev priv obj is null");
130 		return;
131 	}
132 
133 	pasn_context = &vdev_pos_obj->pasn_context;
134 	secure_list = pasn_context->secure_peer_list;
135 	unsecure_list = pasn_context->unsecure_peer_list;
136 
137 	/* Find the 1st empty slot and copy the entry to peer list */
138 	for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) {
139 		if (req->peer_type == WLAN_WIFI_POS_PASN_SECURE_PEER)
140 			dst_entry = &secure_list[i];
141 		else
142 			dst_entry = &unsecure_list[i];
143 
144 		/* Current slot is not empty */
145 		if (!qdf_is_macaddr_broadcast(&dst_entry->peer_mac))
146 			continue;
147 
148 		*dst_entry = *req;
149 		if (is_peer_create_required)
150 			pasn_context->num_pending_peer_creation++;
151 
152 		if (req->peer_type == WLAN_WIFI_POS_PASN_SECURE_PEER)
153 			pasn_context->num_secure_peers++;
154 		else
155 			pasn_context->num_unsecure_peers++;
156 
157 		wifi_pos_debug("Added %s peer: " QDF_MAC_ADDR_FMT " at idx[%d]",
158 			       (req->peer_type == WLAN_WIFI_POS_PASN_SECURE_PEER) ? "secure" : "insecure",
159 			       QDF_MAC_ADDR_REF(dst_entry->peer_mac.bytes), i);
160 
161 		break;
162 	}
163 }
164 
165 /**
166  * wifi_pos_move_peers_to_fail_list  - Move the peers in secure/insecure list
167  * to failed peer list
168  * @vdev: Vdev pointer
169  * @peer_mac: Peer mac address
170  * @peer_type: Secure or insecure PASN peer
171  *
172  * Return: None
173  */
174 static
wifi_pos_move_peers_to_fail_list(struct wlan_objmgr_vdev * vdev,struct qdf_mac_addr * peer_mac,enum wifi_pos_pasn_peer_type peer_type)175 void wifi_pos_move_peers_to_fail_list(struct wlan_objmgr_vdev *vdev,
176 				      struct qdf_mac_addr *peer_mac,
177 				      enum wifi_pos_pasn_peer_type peer_type)
178 {
179 	uint8_t i;
180 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
181 	struct wifi_pos_11az_context *pasn_context;
182 	struct wlan_pasn_request *secure_list, *unsecure_list, *list = NULL;
183 	struct qdf_mac_addr entry_to_copy;
184 
185 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)
186 		return;
187 
188 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
189 	if (!vdev_pos_obj) {
190 		wifi_pos_err("Wifi pos vdev priv obj is null");
191 		return;
192 	}
193 
194 	pasn_context = &vdev_pos_obj->pasn_context;
195 
196 	/*
197 	 * Broadcast mac address will be sent by caller when initiate
198 	 * external auth fails and to move the entire list to failed
199 	 * peers list
200 	 */
201 	if (qdf_is_macaddr_broadcast(peer_mac)) {
202 		/* Clear the entire list and move it to failed peers list */
203 		if (peer_type == WLAN_WIFI_POS_PASN_SECURE_PEER)
204 			list = pasn_context->secure_peer_list;
205 		else if (peer_type == WLAN_WIFI_POS_PASN_UNSECURE_PEER)
206 			list = pasn_context->unsecure_peer_list;
207 
208 		if (!list) {
209 			wifi_pos_err("No Valid list exists");
210 			return;
211 		}
212 
213 		for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) {
214 			/*
215 			 * if valid entry exist in the list, set that mac
216 			 * address to failed list and clear that mac from the
217 			 * secure/insecure list
218 			 */
219 			if (!qdf_is_macaddr_broadcast(&list[i].peer_mac)) {
220 				wifi_pos_set_11az_failed_peers(
221 						vdev, &list[i].peer_mac);
222 				qdf_set_macaddr_broadcast(&list[i].peer_mac);
223 			}
224 		}
225 
226 		return;
227 	}
228 
229 	secure_list = pasn_context->secure_peer_list;
230 	unsecure_list = pasn_context->unsecure_peer_list;
231 	/*
232 	 * This condition is hit when peer create confirm for a pasn
233 	 * peer is received with failure status
234 	 */
235 	for (i = 0; i < WLAN_MAX_11AZ_PEERS; i++) {
236 		/*
237 		 * Clear the individual entry that exist for the given
238 		 * mac address in secure/insecure list
239 		 */
240 		if (qdf_is_macaddr_equal(peer_mac, &secure_list[i].peer_mac)) {
241 			entry_to_copy = secure_list[i].peer_mac;
242 			qdf_set_macaddr_broadcast(&secure_list[i].peer_mac);
243 			pasn_context->num_secure_peers--;
244 		} else if (qdf_is_macaddr_equal(peer_mac,
245 			   &unsecure_list[i].peer_mac)) {
246 			entry_to_copy = unsecure_list[i].peer_mac;
247 			qdf_set_macaddr_broadcast(&unsecure_list[i].peer_mac);
248 			pasn_context->num_unsecure_peers--;
249 		} else {
250 			continue;
251 		}
252 
253 		wifi_pos_set_11az_failed_peers(vdev, &entry_to_copy);
254 		break;
255 	}
256 }
257 
258 static QDF_STATUS
wifi_pos_request_external_pasn_auth(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct wlan_pasn_request * peer_list,uint8_t num_peers)259 wifi_pos_request_external_pasn_auth(struct wlan_objmgr_psoc *psoc,
260 				    struct wlan_objmgr_vdev *vdev,
261 				    struct wlan_pasn_request *peer_list,
262 				    uint8_t num_peers)
263 {
264 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
265 	struct wifi_pos_osif_ops *osif_cb;
266 	QDF_STATUS status;
267 
268 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)
269 		return QDF_STATUS_E_INVAL;
270 
271 	osif_cb = wifi_pos_get_osif_callbacks();
272 	if (!osif_cb || !osif_cb->osif_initiate_pasn_cb) {
273 		wifi_pos_err("OSIF %s cb is NULL",
274 			     !osif_cb ? "" : "PASN");
275 		return QDF_STATUS_E_FAILURE;
276 	}
277 
278 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
279 	if (!vdev_pos_obj) {
280 		wifi_pos_err("Wifi pos vdev priv obj is null");
281 		return QDF_STATUS_E_FAILURE;
282 	}
283 
284 	status = osif_cb->osif_initiate_pasn_cb(vdev, peer_list,
285 						num_peers, true);
286 	if (QDF_IS_STATUS_ERROR(status))
287 		wifi_pos_err("Initiate PASN auth failed");
288 
289 	return status;
290 }
291 
292 static QDF_STATUS
wifi_pos_request_flush_pasn_keys(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct wlan_pasn_request * peer_list,uint8_t num_peers)293 wifi_pos_request_flush_pasn_keys(struct wlan_objmgr_psoc *psoc,
294 				 struct wlan_objmgr_vdev *vdev,
295 				 struct wlan_pasn_request *peer_list,
296 				 uint8_t num_peers)
297 {
298 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
299 	struct wifi_pos_osif_ops *osif_cb;
300 	QDF_STATUS status;
301 
302 	osif_cb = wifi_pos_get_osif_callbacks();
303 	if (!osif_cb || !osif_cb->osif_initiate_pasn_cb) {
304 		wifi_pos_err("OSIF %s cb is NULL",
305 			     !osif_cb ? "" : "PASN");
306 		return QDF_STATUS_E_FAILURE;
307 	}
308 
309 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
310 	if (!vdev_pos_obj) {
311 		wifi_pos_err("Wifi pos vdev priv obj is null");
312 		return QDF_STATUS_E_FAILURE;
313 	}
314 
315 	status = osif_cb->osif_initiate_pasn_cb(vdev, peer_list, num_peers,
316 						false);
317 
318 	return status;
319 }
320 
321 static QDF_STATUS
wifi_pos_check_and_initiate_pasn_authentication(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct wifi_pos_11az_context * pasn_ctx)322 wifi_pos_check_and_initiate_pasn_authentication(struct wlan_objmgr_psoc *psoc,
323 						struct wlan_objmgr_vdev *vdev,
324 						struct wifi_pos_11az_context *pasn_ctx)
325 {
326 	struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT;
327 	QDF_STATUS status;
328 
329 	if (pasn_ctx->num_pending_peer_creation ||
330 	    !pasn_ctx->num_secure_peers)
331 		return QDF_STATUS_SUCCESS;
332 
333 	status = wifi_pos_request_external_pasn_auth(psoc, vdev,
334 						     pasn_ctx->secure_peer_list,
335 						     pasn_ctx->num_secure_peers);
336 	if (QDF_IS_STATUS_ERROR(status)) {
337 		wifi_pos_err("Initiate Pasn Authentication failed");
338 		wifi_pos_move_peers_to_fail_list(vdev, &bcast_mac,
339 						 WLAN_WIFI_POS_PASN_SECURE_PEER);
340 		/* TODO send PASN_STATUS cmd from here */
341 	}
342 
343 	return status;
344 }
345 
wifi_pos_handle_ranging_peer_create(struct wlan_objmgr_psoc * psoc,struct wlan_pasn_request * req,uint8_t vdev_id,uint8_t total_entries)346 QDF_STATUS wifi_pos_handle_ranging_peer_create(struct wlan_objmgr_psoc *psoc,
347 					       struct wlan_pasn_request *req,
348 					       uint8_t vdev_id,
349 					       uint8_t total_entries)
350 {
351 	struct wifi_pos_legacy_ops *legacy_cb;
352 	struct wlan_objmgr_peer *peer;
353 	struct wlan_objmgr_vdev *vdev;
354 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
355 	struct wifi_pos_11az_context *pasn_context;
356 	QDF_STATUS status = QDF_STATUS_SUCCESS;
357 	uint8_t i;
358 
359 	legacy_cb = wifi_pos_get_legacy_ops();
360 	if (!legacy_cb || !legacy_cb->pasn_peer_create_cb) {
361 		wifi_pos_err("legacy callbacks is not registered");
362 		return QDF_STATUS_E_FAILURE;
363 	}
364 
365 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
366 						    WLAN_WIFI_POS_CORE_ID);
367 	if (!vdev) {
368 		wifi_pos_err("Vdev object is null");
369 		return QDF_STATUS_E_FAILURE;
370 	}
371 
372 	wifi_pos_debug("vdev:%d PASN peer create request received. Num peers:%d",
373 		       vdev_id, total_entries);
374 	for (i = 0; i < total_entries; i++) {
375 		peer = wlan_objmgr_get_peer_by_mac(psoc, req[i].peer_mac.bytes,
376 						   WLAN_WIFI_POS_CORE_ID);
377 		/*
378 		 * If already PASN peer is found, then this is a request to
379 		 * initiate PASN authentication alone and not to send
380 		 * peer create to fw
381 		 */
382 		if (peer &&
383 		    (wlan_peer_get_peer_type(peer) == WLAN_PEER_RTT_PASN)) {
384 			wifi_pos_debug("PASN Peer: " QDF_MAC_ADDR_FMT "already exists",
385 				       QDF_MAC_ADDR_REF(req[i].peer_mac.bytes));
386 			wifi_pos_add_peer_to_list(vdev, &req[i], false);
387 
388 			if (req[i].is_ltf_keyseed_required)
389 				wifi_pos_set_peer_ltf_keyseed_required(peer,
390 								       true);
391 			else
392 				wifi_pos_set_peer_ltf_keyseed_required(peer,
393 								       false);
394 			wlan_objmgr_peer_release_ref(peer,
395 						     WLAN_WIFI_POS_CORE_ID);
396 			continue;
397 		} else if (peer) {
398 			/*
399 			 * If a peer with given mac address already exists which
400 			 * is not a PASN peer, then move this peer to failed
401 			 * list
402 			 */
403 			wifi_pos_debug("Peer: " QDF_MAC_ADDR_FMT "of type:%d already exist",
404 				       QDF_MAC_ADDR_REF(req[i].peer_mac.bytes),
405 				       wlan_peer_get_peer_type(peer));
406 			wifi_pos_set_11az_failed_peers(vdev, &req[i].peer_mac);
407 			wlan_objmgr_peer_release_ref(peer,
408 						     WLAN_WIFI_POS_CORE_ID);
409 			continue;
410 		}
411 
412 		status = legacy_cb->pasn_peer_create_cb(psoc, &req[i].peer_mac,
413 							vdev_id);
414 		if (QDF_IS_STATUS_ERROR(status)) {
415 			wifi_pos_set_11az_failed_peers(vdev, &req[i].peer_mac);
416 			continue;
417 		}
418 
419 		wifi_pos_update_pasn_peer_count(vdev, true);
420 		if (req[i].is_ltf_keyseed_required) {
421 			peer = wlan_objmgr_get_peer_by_mac(psoc,
422 							   req[i].peer_mac.bytes,
423 							   WLAN_WIFI_POS_CORE_ID);
424 			if (peer) {
425 				wifi_pos_set_peer_ltf_keyseed_required(peer,
426 								       true);
427 				wlan_objmgr_peer_release_ref(peer,
428 							     WLAN_WIFI_POS_CORE_ID);
429 			}
430 		}
431 
432 		/* Track the peers only for I-STA mode */
433 		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE)
434 			wifi_pos_add_peer_to_list(vdev, &req[i], true);
435 	}
436 
437 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)
438 		goto end;
439 
440 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
441 	if (!vdev_pos_obj) {
442 		wifi_pos_err("Wifi pos vdev priv obj is null");
443 		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
444 		return QDF_STATUS_E_FAILURE;
445 	}
446 
447 	/*
448 	 * If peer already exists for all the entries provided in the request,
449 	 * then fw peer create will not be sent again. Just the secure list
450 	 * will be updated and num_pending_peer_creation will be 0.
451 	 * In this case initiate the PASN auth directly without waiting for
452 	 * peer create response.
453 	 */
454 	pasn_context = &vdev_pos_obj->pasn_context;
455 	status = wifi_pos_check_and_initiate_pasn_authentication(psoc, vdev,
456 								 pasn_context);
457 end:
458 	wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
459 
460 	return status;
461 }
462 
463 QDF_STATUS
wifi_pos_handle_ranging_peer_create_rsp(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,struct qdf_mac_addr * peer_mac,uint8_t peer_create_status)464 wifi_pos_handle_ranging_peer_create_rsp(struct wlan_objmgr_psoc *psoc,
465 					uint8_t vdev_id,
466 					struct qdf_mac_addr *peer_mac,
467 					uint8_t peer_create_status)
468 {
469 	struct wlan_objmgr_vdev *vdev;
470 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
471 	struct wifi_pos_11az_context *pasn_context;
472 	QDF_STATUS status = QDF_STATUS_SUCCESS;
473 
474 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
475 						    WLAN_WIFI_POS_CORE_ID);
476 	if (!vdev) {
477 		wifi_pos_err("Vdev object is null");
478 		return QDF_STATUS_E_FAILURE;
479 	}
480 
481 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
482 	if (!vdev_pos_obj) {
483 		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
484 		wifi_pos_err("Wifi pos vdev priv obj is null");
485 		return QDF_STATUS_E_FAILURE;
486 	}
487 
488 	pasn_context = &vdev_pos_obj->pasn_context;
489 	if (pasn_context->num_pending_peer_creation)
490 		pasn_context->num_pending_peer_creation--;
491 
492 	wifi_pos_debug("Received peer create response for " QDF_MAC_ADDR_FMT " status:%d pending_count:%d",
493 		       QDF_MAC_ADDR_REF(peer_mac->bytes), peer_create_status,
494 		       pasn_context->num_pending_peer_creation);
495 
496 	if (peer_create_status) {
497 		wifi_pos_move_peers_to_fail_list(vdev, peer_mac,
498 						 WLAN_WIFI_POS_PASN_PEER_TYPE_MAX);
499 		wifi_pos_update_pasn_peer_count(vdev, false);
500 	}
501 
502 	status = wifi_pos_check_and_initiate_pasn_authentication(psoc, vdev,
503 								 pasn_context);
504 	wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
505 
506 	return QDF_STATUS_SUCCESS;
507 }
508 
wifi_pos_handle_ranging_peer_delete(struct wlan_objmgr_psoc * psoc,struct wlan_pasn_request * req,uint8_t vdev_id,uint8_t total_entries)509 QDF_STATUS wifi_pos_handle_ranging_peer_delete(struct wlan_objmgr_psoc *psoc,
510 					       struct wlan_pasn_request *req,
511 					       uint8_t vdev_id,
512 					       uint8_t total_entries)
513 {
514 	struct wifi_pos_legacy_ops *legacy_cb;
515 	struct wlan_objmgr_peer *peer;
516 	struct wlan_pasn_request *del_peer_list;
517 	struct wlan_objmgr_vdev *vdev;
518 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
519 	bool no_fw_peer_delete;
520 	uint8_t peer_count = 0, i;
521 	QDF_STATUS status = QDF_STATUS_SUCCESS;
522 
523 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
524 						    WLAN_WIFI_POS_CORE_ID);
525 	if (!vdev) {
526 		wifi_pos_err("Vdev object is null");
527 		return QDF_STATUS_E_FAILURE;
528 	}
529 
530 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
531 	if (!vdev_pos_obj) {
532 		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
533 		wifi_pos_err("Wifi pos vdev priv obj is null");
534 		return QDF_STATUS_E_FAILURE;
535 	}
536 
537 	if (vdev_pos_obj->is_delete_all_pasn_peer_in_progress) {
538 		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
539 		wifi_pos_err("Vdev delete all peer in progress. Ignore individual peer delete");
540 		return QDF_STATUS_SUCCESS;
541 	}
542 	wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
543 
544 	legacy_cb = wifi_pos_get_legacy_ops();
545 	if (!legacy_cb || !legacy_cb->pasn_peer_delete_cb) {
546 		wifi_pos_err("legacy callback is not registered");
547 		return QDF_STATUS_E_FAILURE;
548 	}
549 
550 	del_peer_list = qdf_mem_malloc(sizeof(*del_peer_list) * total_entries);
551 	if (!del_peer_list)
552 		return QDF_STATUS_E_NOMEM;
553 
554 	for (i = 0; i < total_entries; i++) {
555 		peer = wlan_objmgr_get_peer_by_mac(psoc, req[i].peer_mac.bytes,
556 						   WLAN_WIFI_POS_CORE_ID);
557 		if (peer &&
558 		    (wlan_peer_get_peer_type(peer) == WLAN_PEER_RTT_PASN)) {
559 			no_fw_peer_delete = WIFI_POS_IS_PEER_ALREADY_DELETED(
560 							req[i].control_flags);
561 			wifi_pos_debug("Delete PASN Peer: " QDF_MAC_ADDR_FMT,
562 				       QDF_MAC_ADDR_REF(req[i].peer_mac.bytes));
563 
564 			del_peer_list[peer_count] = req[i];
565 			peer_count++;
566 
567 			status = legacy_cb->pasn_peer_delete_cb(
568 					psoc, &req[i].peer_mac,
569 					vdev_id, no_fw_peer_delete);
570 
571 			wlan_objmgr_peer_release_ref(peer,
572 						     WLAN_WIFI_POS_CORE_ID);
573 			continue;
574 		} else {
575 			wifi_pos_debug("PASN Peer: " QDF_MAC_ADDR_FMT "doesn't exist",
576 				       QDF_MAC_ADDR_REF(req[i].peer_mac.bytes));
577 			if (peer)
578 				wlan_objmgr_peer_release_ref(
579 						peer, WLAN_WIFI_POS_CORE_ID);
580 
581 			continue;
582 		}
583 	}
584 
585 	if (!peer_count) {
586 		wifi_pos_debug("No Peers to delete ");
587 		goto no_peer;
588 	}
589 
590 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
591 						    WLAN_WIFI_POS_CORE_ID);
592 	if (!vdev) {
593 		wifi_pos_err("Vdev object is null");
594 		qdf_mem_free(del_peer_list);
595 		return QDF_STATUS_E_FAILURE;
596 	}
597 
598 	status = wifi_pos_request_flush_pasn_keys(psoc, vdev,
599 						  del_peer_list,
600 						  peer_count);
601 	if (QDF_IS_STATUS_ERROR(status))
602 		wifi_pos_err("Failed to indicate peer deauth to userspace");
603 
604 	wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
605 
606 no_peer:
607 	qdf_mem_free(del_peer_list);
608 
609 	return status;
610 }
611 
612 QDF_STATUS
wifi_pos_send_pasn_auth_status(struct wlan_objmgr_psoc * psoc,struct wlan_pasn_auth_status * data)613 wifi_pos_send_pasn_auth_status(struct wlan_objmgr_psoc *psoc,
614 			       struct wlan_pasn_auth_status *data)
615 {
616 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
617 	QDF_STATUS status;
618 	uint8_t vdev_id = data->vdev_id;
619 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
620 	struct wifi_pos_11az_context *pasn_context;
621 	struct wlan_objmgr_vdev *vdev;
622 	uint8_t i, failed_peers_counter = 0, total_peers_to_fill = 0;
623 
624 	tx_ops = wifi_pos_get_tx_ops(psoc);
625 	if (!tx_ops || !tx_ops->send_rtt_pasn_auth_status) {
626 		wifi_pos_err("%s is null",
627 			     tx_ops ? "Tx_ops" : "send_auth_status cb");
628 		return QDF_STATUS_E_FAILURE;
629 	}
630 
631 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
632 						    WLAN_WIFI_POS_CORE_ID);
633 	if (!vdev) {
634 		wifi_pos_err("vdev obj is null");
635 		return QDF_STATUS_E_FAILURE;
636 	}
637 
638 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
639 	if (!vdev_pos_obj) {
640 		wifi_pos_err("Wifi pos vdev priv obj is null");
641 		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
642 		return QDF_STATUS_E_FAILURE;
643 	}
644 
645 	pasn_context = &vdev_pos_obj->pasn_context;
646 	total_peers_to_fill = data->num_peers + pasn_context->num_failed_peers;
647 	for (i = data->num_peers; i < total_peers_to_fill; i++) {
648 		data->auth_status[i].peer_mac =
649 			pasn_context->failed_peer_list[failed_peers_counter];
650 		data->auth_status[i].status =
651 			WLAN_PASN_AUTH_STATUS_PEER_CREATE_FAILED;
652 
653 		failed_peers_counter++;
654 		if (failed_peers_counter >= pasn_context->num_failed_peers)
655 			break;
656 	}
657 
658 	status = tx_ops->send_rtt_pasn_auth_status(psoc, data);
659 	if (QDF_IS_STATUS_ERROR(status))
660 		wifi_pos_err("Failed to send PASN authentication status");
661 
662 	wifi_pos_init_11az_context(vdev_pos_obj);
663 	wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
664 
665 	return status;
666 }
667 
668 QDF_STATUS
wifi_pos_send_pasn_peer_deauth(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_mac)669 wifi_pos_send_pasn_peer_deauth(struct wlan_objmgr_psoc *psoc,
670 			       struct qdf_mac_addr *peer_mac)
671 {
672 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
673 	QDF_STATUS status;
674 
675 	tx_ops = wifi_pos_get_tx_ops(psoc);
676 	if (!tx_ops || !tx_ops->send_rtt_pasn_deauth) {
677 		wifi_pos_err("%s is null",
678 			     tx_ops ? "Tx_ops" : "send_pasn deauth cb");
679 		return QDF_STATUS_E_FAILURE;
680 	}
681 
682 	status = tx_ops->send_rtt_pasn_deauth(psoc, peer_mac);
683 
684 	return status;
685 }
686 
687 QDF_STATUS
wifi_pos_set_peer_ltf_keyseed_required(struct wlan_objmgr_peer * peer,bool value)688 wifi_pos_set_peer_ltf_keyseed_required(struct wlan_objmgr_peer *peer,
689 				       bool value)
690 {
691 	struct wlan_wifi_pos_peer_priv_obj *peer_priv;
692 
693 	peer_priv = wifi_pos_get_peer_private_object(peer);
694 	if (!peer_priv) {
695 		wifi_pos_err("peer private object is null");
696 		return QDF_STATUS_E_FAILURE;
697 	}
698 
699 	peer_priv->is_ltf_keyseed_required = value;
700 	wifi_pos_debug("peer_mac:" QDF_MAC_ADDR_FMT " value:%d",
701 		       QDF_MAC_ADDR_REF(wlan_peer_get_macaddr(peer)), value);
702 
703 	return QDF_STATUS_SUCCESS;
704 }
705 
wifi_pos_is_ltf_keyseed_required_for_peer(struct wlan_objmgr_peer * peer)706 bool wifi_pos_is_ltf_keyseed_required_for_peer(struct wlan_objmgr_peer *peer)
707 {
708 	struct wlan_wifi_pos_peer_priv_obj *peer_priv;
709 
710 	peer_priv = wifi_pos_get_peer_private_object(peer);
711 	if (!peer_priv) {
712 		wifi_pos_err("peer private object is null");
713 		return QDF_STATUS_E_FAILURE;
714 	}
715 
716 	return peer_priv->is_ltf_keyseed_required;
717 }
718 
719 static
wifi_pos_delete_objmgr_ranging_peer(struct wlan_objmgr_psoc * psoc,void * object,void * arg)720 void wifi_pos_delete_objmgr_ranging_peer(struct wlan_objmgr_psoc *psoc,
721 					 void *object, void *arg)
722 {
723 	struct wlan_objmgr_peer *peer = object;
724 	struct wlan_objmgr_vdev *vdev = arg;
725 	uint8_t vdev_id, peer_vdev_id;
726 	enum wlan_peer_type peer_type;
727 	QDF_STATUS status;
728 
729 	if (!peer) {
730 		wifi_pos_err("Peer is NULL");
731 		return;
732 	}
733 
734 	peer_type = wlan_peer_get_peer_type(peer);
735 	if (peer_type != WLAN_PEER_RTT_PASN)
736 		return;
737 
738 	if (!vdev) {
739 		wifi_pos_err("VDEV is NULL");
740 		return;
741 	}
742 
743 	vdev_id = wlan_vdev_get_id(vdev);
744 	peer_vdev_id = wlan_vdev_get_id(wlan_peer_get_vdev(peer));
745 	if (vdev_id != peer_vdev_id)
746 		return;
747 
748 	status = wlan_objmgr_peer_obj_delete(peer);
749 	if (QDF_IS_STATUS_ERROR(status))
750 		wifi_pos_err("Failed to delete peer");
751 
752 	wifi_pos_update_pasn_peer_count(vdev, false);
753 }
754 
755 QDF_STATUS
wifi_pos_cleanup_pasn_peers(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)756 wifi_pos_cleanup_pasn_peers(struct wlan_objmgr_psoc *psoc,
757 			    struct wlan_objmgr_vdev *vdev)
758 {
759 	QDF_STATUS status;
760 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
761 
762 	wifi_pos_debug("Iterate and delete PASN peers");
763 	status = wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
764 					      wifi_pos_delete_objmgr_ranging_peer,
765 					      vdev, 0, WLAN_WIFI_POS_CORE_ID);
766 	if (QDF_IS_STATUS_ERROR(status))
767 		wifi_pos_err("Delete objmgr peers failed");
768 
769 	/*
770 	 * PASN Peer count should be zero here
771 	 */
772 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
773 	if (vdev_pos_obj)
774 		vdev_pos_obj->num_pasn_peers = 0;
775 
776 	return status;
777 }
778 
779 QDF_STATUS
wifi_pos_vdev_delete_all_ranging_peers(struct wlan_objmgr_vdev * vdev)780 wifi_pos_vdev_delete_all_ranging_peers(struct wlan_objmgr_vdev *vdev)
781 {
782 	QDF_STATUS status;
783 	struct vdev_mlme_obj *vdev_mlme;
784 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
785 	struct peer_delete_all_params param;
786 
787 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
788 	if (!vdev_pos_obj) {
789 		wifi_pos_err("Wifi pos vdev priv obj is null");
790 		return QDF_STATUS_E_FAILURE;
791 	}
792 
793 	if (!vdev_pos_obj->num_pasn_peers)
794 		return QDF_STATUS_SUCCESS;
795 
796 	vdev_pos_obj->is_delete_all_pasn_peer_in_progress = true;
797 
798 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
799 	if (!vdev_mlme) {
800 		wifi_pos_err(" VDEV MLME component object is NULL");
801 		return QDF_STATUS_E_FAILURE;
802 	}
803 
804 	param.vdev_id = wlan_vdev_get_id(vdev);
805 	param.peer_type_bitmap = BIT(WLAN_PEER_RTT_PASN);
806 
807 	status = tgt_vdev_mgr_peer_delete_all_send(vdev_mlme, &param);
808 	if (QDF_IS_STATUS_ERROR(status))
809 		wifi_pos_err("Send vdev delete all peers failed");
810 
811 	return status;
812 }
813 
814 QDF_STATUS
wifi_pos_vdev_delete_all_ranging_peers_rsp(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id)815 wifi_pos_vdev_delete_all_ranging_peers_rsp(struct wlan_objmgr_psoc *psoc,
816 					   uint8_t vdev_id)
817 {
818 	struct wifi_pos_legacy_ops *legacy_cb;
819 	struct wlan_objmgr_vdev *vdev;
820 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
821 	QDF_STATUS status;
822 
823 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
824 						    WLAN_WIFI_POS_CORE_ID);
825 	if (!vdev) {
826 		wifi_pos_err(" VDEV is NULL");
827 		return QDF_STATUS_E_FAILURE;
828 	}
829 
830 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
831 	if (!vdev_pos_obj) {
832 		wifi_pos_err("Wifi pos vdev priv obj is null");
833 		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
834 		return QDF_STATUS_E_FAILURE;
835 	}
836 
837 	status = wifi_pos_cleanup_pasn_peers(psoc, vdev);
838 	if (QDF_IS_STATUS_ERROR(status)) {
839 		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
840 		return status;
841 	}
842 
843 	/*
844 	 * Should have deleted all the pasn peers when we reach here
845 	 */
846 	vdev_pos_obj->is_delete_all_pasn_peer_in_progress = false;
847 	vdev_pos_obj->num_pasn_peers = 0;
848 
849 	legacy_cb = wifi_pos_get_legacy_ops();
850 	if (!legacy_cb || !legacy_cb->pasn_vdev_delete_resume_cb) {
851 		wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
852 		wifi_pos_err("legacy callbacks is not registered");
853 		return QDF_STATUS_E_FAILURE;
854 	}
855 
856 	status = legacy_cb->pasn_vdev_delete_resume_cb(vdev);
857 	if (QDF_IS_STATUS_ERROR(status))
858 		wifi_pos_err("Delete all PASN peer failed");
859 
860 	wlan_objmgr_vdev_release_ref(vdev, WLAN_WIFI_POS_CORE_ID);
861 
862 	return status;
863 }
864 
wifi_pos_is_delete_all_peer_in_progress(struct wlan_objmgr_vdev * vdev)865 bool wifi_pos_is_delete_all_peer_in_progress(struct wlan_objmgr_vdev *vdev)
866 {
867 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
868 
869 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
870 	if (!vdev_pos_obj) {
871 		wifi_pos_err("Wifi pos vdev priv obj is null");
872 		return false;
873 	}
874 
875 	return vdev_pos_obj->is_delete_all_pasn_peer_in_progress;
876 }
877 
wifi_pos_set_delete_all_peer_in_progress(struct wlan_objmgr_vdev * vdev,bool flag)878 void wifi_pos_set_delete_all_peer_in_progress(struct wlan_objmgr_vdev *vdev,
879 					      bool flag)
880 {
881 	struct wifi_pos_vdev_priv_obj *vdev_pos_obj;
882 
883 	vdev_pos_obj = wifi_pos_get_vdev_priv_obj(vdev);
884 	if (!vdev_pos_obj) {
885 		wifi_pos_err("Wifi pos vdev priv obj is null");
886 		return;
887 	}
888 
889 	vdev_pos_obj->is_delete_all_pasn_peer_in_progress = flag;
890 }
891