xref: /wlan-dirver/qca-wifi-host-cmn/dp/wifi3.0/dp_peer.c (revision f4dda761c5d694205beb627cc28032fb99492c74)
1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2024 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 #include <qdf_types.h>
21 #include <qdf_lock.h>
22 #include <hal_hw_headers.h>
23 #include "dp_htt.h"
24 #include "dp_types.h"
25 #include "dp_internal.h"
26 #include "dp_peer.h"
27 #include "dp_rx_defrag.h"
28 #include "dp_rx.h"
29 #include <hal_api.h>
30 #include <hal_reo.h>
31 #include <cdp_txrx_handle.h>
32 #include <wlan_cfg.h>
33 #ifdef WIFI_MONITOR_SUPPORT
34 #include <dp_mon.h>
35 #endif
36 #ifdef FEATURE_WDS
37 #include "dp_txrx_wds.h"
38 #endif
39 #include <qdf_module.h>
40 #ifdef QCA_PEER_EXT_STATS
41 #include "dp_hist.h"
42 #endif
43 #ifdef BYPASS_OL_OPS
44 #include <target_if_dp.h>
45 #endif
46 #if defined(WLAN_FEATURE_11BE_MLO) && defined(DP_MLO_LINK_STATS_SUPPORT)
47 #include "reg_services_common.h"
48 #endif
49 #ifdef FEATURE_AST
50 #ifdef BYPASS_OL_OPS
51 /**
52  * dp_add_wds_entry_wrapper() - Add new AST entry for the wds station
53  * @soc: DP soc structure pointer
54  * @peer: dp peer structure
55  * @dest_macaddr: MAC address of ast node
56  * @flags: wds or hmwds
57  * @type: type from enum cdp_txrx_ast_entry_type
58  *
59  * This API is used by WDS source port learning function to
60  * add a new AST entry in the fw.
61  *
62  * Return: 0 on success, error code otherwise.
63  */
64 static int dp_add_wds_entry_wrapper(struct dp_soc *soc,
65 				    struct dp_peer *peer,
66 				    const uint8_t *dest_macaddr,
67 				    uint32_t flags,
68 				    uint8_t type)
69 {
70 	QDF_STATUS status;
71 
72 	status = target_if_add_wds_entry(soc->ctrl_psoc,
73 					 peer->vdev->vdev_id,
74 					 peer->mac_addr.raw,
75 					 dest_macaddr,
76 					 WMI_HOST_WDS_FLAG_STATIC,
77 					 type);
78 
79 	return qdf_status_to_os_return(status);
80 }
81 
82 /**
83  * dp_update_wds_entry_wrapper() - update an existing wds entry with new peer
84  * @soc: DP soc structure pointer
85  * @peer: dp peer structure
86  * @dest_macaddr: MAC address of ast node
87  * @flags: wds or hmwds
88  *
89  * This API is used by update the peer mac address for the ast
90  * in the fw.
91  *
92  * Return: 0 on success, error code otherwise.
93  */
94 static int dp_update_wds_entry_wrapper(struct dp_soc *soc,
95 				       struct dp_peer *peer,
96 				       uint8_t *dest_macaddr,
97 				       uint32_t flags)
98 {
99 	QDF_STATUS status;
100 
101 	status = target_if_update_wds_entry(soc->ctrl_psoc,
102 					    peer->vdev->vdev_id,
103 					    dest_macaddr,
104 					    peer->mac_addr.raw,
105 					    WMI_HOST_WDS_FLAG_STATIC);
106 
107 	return qdf_status_to_os_return(status);
108 }
109 
110 /**
111  * dp_del_wds_entry_wrapper() - delete a WSD AST entry
112  * @soc: DP soc structure pointer
113  * @vdev_id: vdev_id
114  * @wds_macaddr: MAC address of ast node
115  * @type: type from enum cdp_txrx_ast_entry_type
116  * @delete_in_fw: Flag to indicate if entry needs to be deleted in fw
117  *
118  * This API is used to delete an AST entry from fw
119  *
120  * Return: None
121  */
122 void dp_del_wds_entry_wrapper(struct dp_soc *soc,
123 			      uint8_t vdev_id,
124 			      uint8_t *wds_macaddr,
125 			      uint8_t type,
126 			      uint8_t delete_in_fw)
127 {
128 	target_if_del_wds_entry(soc->ctrl_psoc, vdev_id,
129 				wds_macaddr, type, delete_in_fw);
130 }
131 #else
132 static int dp_add_wds_entry_wrapper(struct dp_soc *soc,
133 				    struct dp_peer *peer,
134 				    const uint8_t *dest_macaddr,
135 				    uint32_t flags,
136 				    uint8_t type)
137 {
138 	int status;
139 
140 	status = soc->cdp_soc.ol_ops->peer_add_wds_entry(
141 					soc->ctrl_psoc,
142 					peer->vdev->vdev_id,
143 					peer->mac_addr.raw,
144 					peer->peer_id,
145 					dest_macaddr,
146 					peer->mac_addr.raw,
147 					flags,
148 					type);
149 
150 	return status;
151 }
152 
153 static int dp_update_wds_entry_wrapper(struct dp_soc *soc,
154 				       struct dp_peer *peer,
155 				       uint8_t *dest_macaddr,
156 				       uint32_t flags)
157 {
158 	int status;
159 
160 	status = soc->cdp_soc.ol_ops->peer_update_wds_entry(
161 				soc->ctrl_psoc,
162 				peer->vdev->vdev_id,
163 				dest_macaddr,
164 				peer->mac_addr.raw,
165 				flags);
166 
167 	return status;
168 }
169 
170 void dp_del_wds_entry_wrapper(struct dp_soc *soc,
171 			      uint8_t vdev_id,
172 			      uint8_t *wds_macaddr,
173 			      uint8_t type,
174 			      uint8_t delete_in_fw)
175 {
176 	soc->cdp_soc.ol_ops->peer_del_wds_entry(soc->ctrl_psoc,
177 						vdev_id,
178 						wds_macaddr,
179 						type,
180 						delete_in_fw);
181 }
182 #endif /* BYPASS_OL_OPS */
183 #else
184 void dp_del_wds_entry_wrapper(struct dp_soc *soc,
185 			      uint8_t vdev_id,
186 			      uint8_t *wds_macaddr,
187 			      uint8_t type,
188 			      uint8_t delete_in_fw)
189 {
190 }
191 #endif /* FEATURE_AST */
192 
193 #ifdef FEATURE_WDS
194 static inline bool
195 dp_peer_ast_free_in_unmap_supported(struct dp_soc *soc,
196 				    struct dp_ast_entry *ast_entry)
197 {
198 	/* if peer map v2 is enabled we are not freeing ast entry
199 	 * here and it is supposed to be freed in unmap event (after
200 	 * we receive delete confirmation from target)
201 	 *
202 	 * if peer_id is invalid we did not get the peer map event
203 	 * for the peer free ast entry from here only in this case
204 	 */
205 
206 	if ((ast_entry->type != CDP_TXRX_AST_TYPE_WDS_HM_SEC) &&
207 	    (ast_entry->type != CDP_TXRX_AST_TYPE_SELF))
208 		return true;
209 
210 	return false;
211 }
212 #else
213 static inline bool
214 dp_peer_ast_free_in_unmap_supported(struct dp_soc *soc,
215 				    struct dp_ast_entry *ast_entry)
216 {
217 	return false;
218 }
219 
220 void dp_soc_wds_attach(struct dp_soc *soc)
221 {
222 }
223 
224 void dp_soc_wds_detach(struct dp_soc *soc)
225 {
226 }
227 #endif
228 
229 #ifdef QCA_SUPPORT_WDS_EXTENDED
230 bool dp_peer_check_wds_ext_peer(struct dp_peer *peer)
231 {
232 	struct dp_vdev *vdev = peer->vdev;
233 	struct dp_txrx_peer *txrx_peer;
234 
235 	if (!vdev->wds_ext_enabled)
236 		return false;
237 
238 	txrx_peer = dp_get_txrx_peer(peer);
239 	if (!txrx_peer)
240 		return false;
241 
242 	if (qdf_atomic_test_bit(WDS_EXT_PEER_INIT_BIT,
243 				&txrx_peer->wds_ext.init))
244 		return true;
245 
246 	return false;
247 }
248 #else
249 bool dp_peer_check_wds_ext_peer(struct dp_peer *peer)
250 {
251 	return false;
252 }
253 #endif
254 
255 QDF_STATUS dp_peer_ast_table_attach(struct dp_soc *soc)
256 {
257 	uint32_t max_ast_index;
258 
259 	max_ast_index = wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx);
260 	/* allocate ast_table for ast entry to ast_index map */
261 	dp_peer_info("\n%pK:<=== cfg max ast idx %d ====>", soc, max_ast_index);
262 	soc->ast_table = qdf_mem_malloc(max_ast_index *
263 					sizeof(struct dp_ast_entry *));
264 	if (!soc->ast_table) {
265 		dp_peer_err("%pK: ast_table memory allocation failed", soc);
266 		return QDF_STATUS_E_NOMEM;
267 	}
268 	return QDF_STATUS_SUCCESS; /* success */
269 }
270 
271 /**
272  * dp_find_peer_by_macaddr() - Finding the peer from mac address provided.
273  * @soc: soc handle
274  * @mac_addr: MAC address to be used to find peer
275  * @vdev_id: VDEV id
276  * @mod_id: MODULE ID
277  *
278  * Return: struct dp_peer
279  */
280 struct dp_peer *dp_find_peer_by_macaddr(struct dp_soc *soc, uint8_t *mac_addr,
281 					uint8_t vdev_id, enum dp_mod_id mod_id)
282 {
283 	bool ast_ind_disable = wlan_cfg_get_ast_indication_disable(
284 							    soc->wlan_cfg_ctx);
285 	struct cdp_peer_info peer_info = {0};
286 
287 	if ((!soc->ast_offload_support) || (!ast_ind_disable)) {
288 		struct dp_ast_entry *ast_entry = NULL;
289 		uint16_t peer_id;
290 
291 		qdf_spin_lock_bh(&soc->ast_lock);
292 
293 		if (vdev_id == DP_VDEV_ALL)
294 			ast_entry = dp_peer_ast_hash_find_soc(soc, mac_addr);
295 		else
296 			ast_entry = dp_peer_ast_hash_find_by_vdevid
297 						(soc, mac_addr, vdev_id);
298 
299 		if (!ast_entry) {
300 			qdf_spin_unlock_bh(&soc->ast_lock);
301 			dp_err("NULL ast entry");
302 			return NULL;
303 		}
304 
305 		peer_id = ast_entry->peer_id;
306 		qdf_spin_unlock_bh(&soc->ast_lock);
307 
308 		if (peer_id == HTT_INVALID_PEER)
309 			return NULL;
310 
311 		return dp_peer_get_ref_by_id(soc, peer_id, mod_id);
312 	}
313 
314 	DP_PEER_INFO_PARAMS_INIT(&peer_info, vdev_id, mac_addr, false,
315 				 CDP_WILD_PEER_TYPE);
316 	return dp_peer_hash_find_wrapper(soc, &peer_info, mod_id);
317 }
318 
319 /**
320  * dp_peer_find_map_attach() - allocate memory for peer_id_to_obj_map
321  * @soc: soc handle
322  *
323  * return: QDF_STATUS
324  */
325 static QDF_STATUS dp_peer_find_map_attach(struct dp_soc *soc)
326 {
327 	uint32_t max_peers, peer_map_size;
328 
329 	max_peers = soc->max_peer_id;
330 	/* allocate the peer ID -> peer object map */
331 	dp_peer_info("\n%pK:<=== cfg max peer id %d ====>", soc, max_peers);
332 	peer_map_size = max_peers * sizeof(soc->peer_id_to_obj_map[0]);
333 	soc->peer_id_to_obj_map = qdf_mem_malloc(peer_map_size);
334 	if (!soc->peer_id_to_obj_map) {
335 		dp_peer_err("%pK: peer map memory allocation failed", soc);
336 		return QDF_STATUS_E_NOMEM;
337 	}
338 
339 	/*
340 	 * The peer_id_to_obj_map doesn't really need to be initialized,
341 	 * since elements are only used after they have been individually
342 	 * initialized.
343 	 * However, it is convenient for debugging to have all elements
344 	 * that are not in use set to 0.
345 	 */
346 	qdf_mem_zero(soc->peer_id_to_obj_map, peer_map_size);
347 
348 	qdf_spinlock_create(&soc->peer_map_lock);
349 	return QDF_STATUS_SUCCESS; /* success */
350 }
351 
352 #define DP_AST_HASH_LOAD_MULT  2
353 #define DP_AST_HASH_LOAD_SHIFT 0
354 
355 static inline uint32_t
356 dp_peer_find_hash_index(struct dp_soc *soc,
357 			union dp_align_mac_addr *mac_addr)
358 {
359 	uint32_t index;
360 
361 	index =
362 		mac_addr->align2.bytes_ab ^
363 		mac_addr->align2.bytes_cd ^
364 		mac_addr->align2.bytes_ef;
365 
366 	index ^= index >> soc->peer_hash.idx_bits;
367 	index &= soc->peer_hash.mask;
368 	return index;
369 }
370 
371 struct dp_peer *dp_peer_find_hash_find(
372 				struct dp_soc *soc, uint8_t *peer_mac_addr,
373 				int mac_addr_is_aligned, uint8_t vdev_id,
374 				enum dp_mod_id mod_id)
375 {
376 	union dp_align_mac_addr local_mac_addr_aligned, *mac_addr;
377 	uint32_t index;
378 	struct dp_peer *peer;
379 
380 	if (!soc->peer_hash.bins)
381 		return NULL;
382 
383 	if (mac_addr_is_aligned) {
384 		mac_addr = (union dp_align_mac_addr *)peer_mac_addr;
385 	} else {
386 		qdf_mem_copy(
387 			&local_mac_addr_aligned.raw[0],
388 			peer_mac_addr, QDF_MAC_ADDR_SIZE);
389 		mac_addr = &local_mac_addr_aligned;
390 	}
391 	index = dp_peer_find_hash_index(soc, mac_addr);
392 	qdf_spin_lock_bh(&soc->peer_hash_lock);
393 	TAILQ_FOREACH(peer, &soc->peer_hash.bins[index], hash_list_elem) {
394 		if (dp_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) == 0 &&
395 		    ((peer->vdev->vdev_id == vdev_id) ||
396 		     (vdev_id == DP_VDEV_ALL))) {
397 			/* take peer reference before returning */
398 			if (dp_peer_get_ref(soc, peer, mod_id) !=
399 						QDF_STATUS_SUCCESS)
400 				peer = NULL;
401 
402 			qdf_spin_unlock_bh(&soc->peer_hash_lock);
403 			return peer;
404 		}
405 	}
406 	qdf_spin_unlock_bh(&soc->peer_hash_lock);
407 	return NULL; /* failure */
408 }
409 
410 qdf_export_symbol(dp_peer_find_hash_find);
411 
412 #ifdef WLAN_FEATURE_11BE_MLO
413 /**
414  * dp_peer_find_hash_detach() - cleanup memory for peer_hash table
415  * @soc: soc handle
416  *
417  * return: none
418  */
419 static void dp_peer_find_hash_detach(struct dp_soc *soc)
420 {
421 	if (soc->peer_hash.bins) {
422 		qdf_mem_free(soc->peer_hash.bins);
423 		soc->peer_hash.bins = NULL;
424 		qdf_spinlock_destroy(&soc->peer_hash_lock);
425 	}
426 
427 	if (soc->arch_ops.mlo_peer_find_hash_detach)
428 		soc->arch_ops.mlo_peer_find_hash_detach(soc);
429 }
430 
431 /**
432  * dp_peer_find_hash_attach() - allocate memory for peer_hash table
433  * @soc: soc handle
434  *
435  * return: QDF_STATUS
436  */
437 static QDF_STATUS dp_peer_find_hash_attach(struct dp_soc *soc)
438 {
439 	int i, hash_elems, log2;
440 
441 	/* allocate the peer MAC address -> peer object hash table */
442 	hash_elems = soc->max_peers;
443 	hash_elems *= DP_PEER_HASH_LOAD_MULT;
444 	hash_elems >>= DP_PEER_HASH_LOAD_SHIFT;
445 	log2 = dp_log2_ceil(hash_elems);
446 	hash_elems = 1 << log2;
447 
448 	soc->peer_hash.mask = hash_elems - 1;
449 	soc->peer_hash.idx_bits = log2;
450 	/* allocate an array of TAILQ peer object lists */
451 	soc->peer_hash.bins = qdf_mem_malloc(
452 		hash_elems * sizeof(TAILQ_HEAD(anonymous_tail_q, dp_peer)));
453 	if (!soc->peer_hash.bins)
454 		return QDF_STATUS_E_NOMEM;
455 
456 	for (i = 0; i < hash_elems; i++)
457 		TAILQ_INIT(&soc->peer_hash.bins[i]);
458 
459 	qdf_spinlock_create(&soc->peer_hash_lock);
460 
461 	if (soc->arch_ops.mlo_peer_find_hash_attach &&
462 	    (soc->arch_ops.mlo_peer_find_hash_attach(soc) !=
463 			QDF_STATUS_SUCCESS)) {
464 		dp_peer_find_hash_detach(soc);
465 		return QDF_STATUS_E_NOMEM;
466 	}
467 	return QDF_STATUS_SUCCESS;
468 }
469 
470 void dp_peer_find_hash_add(struct dp_soc *soc, struct dp_peer *peer)
471 {
472 	unsigned index;
473 
474 	index = dp_peer_find_hash_index(soc, &peer->mac_addr);
475 	if (peer->peer_type == CDP_LINK_PEER_TYPE) {
476 		qdf_spin_lock_bh(&soc->peer_hash_lock);
477 
478 		if (QDF_IS_STATUS_ERROR(dp_peer_get_ref(soc, peer,
479 							DP_MOD_ID_CONFIG))) {
480 			dp_err("fail to get peer ref:" QDF_MAC_ADDR_FMT,
481 			       QDF_MAC_ADDR_REF(peer->mac_addr.raw));
482 			qdf_spin_unlock_bh(&soc->peer_hash_lock);
483 			return;
484 		}
485 
486 		/*
487 		 * It is important to add the new peer at the tail of
488 		 * peer list with the bin index. Together with having
489 		 * the hash_find function search from head to tail,
490 		 * this ensures that if two entries with the same MAC address
491 		 * are stored, the one added first will be found first.
492 		 */
493 		TAILQ_INSERT_TAIL(&soc->peer_hash.bins[index], peer,
494 				  hash_list_elem);
495 
496 		qdf_spin_unlock_bh(&soc->peer_hash_lock);
497 	} else if (peer->peer_type == CDP_MLD_PEER_TYPE) {
498 		if (soc->arch_ops.mlo_peer_find_hash_add)
499 			soc->arch_ops.mlo_peer_find_hash_add(soc, peer);
500 	} else {
501 		dp_err("unknown peer type %d", peer->peer_type);
502 	}
503 }
504 
505 void dp_peer_find_hash_remove(struct dp_soc *soc, struct dp_peer *peer)
506 {
507 	unsigned index;
508 	struct dp_peer *tmppeer = NULL;
509 	int found = 0;
510 
511 	index = dp_peer_find_hash_index(soc, &peer->mac_addr);
512 
513 	if (peer->peer_type == CDP_LINK_PEER_TYPE) {
514 		/* Check if tail is not empty before delete*/
515 		QDF_ASSERT(!TAILQ_EMPTY(&soc->peer_hash.bins[index]));
516 
517 		qdf_spin_lock_bh(&soc->peer_hash_lock);
518 		TAILQ_FOREACH(tmppeer, &soc->peer_hash.bins[index],
519 			      hash_list_elem) {
520 			if (tmppeer == peer) {
521 				found = 1;
522 				break;
523 			}
524 		}
525 		QDF_ASSERT(found);
526 		TAILQ_REMOVE(&soc->peer_hash.bins[index], peer,
527 			     hash_list_elem);
528 
529 		dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
530 		qdf_spin_unlock_bh(&soc->peer_hash_lock);
531 	} else if (peer->peer_type == CDP_MLD_PEER_TYPE) {
532 		if (soc->arch_ops.mlo_peer_find_hash_remove)
533 			soc->arch_ops.mlo_peer_find_hash_remove(soc, peer);
534 	} else {
535 		dp_err("unknown peer type %d", peer->peer_type);
536 	}
537 }
538 
539 uint8_t dp_get_peer_link_id(struct dp_peer *peer)
540 {
541 	uint8_t link_id;
542 
543 	link_id = IS_MLO_DP_LINK_PEER(peer) ? peer->link_id + 1 : 0;
544 	if (link_id < 1 || link_id > DP_MAX_MLO_LINKS)
545 		link_id = 0;
546 
547 	return link_id;
548 }
549 #else
550 static QDF_STATUS dp_peer_find_hash_attach(struct dp_soc *soc)
551 {
552 	int i, hash_elems, log2;
553 
554 	/* allocate the peer MAC address -> peer object hash table */
555 	hash_elems = soc->max_peers;
556 	hash_elems *= DP_PEER_HASH_LOAD_MULT;
557 	hash_elems >>= DP_PEER_HASH_LOAD_SHIFT;
558 	log2 = dp_log2_ceil(hash_elems);
559 	hash_elems = 1 << log2;
560 
561 	soc->peer_hash.mask = hash_elems - 1;
562 	soc->peer_hash.idx_bits = log2;
563 	/* allocate an array of TAILQ peer object lists */
564 	soc->peer_hash.bins = qdf_mem_malloc(
565 		hash_elems * sizeof(TAILQ_HEAD(anonymous_tail_q, dp_peer)));
566 	if (!soc->peer_hash.bins)
567 		return QDF_STATUS_E_NOMEM;
568 
569 	for (i = 0; i < hash_elems; i++)
570 		TAILQ_INIT(&soc->peer_hash.bins[i]);
571 
572 	qdf_spinlock_create(&soc->peer_hash_lock);
573 	return QDF_STATUS_SUCCESS;
574 }
575 
576 static void dp_peer_find_hash_detach(struct dp_soc *soc)
577 {
578 	if (soc->peer_hash.bins) {
579 		qdf_mem_free(soc->peer_hash.bins);
580 		soc->peer_hash.bins = NULL;
581 		qdf_spinlock_destroy(&soc->peer_hash_lock);
582 	}
583 }
584 
585 void dp_peer_find_hash_add(struct dp_soc *soc, struct dp_peer *peer)
586 {
587 	unsigned index;
588 
589 	index = dp_peer_find_hash_index(soc, &peer->mac_addr);
590 	qdf_spin_lock_bh(&soc->peer_hash_lock);
591 
592 	if (QDF_IS_STATUS_ERROR(dp_peer_get_ref(soc, peer, DP_MOD_ID_CONFIG))) {
593 		dp_err("unable to get peer ref at MAP mac: "QDF_MAC_ADDR_FMT,
594 		       QDF_MAC_ADDR_REF(peer->mac_addr.raw));
595 		qdf_spin_unlock_bh(&soc->peer_hash_lock);
596 		return;
597 	}
598 
599 	/*
600 	 * It is important to add the new peer at the tail of the peer list
601 	 * with the bin index.  Together with having the hash_find function
602 	 * search from head to tail, this ensures that if two entries with
603 	 * the same MAC address are stored, the one added first will be
604 	 * found first.
605 	 */
606 	TAILQ_INSERT_TAIL(&soc->peer_hash.bins[index], peer, hash_list_elem);
607 
608 	qdf_spin_unlock_bh(&soc->peer_hash_lock);
609 }
610 
611 void dp_peer_find_hash_remove(struct dp_soc *soc, struct dp_peer *peer)
612 {
613 	unsigned index;
614 	struct dp_peer *tmppeer = NULL;
615 	int found = 0;
616 
617 	index = dp_peer_find_hash_index(soc, &peer->mac_addr);
618 	/* Check if tail is not empty before delete*/
619 	QDF_ASSERT(!TAILQ_EMPTY(&soc->peer_hash.bins[index]));
620 
621 	qdf_spin_lock_bh(&soc->peer_hash_lock);
622 	TAILQ_FOREACH(tmppeer, &soc->peer_hash.bins[index], hash_list_elem) {
623 		if (tmppeer == peer) {
624 			found = 1;
625 			break;
626 		}
627 	}
628 	QDF_ASSERT(found);
629 	TAILQ_REMOVE(&soc->peer_hash.bins[index], peer, hash_list_elem);
630 
631 	dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
632 	qdf_spin_unlock_bh(&soc->peer_hash_lock);
633 }
634 
635 
636 #endif/* WLAN_FEATURE_11BE_MLO */
637 
638 void dp_peer_vdev_list_add(struct dp_soc *soc, struct dp_vdev *vdev,
639 			   struct dp_peer *peer)
640 {
641 	/* only link peer will be added to vdev peer list */
642 	if (IS_MLO_DP_MLD_PEER(peer))
643 		return;
644 
645 	qdf_spin_lock_bh(&vdev->peer_list_lock);
646 	if (QDF_IS_STATUS_ERROR(dp_peer_get_ref(soc, peer, DP_MOD_ID_CONFIG))) {
647 		dp_err("unable to get peer ref at MAP mac: "QDF_MAC_ADDR_FMT,
648 		       QDF_MAC_ADDR_REF(peer->mac_addr.raw));
649 		qdf_spin_unlock_bh(&vdev->peer_list_lock);
650 		return;
651 	}
652 
653 	/* add this peer into the vdev's list */
654 	if (wlan_op_mode_sta == vdev->opmode)
655 		TAILQ_INSERT_HEAD(&vdev->peer_list, peer, peer_list_elem);
656 	else
657 		TAILQ_INSERT_TAIL(&vdev->peer_list, peer, peer_list_elem);
658 
659 	vdev->num_peers++;
660 	qdf_spin_unlock_bh(&vdev->peer_list_lock);
661 }
662 
663 void dp_peer_vdev_list_remove(struct dp_soc *soc, struct dp_vdev *vdev,
664 			      struct dp_peer *peer)
665 {
666 	uint8_t found = 0;
667 	struct dp_peer *tmppeer = NULL;
668 
669 	/* only link peer will be added to vdev peer list */
670 	if (IS_MLO_DP_MLD_PEER(peer))
671 		return;
672 
673 	qdf_spin_lock_bh(&vdev->peer_list_lock);
674 	TAILQ_FOREACH(tmppeer, &peer->vdev->peer_list, peer_list_elem) {
675 		if (tmppeer == peer) {
676 			found = 1;
677 			break;
678 		}
679 	}
680 
681 	if (found) {
682 		TAILQ_REMOVE(&peer->vdev->peer_list, peer,
683 			     peer_list_elem);
684 		dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
685 		vdev->num_peers--;
686 	} else {
687 		/*Ignoring the remove operation as peer not found*/
688 		dp_peer_debug("%pK: peer:%pK not found in vdev:%pK peerlist:%pK"
689 			      , soc, peer, vdev, &peer->vdev->peer_list);
690 	}
691 	qdf_spin_unlock_bh(&vdev->peer_list_lock);
692 }
693 
694 void dp_txrx_peer_attach_add(struct dp_soc *soc,
695 			     struct dp_peer *peer,
696 			     struct dp_txrx_peer *txrx_peer)
697 {
698 	qdf_spin_lock_bh(&soc->peer_map_lock);
699 
700 	peer->txrx_peer = txrx_peer;
701 	txrx_peer->bss_peer = peer->bss_peer;
702 
703 	if (peer->peer_id == HTT_INVALID_PEER) {
704 		qdf_spin_unlock_bh(&soc->peer_map_lock);
705 		return;
706 	}
707 
708 	txrx_peer->peer_id = peer->peer_id;
709 
710 	QDF_ASSERT(soc->peer_id_to_obj_map[peer->peer_id]);
711 
712 	qdf_spin_unlock_bh(&soc->peer_map_lock);
713 }
714 
715 void dp_peer_find_id_to_obj_add(struct dp_soc *soc,
716 				struct dp_peer *peer,
717 				uint16_t peer_id)
718 {
719 	QDF_ASSERT(peer_id <= soc->max_peer_id);
720 
721 	qdf_spin_lock_bh(&soc->peer_map_lock);
722 
723 	peer->peer_id = peer_id;
724 
725 	if (QDF_IS_STATUS_ERROR(dp_peer_get_ref(soc, peer, DP_MOD_ID_CONFIG))) {
726 		dp_err("unable to get peer ref at MAP mac: "QDF_MAC_ADDR_FMT" peer_id %u",
727 		       QDF_MAC_ADDR_REF(peer->mac_addr.raw), peer_id);
728 		qdf_spin_unlock_bh(&soc->peer_map_lock);
729 		return;
730 	}
731 
732 	if (!soc->peer_id_to_obj_map[peer_id]) {
733 		soc->peer_id_to_obj_map[peer_id] = peer;
734 		if (peer->txrx_peer)
735 			peer->txrx_peer->peer_id = peer_id;
736 	} else {
737 		/* Peer map event came for peer_id which
738 		 * is already mapped, this is not expected
739 		 */
740 		dp_err("peer %pK(" QDF_MAC_ADDR_FMT ")map failed, id %d mapped "
741 		       "to peer %pK, Stats: peer(map %u unmap %u "
742 		       "invalid unmap %u) mld per(map %u unmap %u)",
743 		       peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw), peer_id,
744 		       soc->peer_id_to_obj_map[peer_id],
745 		       soc->stats.t2h_msg_stats.peer_map,
746 		       (soc->stats.t2h_msg_stats.peer_unmap -
747 			soc->stats.t2h_msg_stats.ml_peer_unmap),
748 		       soc->stats.t2h_msg_stats.invalid_peer_unmap,
749 		       soc->stats.t2h_msg_stats.ml_peer_map,
750 		       soc->stats.t2h_msg_stats.ml_peer_unmap);
751 		dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
752 		qdf_assert_always(0);
753 	}
754 	qdf_spin_unlock_bh(&soc->peer_map_lock);
755 }
756 
757 void dp_peer_find_id_to_obj_remove(struct dp_soc *soc,
758 				   uint16_t peer_id)
759 {
760 	struct dp_peer *peer = NULL;
761 	QDF_ASSERT(peer_id <= soc->max_peer_id);
762 
763 	qdf_spin_lock_bh(&soc->peer_map_lock);
764 	peer = soc->peer_id_to_obj_map[peer_id];
765 	if (!peer) {
766 		dp_err("unable to get peer during peer id obj map remove");
767 		qdf_spin_unlock_bh(&soc->peer_map_lock);
768 		return;
769 	}
770 	peer->peer_id = HTT_INVALID_PEER;
771 	if (peer->txrx_peer)
772 		peer->txrx_peer->peer_id = HTT_INVALID_PEER;
773 	soc->peer_id_to_obj_map[peer_id] = NULL;
774 	dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
775 	qdf_spin_unlock_bh(&soc->peer_map_lock);
776 }
777 
778 #ifdef FEATURE_MEC
779 QDF_STATUS dp_peer_mec_hash_attach(struct dp_soc *soc)
780 {
781 	int log2, hash_elems, i;
782 
783 	log2 = dp_log2_ceil(DP_PEER_MAX_MEC_IDX);
784 	hash_elems = 1 << log2;
785 
786 	soc->mec_hash.mask = hash_elems - 1;
787 	soc->mec_hash.idx_bits = log2;
788 
789 	dp_peer_info("%pK: max mec index: %d",
790 		     soc, DP_PEER_MAX_MEC_IDX);
791 
792 	/* allocate an array of TAILQ mec object lists */
793 	soc->mec_hash.bins = qdf_mem_malloc(hash_elems *
794 					    sizeof(TAILQ_HEAD(anonymous_tail_q,
795 							      dp_mec_entry)));
796 
797 	if (!soc->mec_hash.bins)
798 		return QDF_STATUS_E_NOMEM;
799 
800 	for (i = 0; i < hash_elems; i++)
801 		TAILQ_INIT(&soc->mec_hash.bins[i]);
802 
803 	return QDF_STATUS_SUCCESS;
804 }
805 
806 /**
807  * dp_peer_mec_hash_index() - Compute the MEC hash from MAC address
808  * @soc: SoC handle
809  * @mac_addr: MAC address
810  *
811  * Return: MEC hash
812  */
813 static inline uint32_t dp_peer_mec_hash_index(struct dp_soc *soc,
814 					      union dp_align_mac_addr *mac_addr)
815 {
816 	uint32_t index;
817 
818 	index =
819 		mac_addr->align2.bytes_ab ^
820 		mac_addr->align2.bytes_cd ^
821 		mac_addr->align2.bytes_ef;
822 	index ^= index >> soc->mec_hash.idx_bits;
823 	index &= soc->mec_hash.mask;
824 	return index;
825 }
826 
827 struct dp_mec_entry *dp_peer_mec_hash_find_by_pdevid(struct dp_soc *soc,
828 						     uint8_t pdev_id,
829 						     uint8_t *mec_mac_addr)
830 {
831 	union dp_align_mac_addr local_mac_addr_aligned, *mac_addr;
832 	uint32_t index;
833 	struct dp_mec_entry *mecentry;
834 
835 	qdf_mem_copy(&local_mac_addr_aligned.raw[0],
836 		     mec_mac_addr, QDF_MAC_ADDR_SIZE);
837 	mac_addr = &local_mac_addr_aligned;
838 
839 	index = dp_peer_mec_hash_index(soc, mac_addr);
840 	TAILQ_FOREACH(mecentry, &soc->mec_hash.bins[index], hash_list_elem) {
841 		if ((pdev_id == mecentry->pdev_id) &&
842 		    !dp_peer_find_mac_addr_cmp(mac_addr, &mecentry->mac_addr))
843 			return mecentry;
844 	}
845 
846 	return NULL;
847 }
848 
849 /**
850  * dp_peer_mec_hash_add() - Add MEC entry into hash table
851  * @soc: SoC handle
852  * @mecentry: MEC entry
853  *
854  * This function adds the MEC entry into SoC MEC hash table
855  *
856  * Return: None
857  */
858 static inline void dp_peer_mec_hash_add(struct dp_soc *soc,
859 					struct dp_mec_entry *mecentry)
860 {
861 	uint32_t index;
862 
863 	index = dp_peer_mec_hash_index(soc, &mecentry->mac_addr);
864 	qdf_spin_lock_bh(&soc->mec_lock);
865 	TAILQ_INSERT_TAIL(&soc->mec_hash.bins[index], mecentry, hash_list_elem);
866 	qdf_spin_unlock_bh(&soc->mec_lock);
867 }
868 
869 QDF_STATUS dp_peer_mec_add_entry(struct dp_soc *soc,
870 				 struct dp_vdev *vdev,
871 				 uint8_t *mac_addr)
872 {
873 	struct dp_mec_entry *mecentry = NULL;
874 	struct dp_pdev *pdev = NULL;
875 
876 	if (!vdev) {
877 		dp_peer_err("%pK: Peers vdev is NULL", soc);
878 		return QDF_STATUS_E_INVAL;
879 	}
880 
881 	pdev = vdev->pdev;
882 
883 	if (qdf_unlikely(qdf_atomic_read(&soc->mec_cnt) >=
884 					 DP_PEER_MAX_MEC_ENTRY)) {
885 		dp_peer_warn("%pK: max MEC entry limit reached mac_addr: "
886 			     QDF_MAC_ADDR_FMT, soc, QDF_MAC_ADDR_REF(mac_addr));
887 		return QDF_STATUS_E_NOMEM;
888 	}
889 
890 	qdf_spin_lock_bh(&soc->mec_lock);
891 	mecentry = dp_peer_mec_hash_find_by_pdevid(soc, pdev->pdev_id,
892 						   mac_addr);
893 	if (qdf_likely(mecentry)) {
894 		mecentry->is_active = TRUE;
895 		qdf_spin_unlock_bh(&soc->mec_lock);
896 		return QDF_STATUS_E_ALREADY;
897 	}
898 
899 	qdf_spin_unlock_bh(&soc->mec_lock);
900 
901 	dp_peer_debug("%pK: pdevid: %u vdev: %u type: MEC mac_addr: "
902 		      QDF_MAC_ADDR_FMT,
903 		      soc, pdev->pdev_id, vdev->vdev_id,
904 		      QDF_MAC_ADDR_REF(mac_addr));
905 
906 	mecentry = (struct dp_mec_entry *)
907 			qdf_mem_malloc(sizeof(struct dp_mec_entry));
908 
909 	if (qdf_unlikely(!mecentry)) {
910 		dp_peer_err("%pK: fail to allocate mecentry", soc);
911 		return QDF_STATUS_E_NOMEM;
912 	}
913 
914 	qdf_copy_macaddr((struct qdf_mac_addr *)&mecentry->mac_addr.raw[0],
915 			 (struct qdf_mac_addr *)mac_addr);
916 	mecentry->pdev_id = pdev->pdev_id;
917 	mecentry->vdev_id = vdev->vdev_id;
918 	mecentry->is_active = TRUE;
919 	dp_peer_mec_hash_add(soc, mecentry);
920 
921 	qdf_atomic_inc(&soc->mec_cnt);
922 	DP_STATS_INC(soc, mec.added, 1);
923 
924 	return QDF_STATUS_SUCCESS;
925 }
926 
927 void dp_peer_mec_detach_entry(struct dp_soc *soc, struct dp_mec_entry *mecentry,
928 			      void *ptr)
929 {
930 	uint32_t index = dp_peer_mec_hash_index(soc, &mecentry->mac_addr);
931 
932 	TAILQ_HEAD(, dp_mec_entry) * free_list = ptr;
933 
934 	TAILQ_REMOVE(&soc->mec_hash.bins[index], mecentry,
935 		     hash_list_elem);
936 	TAILQ_INSERT_TAIL(free_list, mecentry, hash_list_elem);
937 }
938 
939 void dp_peer_mec_free_list(struct dp_soc *soc, void *ptr)
940 {
941 	struct dp_mec_entry *mecentry, *mecentry_next;
942 
943 	TAILQ_HEAD(, dp_mec_entry) * free_list = ptr;
944 
945 	TAILQ_FOREACH_SAFE(mecentry, free_list, hash_list_elem,
946 			   mecentry_next) {
947 		dp_peer_debug("%pK: MEC delete for mac_addr " QDF_MAC_ADDR_FMT,
948 			      soc, QDF_MAC_ADDR_REF(&mecentry->mac_addr));
949 		qdf_mem_free(mecentry);
950 		qdf_atomic_dec(&soc->mec_cnt);
951 		DP_STATS_INC(soc, mec.deleted, 1);
952 	}
953 }
954 
955 void dp_peer_mec_hash_detach(struct dp_soc *soc)
956 {
957 	dp_peer_mec_flush_entries(soc);
958 	qdf_mem_free(soc->mec_hash.bins);
959 	soc->mec_hash.bins = NULL;
960 }
961 
962 void dp_peer_mec_spinlock_destroy(struct dp_soc *soc)
963 {
964 	qdf_spinlock_destroy(&soc->mec_lock);
965 }
966 
967 void dp_peer_mec_spinlock_create(struct dp_soc *soc)
968 {
969 	qdf_spinlock_create(&soc->mec_lock);
970 }
971 #else
972 QDF_STATUS dp_peer_mec_hash_attach(struct dp_soc *soc)
973 {
974 	return QDF_STATUS_SUCCESS;
975 }
976 
977 void dp_peer_mec_hash_detach(struct dp_soc *soc)
978 {
979 }
980 #endif
981 
982 #ifdef FEATURE_AST
983 #ifdef WLAN_FEATURE_11BE_MLO
984 /**
985  * dp_peer_exist_on_pdev() - check if peer with mac address exist on pdev
986  *
987  * @soc: Datapath SOC handle
988  * @peer_mac_addr: peer mac address
989  * @mac_addr_is_aligned: is mac address aligned
990  * @pdev: Datapath PDEV handle
991  *
992  * Return: true if peer found else return false
993  */
994 static bool dp_peer_exist_on_pdev(struct dp_soc *soc,
995 				  uint8_t *peer_mac_addr,
996 				  int mac_addr_is_aligned,
997 				  struct dp_pdev *pdev)
998 {
999 	union dp_align_mac_addr local_mac_addr_aligned, *mac_addr;
1000 	unsigned int index;
1001 	struct dp_peer *peer;
1002 	bool found = false;
1003 
1004 	if (mac_addr_is_aligned) {
1005 		mac_addr = (union dp_align_mac_addr *)peer_mac_addr;
1006 	} else {
1007 		qdf_mem_copy(
1008 			&local_mac_addr_aligned.raw[0],
1009 			peer_mac_addr, QDF_MAC_ADDR_SIZE);
1010 		mac_addr = &local_mac_addr_aligned;
1011 	}
1012 	index = dp_peer_find_hash_index(soc, mac_addr);
1013 	qdf_spin_lock_bh(&soc->peer_hash_lock);
1014 	TAILQ_FOREACH(peer, &soc->peer_hash.bins[index], hash_list_elem) {
1015 		if (dp_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) == 0 &&
1016 		    (peer->vdev->pdev == pdev)) {
1017 			found = true;
1018 			break;
1019 		}
1020 	}
1021 	qdf_spin_unlock_bh(&soc->peer_hash_lock);
1022 
1023 	if (found)
1024 		return found;
1025 
1026 	peer = dp_mld_peer_find_hash_find(soc, peer_mac_addr,
1027 					  mac_addr_is_aligned, DP_VDEV_ALL,
1028 					  DP_MOD_ID_CDP);
1029 	if (peer) {
1030 		if (peer->vdev->pdev == pdev)
1031 			found = true;
1032 		dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
1033 	}
1034 
1035 	return found;
1036 }
1037 #else
1038 static bool dp_peer_exist_on_pdev(struct dp_soc *soc,
1039 				  uint8_t *peer_mac_addr,
1040 				  int mac_addr_is_aligned,
1041 				  struct dp_pdev *pdev)
1042 {
1043 	union dp_align_mac_addr local_mac_addr_aligned, *mac_addr;
1044 	unsigned int index;
1045 	struct dp_peer *peer;
1046 	bool found = false;
1047 
1048 	if (mac_addr_is_aligned) {
1049 		mac_addr = (union dp_align_mac_addr *)peer_mac_addr;
1050 	} else {
1051 		qdf_mem_copy(
1052 			&local_mac_addr_aligned.raw[0],
1053 			peer_mac_addr, QDF_MAC_ADDR_SIZE);
1054 		mac_addr = &local_mac_addr_aligned;
1055 	}
1056 	index = dp_peer_find_hash_index(soc, mac_addr);
1057 	qdf_spin_lock_bh(&soc->peer_hash_lock);
1058 	TAILQ_FOREACH(peer, &soc->peer_hash.bins[index], hash_list_elem) {
1059 		if (dp_peer_find_mac_addr_cmp(mac_addr, &peer->mac_addr) == 0 &&
1060 		    (peer->vdev->pdev == pdev)) {
1061 			found = true;
1062 			break;
1063 		}
1064 	}
1065 	qdf_spin_unlock_bh(&soc->peer_hash_lock);
1066 	return found;
1067 }
1068 #endif /* WLAN_FEATURE_11BE_MLO */
1069 
1070 QDF_STATUS dp_peer_ast_hash_attach(struct dp_soc *soc)
1071 {
1072 	int i, hash_elems, log2;
1073 	unsigned int max_ast_idx = wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx);
1074 
1075 	hash_elems = ((max_ast_idx * DP_AST_HASH_LOAD_MULT) >>
1076 		DP_AST_HASH_LOAD_SHIFT);
1077 
1078 	log2 = dp_log2_ceil(hash_elems);
1079 	hash_elems = 1 << log2;
1080 
1081 	soc->ast_hash.mask = hash_elems - 1;
1082 	soc->ast_hash.idx_bits = log2;
1083 
1084 	dp_peer_info("%pK: ast hash_elems: %d, max_ast_idx: %d",
1085 		     soc, hash_elems, max_ast_idx);
1086 
1087 	/* allocate an array of TAILQ peer object lists */
1088 	soc->ast_hash.bins = qdf_mem_malloc(
1089 		hash_elems * sizeof(TAILQ_HEAD(anonymous_tail_q,
1090 				dp_ast_entry)));
1091 
1092 	if (!soc->ast_hash.bins)
1093 		return QDF_STATUS_E_NOMEM;
1094 
1095 	for (i = 0; i < hash_elems; i++)
1096 		TAILQ_INIT(&soc->ast_hash.bins[i]);
1097 
1098 	return QDF_STATUS_SUCCESS;
1099 }
1100 
1101 /**
1102  * dp_peer_ast_cleanup() - cleanup the references
1103  * @soc: SoC handle
1104  * @ast: ast entry
1105  *
1106  * Return: None
1107  */
1108 static inline void dp_peer_ast_cleanup(struct dp_soc *soc,
1109 				       struct dp_ast_entry *ast)
1110 {
1111 	txrx_ast_free_cb cb = ast->callback;
1112 	void *cookie = ast->cookie;
1113 
1114 	dp_peer_debug("mac_addr: " QDF_MAC_ADDR_FMT ", cb: %pK, cookie: %pK",
1115 		      QDF_MAC_ADDR_REF(ast->mac_addr.raw), cb, cookie);
1116 
1117 	/* Call the callbacks to free up the cookie */
1118 	if (cb) {
1119 		ast->callback = NULL;
1120 		ast->cookie = NULL;
1121 		cb(soc->ctrl_psoc,
1122 		   dp_soc_to_cdp_soc(soc),
1123 		   cookie,
1124 		   CDP_TXRX_AST_DELETE_IN_PROGRESS);
1125 	}
1126 }
1127 
1128 void dp_peer_ast_hash_detach(struct dp_soc *soc)
1129 {
1130 	unsigned int index;
1131 	struct dp_ast_entry *ast, *ast_next;
1132 
1133 	if (!soc->ast_hash.mask)
1134 		return;
1135 
1136 	if (!soc->ast_hash.bins)
1137 		return;
1138 
1139 	dp_peer_debug("%pK: num_ast_entries: %u", soc, soc->num_ast_entries);
1140 
1141 	qdf_spin_lock_bh(&soc->ast_lock);
1142 	for (index = 0; index <= soc->ast_hash.mask; index++) {
1143 		if (!TAILQ_EMPTY(&soc->ast_hash.bins[index])) {
1144 			TAILQ_FOREACH_SAFE(ast, &soc->ast_hash.bins[index],
1145 					   hash_list_elem, ast_next) {
1146 				TAILQ_REMOVE(&soc->ast_hash.bins[index], ast,
1147 					     hash_list_elem);
1148 				dp_peer_ast_cleanup(soc, ast);
1149 				soc->num_ast_entries--;
1150 				qdf_mem_free(ast);
1151 			}
1152 		}
1153 	}
1154 	qdf_spin_unlock_bh(&soc->ast_lock);
1155 
1156 	qdf_mem_free(soc->ast_hash.bins);
1157 	soc->ast_hash.bins = NULL;
1158 }
1159 
1160 /**
1161  * dp_peer_ast_hash_index() - Compute the AST hash from MAC address
1162  * @soc: SoC handle
1163  * @mac_addr: MAC address
1164  *
1165  * Return: AST hash
1166  */
1167 static inline uint32_t dp_peer_ast_hash_index(struct dp_soc *soc,
1168 					      union dp_align_mac_addr *mac_addr)
1169 {
1170 	uint32_t index;
1171 
1172 	index =
1173 		mac_addr->align2.bytes_ab ^
1174 		mac_addr->align2.bytes_cd ^
1175 		mac_addr->align2.bytes_ef;
1176 	index ^= index >> soc->ast_hash.idx_bits;
1177 	index &= soc->ast_hash.mask;
1178 	return index;
1179 }
1180 
1181 /**
1182  * dp_peer_ast_hash_add() - Add AST entry into hash table
1183  * @soc: SoC handle
1184  * @ase: AST entry
1185  *
1186  * This function adds the AST entry into SoC AST hash table
1187  * It assumes caller has taken the ast lock to protect the access to this table
1188  *
1189  * Return: None
1190  */
1191 static inline void dp_peer_ast_hash_add(struct dp_soc *soc,
1192 					struct dp_ast_entry *ase)
1193 {
1194 	uint32_t index;
1195 
1196 	index = dp_peer_ast_hash_index(soc, &ase->mac_addr);
1197 	TAILQ_INSERT_TAIL(&soc->ast_hash.bins[index], ase, hash_list_elem);
1198 }
1199 
1200 void dp_peer_ast_hash_remove(struct dp_soc *soc,
1201 			     struct dp_ast_entry *ase)
1202 {
1203 	unsigned index;
1204 	struct dp_ast_entry *tmpase;
1205 	int found = 0;
1206 
1207 	if (soc->ast_offload_support && !soc->host_ast_db_enable)
1208 		return;
1209 
1210 	index = dp_peer_ast_hash_index(soc, &ase->mac_addr);
1211 	/* Check if tail is not empty before delete*/
1212 	QDF_ASSERT(!TAILQ_EMPTY(&soc->ast_hash.bins[index]));
1213 
1214 	dp_peer_debug("ID: %u idx: %u mac_addr: " QDF_MAC_ADDR_FMT,
1215 		      ase->peer_id, index, QDF_MAC_ADDR_REF(ase->mac_addr.raw));
1216 
1217 	TAILQ_FOREACH(tmpase, &soc->ast_hash.bins[index], hash_list_elem) {
1218 		if (tmpase == ase) {
1219 			found = 1;
1220 			break;
1221 		}
1222 	}
1223 
1224 	QDF_ASSERT(found);
1225 
1226 	if (found)
1227 		TAILQ_REMOVE(&soc->ast_hash.bins[index], ase, hash_list_elem);
1228 }
1229 
1230 struct dp_ast_entry *dp_peer_ast_hash_find_by_vdevid(struct dp_soc *soc,
1231 						     uint8_t *ast_mac_addr,
1232 						     uint8_t vdev_id)
1233 {
1234 	union dp_align_mac_addr local_mac_addr_aligned, *mac_addr;
1235 	uint32_t index;
1236 	struct dp_ast_entry *ase;
1237 
1238 	qdf_mem_copy(&local_mac_addr_aligned.raw[0],
1239 		     ast_mac_addr, QDF_MAC_ADDR_SIZE);
1240 	mac_addr = &local_mac_addr_aligned;
1241 
1242 	index = dp_peer_ast_hash_index(soc, mac_addr);
1243 	TAILQ_FOREACH(ase, &soc->ast_hash.bins[index], hash_list_elem) {
1244 		if ((vdev_id == ase->vdev_id) &&
1245 		    !dp_peer_find_mac_addr_cmp(mac_addr, &ase->mac_addr)) {
1246 			return ase;
1247 		}
1248 	}
1249 
1250 	return NULL;
1251 }
1252 
1253 struct dp_ast_entry *dp_peer_ast_hash_find_by_pdevid(struct dp_soc *soc,
1254 						     uint8_t *ast_mac_addr,
1255 						     uint8_t pdev_id)
1256 {
1257 	union dp_align_mac_addr local_mac_addr_aligned, *mac_addr;
1258 	uint32_t index;
1259 	struct dp_ast_entry *ase;
1260 
1261 	qdf_mem_copy(&local_mac_addr_aligned.raw[0],
1262 		     ast_mac_addr, QDF_MAC_ADDR_SIZE);
1263 	mac_addr = &local_mac_addr_aligned;
1264 
1265 	index = dp_peer_ast_hash_index(soc, mac_addr);
1266 	TAILQ_FOREACH(ase, &soc->ast_hash.bins[index], hash_list_elem) {
1267 		if ((pdev_id == ase->pdev_id) &&
1268 		    !dp_peer_find_mac_addr_cmp(mac_addr, &ase->mac_addr)) {
1269 			return ase;
1270 		}
1271 	}
1272 
1273 	return NULL;
1274 }
1275 
1276 struct dp_ast_entry *dp_peer_ast_hash_find_soc(struct dp_soc *soc,
1277 					       uint8_t *ast_mac_addr)
1278 {
1279 	union dp_align_mac_addr local_mac_addr_aligned, *mac_addr;
1280 	unsigned index;
1281 	struct dp_ast_entry *ase;
1282 
1283 	if (!soc->ast_hash.bins)
1284 		return NULL;
1285 
1286 	qdf_mem_copy(&local_mac_addr_aligned.raw[0],
1287 			ast_mac_addr, QDF_MAC_ADDR_SIZE);
1288 	mac_addr = &local_mac_addr_aligned;
1289 
1290 	index = dp_peer_ast_hash_index(soc, mac_addr);
1291 	TAILQ_FOREACH(ase, &soc->ast_hash.bins[index], hash_list_elem) {
1292 		if (dp_peer_find_mac_addr_cmp(mac_addr, &ase->mac_addr) == 0) {
1293 			return ase;
1294 		}
1295 	}
1296 
1297 	return NULL;
1298 }
1299 
1300 struct dp_ast_entry *dp_peer_ast_hash_find_soc_by_type(
1301 					struct dp_soc *soc,
1302 					uint8_t *ast_mac_addr,
1303 					enum cdp_txrx_ast_entry_type type)
1304 {
1305 	union dp_align_mac_addr local_mac_addr_aligned, *mac_addr;
1306 	unsigned index;
1307 	struct dp_ast_entry *ase;
1308 
1309 	if (!soc->ast_hash.bins)
1310 		return NULL;
1311 
1312 	qdf_mem_copy(&local_mac_addr_aligned.raw[0],
1313 			ast_mac_addr, QDF_MAC_ADDR_SIZE);
1314 	mac_addr = &local_mac_addr_aligned;
1315 
1316 	index = dp_peer_ast_hash_index(soc, mac_addr);
1317 	TAILQ_FOREACH(ase, &soc->ast_hash.bins[index], hash_list_elem) {
1318 		if (dp_peer_find_mac_addr_cmp(mac_addr, &ase->mac_addr) == 0 &&
1319 		    ase->type == type) {
1320 			return ase;
1321 		}
1322 	}
1323 
1324 	return NULL;
1325 }
1326 
1327 /**
1328  * dp_peer_map_ipa_evt() - Send peer map event to IPA
1329  * @soc: SoC handle
1330  * @peer: peer to which ast node belongs
1331  * @ast_entry: AST entry
1332  * @mac_addr: MAC address of ast node
1333  *
1334  * Return: None
1335  */
1336 #if defined(IPA_OFFLOAD) && defined(QCA_IPA_LL_TX_FLOW_CONTROL)
1337 static inline
1338 void dp_peer_map_ipa_evt(struct dp_soc *soc, struct dp_peer *peer,
1339 			 struct dp_ast_entry *ast_entry, uint8_t *mac_addr)
1340 {
1341 	if (ast_entry || (peer->vdev && peer->vdev->proxysta_vdev)) {
1342 		if (soc->cdp_soc.ol_ops->peer_map_event) {
1343 			soc->cdp_soc.ol_ops->peer_map_event(
1344 			soc->ctrl_psoc, ast_entry->peer_id,
1345 			ast_entry->ast_idx, ast_entry->vdev_id,
1346 			mac_addr, ast_entry->type, ast_entry->ast_hash_value);
1347 		}
1348 	} else {
1349 		dp_peer_info("%pK: AST entry not found", soc);
1350 	}
1351 }
1352 
1353 /**
1354  * dp_peer_unmap_ipa_evt() - Send peer unmap event to IPA
1355  * @soc: SoC handle
1356  * @peer_id: Peerid
1357  * @vdev_id: Vdev id
1358  * @mac_addr: Peer mac address
1359  *
1360  * Return: None
1361  */
1362 static inline
1363 void dp_peer_unmap_ipa_evt(struct dp_soc *soc, uint16_t peer_id,
1364 			   uint8_t vdev_id, uint8_t *mac_addr)
1365 {
1366 	if (soc->cdp_soc.ol_ops->peer_unmap_event) {
1367 		soc->cdp_soc.ol_ops->peer_unmap_event(soc->ctrl_psoc,
1368 						      peer_id, vdev_id,
1369 						      mac_addr);
1370 	}
1371 }
1372 #else
1373 static inline
1374 void dp_peer_unmap_ipa_evt(struct dp_soc *soc, uint16_t peer_id,
1375 			   uint8_t vdev_id, uint8_t *mac_addr)
1376 {
1377 }
1378 
1379 static inline
1380 void dp_peer_map_ipa_evt(struct dp_soc *soc, struct dp_peer *peer,
1381 			 struct dp_ast_entry *ast_entry, uint8_t *mac_addr)
1382 {
1383 }
1384 #endif
1385 
1386 QDF_STATUS dp_peer_host_add_map_ast(struct dp_soc *soc, uint16_t peer_id,
1387 				    uint8_t *mac_addr, uint16_t hw_peer_id,
1388 				    uint8_t vdev_id, uint16_t ast_hash,
1389 				    uint8_t is_wds)
1390 {
1391 	struct dp_vdev *vdev;
1392 	struct dp_ast_entry *ast_entry;
1393 	enum cdp_txrx_ast_entry_type type;
1394 	struct dp_peer *peer;
1395 	struct dp_peer *old_peer;
1396 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1397 
1398 	if (is_wds)
1399 		type = CDP_TXRX_AST_TYPE_WDS;
1400 	else
1401 		type = CDP_TXRX_AST_TYPE_STATIC;
1402 
1403 	peer = dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_HTT);
1404 	if (!peer) {
1405 		dp_peer_info("Peer not found soc:%pK: peer_id %d, peer_mac " QDF_MAC_ADDR_FMT ", vdev_id %d",
1406 			     soc, peer_id,
1407 			     QDF_MAC_ADDR_REF(mac_addr), vdev_id);
1408 		return QDF_STATUS_E_INVAL;
1409 	}
1410 
1411 	if (!is_wds && IS_MLO_DP_MLD_PEER(peer))
1412 		type = CDP_TXRX_AST_TYPE_MLD;
1413 
1414 	vdev = peer->vdev;
1415 	if (!vdev) {
1416 		dp_peer_err("%pK: Peers vdev is NULL", soc);
1417 		status = QDF_STATUS_E_INVAL;
1418 		goto fail;
1419 	}
1420 
1421 	if (!dp_peer_state_cmp(peer, DP_PEER_STATE_ACTIVE)) {
1422 		if (type != CDP_TXRX_AST_TYPE_STATIC &&
1423 		    type != CDP_TXRX_AST_TYPE_MLD &&
1424 		    type != CDP_TXRX_AST_TYPE_SELF) {
1425 			status = QDF_STATUS_E_BUSY;
1426 			goto fail;
1427 		}
1428 	}
1429 
1430 	dp_peer_debug("%pK: vdev: %u  ast_entry->type: %d peer_mac: " QDF_MAC_ADDR_FMT " peer: %pK mac " QDF_MAC_ADDR_FMT,
1431 		      soc, vdev->vdev_id, type,
1432 		      QDF_MAC_ADDR_REF(peer->mac_addr.raw), peer,
1433 		      QDF_MAC_ADDR_REF(mac_addr));
1434 
1435 	/*
1436 	 * In MLO scenario, there is possibility for same mac address
1437 	 * on both link mac address and MLD mac address.
1438 	 * Duplicate AST map needs to be handled for non-mld type.
1439 	 */
1440 	qdf_spin_lock_bh(&soc->ast_lock);
1441 	ast_entry = dp_peer_ast_hash_find_soc(soc, mac_addr);
1442 	if (ast_entry && type != CDP_TXRX_AST_TYPE_MLD) {
1443 		dp_peer_debug("AST present ID %d vid %d mac " QDF_MAC_ADDR_FMT,
1444 			      hw_peer_id, vdev_id,
1445 			      QDF_MAC_ADDR_REF(mac_addr));
1446 
1447 		old_peer = __dp_peer_get_ref_by_id(soc, ast_entry->peer_id,
1448 						   DP_MOD_ID_AST);
1449 		if (!old_peer) {
1450 			dp_peer_info("Peer not found soc:%pK: peer_id %d, peer_mac " QDF_MAC_ADDR_FMT ", vdev_id %d",
1451 				     soc, ast_entry->peer_id,
1452 				     QDF_MAC_ADDR_REF(mac_addr), vdev_id);
1453 			qdf_spin_unlock_bh(&soc->ast_lock);
1454 			status = QDF_STATUS_E_INVAL;
1455 			goto fail;
1456 		}
1457 
1458 		dp_peer_unlink_ast_entry(soc, ast_entry, old_peer);
1459 		dp_peer_free_ast_entry(soc, ast_entry);
1460 		if (old_peer)
1461 			dp_peer_unref_delete(old_peer, DP_MOD_ID_AST);
1462 	}
1463 
1464 	ast_entry = (struct dp_ast_entry *)
1465 		qdf_mem_malloc(sizeof(struct dp_ast_entry));
1466 	if (!ast_entry) {
1467 		dp_peer_err("%pK: fail to allocate ast_entry", soc);
1468 		qdf_spin_unlock_bh(&soc->ast_lock);
1469 		QDF_ASSERT(0);
1470 		status = QDF_STATUS_E_NOMEM;
1471 		goto fail;
1472 	}
1473 
1474 	qdf_mem_copy(&ast_entry->mac_addr.raw[0], mac_addr, QDF_MAC_ADDR_SIZE);
1475 	ast_entry->pdev_id = vdev->pdev->pdev_id;
1476 	ast_entry->is_mapped = false;
1477 	ast_entry->delete_in_progress = false;
1478 	ast_entry->next_hop = 0;
1479 	ast_entry->vdev_id = vdev->vdev_id;
1480 	ast_entry->type = type;
1481 
1482 	switch (type) {
1483 	case CDP_TXRX_AST_TYPE_STATIC:
1484 		if (peer->vdev->opmode == wlan_op_mode_sta)
1485 			ast_entry->type = CDP_TXRX_AST_TYPE_STA_BSS;
1486 		break;
1487 	case CDP_TXRX_AST_TYPE_WDS:
1488 		ast_entry->next_hop = 1;
1489 		break;
1490 	case CDP_TXRX_AST_TYPE_MLD:
1491 		break;
1492 	default:
1493 		dp_peer_alert("%pK: Incorrect AST entry type", soc);
1494 	}
1495 
1496 	ast_entry->is_active = TRUE;
1497 	DP_STATS_INC(soc, ast.added, 1);
1498 	soc->num_ast_entries++;
1499 	dp_peer_ast_hash_add(soc, ast_entry);
1500 
1501 	ast_entry->ast_idx = hw_peer_id;
1502 	ast_entry->ast_hash_value = ast_hash;
1503 	ast_entry->peer_id = peer_id;
1504 	TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry,
1505 			  ase_list_elem);
1506 
1507 	dp_peer_map_ipa_evt(soc, peer, ast_entry, mac_addr);
1508 
1509 	qdf_spin_unlock_bh(&soc->ast_lock);
1510 fail:
1511 	dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
1512 
1513 	return status;
1514 }
1515 
1516 /**
1517  * dp_peer_map_ast() - Map the ast entry with HW AST Index
1518  * @soc: SoC handle
1519  * @peer: peer to which ast node belongs
1520  * @mac_addr: MAC address of ast node
1521  * @hw_peer_id: HW AST Index returned by target in peer map event
1522  * @vdev_id: vdev id for VAP to which the peer belongs to
1523  * @ast_hash: ast hash value in HW
1524  * @is_wds: flag to indicate peer map event for WDS ast entry
1525  *
1526  * Return: QDF_STATUS code
1527  */
1528 static inline QDF_STATUS dp_peer_map_ast(struct dp_soc *soc,
1529 					 struct dp_peer *peer,
1530 					 uint8_t *mac_addr,
1531 					 uint16_t hw_peer_id,
1532 					 uint8_t vdev_id,
1533 					 uint16_t ast_hash,
1534 					 uint8_t is_wds)
1535 {
1536 	struct dp_ast_entry *ast_entry = NULL;
1537 	enum cdp_txrx_ast_entry_type peer_type = CDP_TXRX_AST_TYPE_STATIC;
1538 	void *cookie = NULL;
1539 	txrx_ast_free_cb cb = NULL;
1540 	QDF_STATUS err = QDF_STATUS_SUCCESS;
1541 
1542 	if (soc->ast_offload_support && !wlan_cfg_get_dp_soc_dpdk_cfg(soc->ctrl_psoc))
1543 		return QDF_STATUS_SUCCESS;
1544 
1545 	dp_peer_err("%pK: peer %pK ID %d vid %d mac " QDF_MAC_ADDR_FMT,
1546 		    soc, peer, hw_peer_id, vdev_id,
1547 		    QDF_MAC_ADDR_REF(mac_addr));
1548 
1549 	qdf_spin_lock_bh(&soc->ast_lock);
1550 
1551 	ast_entry = dp_peer_ast_hash_find_by_vdevid(soc, mac_addr, vdev_id);
1552 
1553 	if (is_wds) {
1554 		/*
1555 		 * While processing peer map of AST entry if the next hop peer is
1556 		 * deleted free the AST entry as it is not attached to peer yet
1557 		 */
1558 		if (!peer) {
1559 			if (ast_entry)
1560 				dp_peer_free_ast_entry(soc, ast_entry);
1561 
1562 			qdf_spin_unlock_bh(&soc->ast_lock);
1563 
1564 			dp_peer_alert("Peer is NULL for WDS entry mac "
1565 				      QDF_MAC_ADDR_FMT " ",
1566 				      QDF_MAC_ADDR_REF(mac_addr));
1567 			return QDF_STATUS_E_INVAL;
1568 		}
1569 		/*
1570 		 * In certain cases like Auth attack on a repeater
1571 		 * can result in the number of ast_entries falling
1572 		 * in the same hash bucket to exceed the max_skid
1573 		 * length supported by HW in root AP. In these cases
1574 		 * the FW will return the hw_peer_id (ast_index) as
1575 		 * 0xffff indicating HW could not add the entry in
1576 		 * its table. Host has to delete the entry from its
1577 		 * table in these cases.
1578 		 */
1579 		if (hw_peer_id == HTT_INVALID_PEER) {
1580 			DP_STATS_INC(soc, ast.map_err, 1);
1581 			if (ast_entry) {
1582 				if (ast_entry->is_mapped) {
1583 					soc->ast_table[ast_entry->ast_idx] =
1584 						NULL;
1585 				}
1586 
1587 				cb = ast_entry->callback;
1588 				cookie = ast_entry->cookie;
1589 				peer_type = ast_entry->type;
1590 
1591 				dp_peer_unlink_ast_entry(soc, ast_entry, peer);
1592 				dp_peer_free_ast_entry(soc, ast_entry);
1593 
1594 				qdf_spin_unlock_bh(&soc->ast_lock);
1595 
1596 				if (cb) {
1597 					cb(soc->ctrl_psoc,
1598 					   dp_soc_to_cdp_soc(soc),
1599 					   cookie,
1600 					   CDP_TXRX_AST_DELETED);
1601 				}
1602 			} else {
1603 				qdf_spin_unlock_bh(&soc->ast_lock);
1604 				dp_peer_alert("AST entry not found with peer %pK peer_id %u peer_mac " QDF_MAC_ADDR_FMT " mac_addr " QDF_MAC_ADDR_FMT " vdev_id %u next_hop %u",
1605 					      peer, peer->peer_id,
1606 					      QDF_MAC_ADDR_REF(peer->mac_addr.raw),
1607 					      QDF_MAC_ADDR_REF(mac_addr),
1608 					      vdev_id, is_wds);
1609 			}
1610 			err = QDF_STATUS_E_INVAL;
1611 
1612 			dp_hmwds_ast_add_notify(peer, mac_addr,
1613 						peer_type, err, true);
1614 
1615 			return err;
1616 		}
1617 	}
1618 
1619 	if (!peer) {
1620 		qdf_spin_unlock_bh(&soc->ast_lock);
1621 		dp_peer_alert("Peer is NULL for mac " QDF_MAC_ADDR_FMT " ",
1622 			      QDF_MAC_ADDR_REF(mac_addr));
1623 		return QDF_STATUS_E_INVAL;
1624 	}
1625 
1626 	if (ast_entry) {
1627 		ast_entry->ast_idx = hw_peer_id;
1628 		soc->ast_table[hw_peer_id] = ast_entry;
1629 		ast_entry->is_active = TRUE;
1630 		peer_type = ast_entry->type;
1631 		ast_entry->ast_hash_value = ast_hash;
1632 		ast_entry->is_mapped = TRUE;
1633 		qdf_assert_always(ast_entry->peer_id == HTT_INVALID_PEER);
1634 
1635 		ast_entry->peer_id = peer->peer_id;
1636 		TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry,
1637 				  ase_list_elem);
1638 	}
1639 
1640 	if (ast_entry || (peer->vdev && peer->vdev->proxysta_vdev) ||
1641 	    wlan_cfg_get_dp_soc_dpdk_cfg(soc->ctrl_psoc)) {
1642 		if (soc->cdp_soc.ol_ops->peer_map_event) {
1643 			soc->cdp_soc.ol_ops->peer_map_event(
1644 			soc->ctrl_psoc, peer->peer_id,
1645 			hw_peer_id, vdev_id,
1646 			mac_addr, peer_type, ast_hash);
1647 		}
1648 	} else {
1649 		dp_peer_err("%pK: AST entry not found", soc);
1650 		err = QDF_STATUS_E_NOENT;
1651 	}
1652 
1653 	qdf_spin_unlock_bh(&soc->ast_lock);
1654 
1655 	dp_hmwds_ast_add_notify(peer, mac_addr,
1656 				peer_type, err, true);
1657 
1658 	return err;
1659 }
1660 
1661 void dp_peer_free_hmwds_cb(struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
1662 			   struct cdp_soc *dp_soc,
1663 			   void *cookie,
1664 			   enum cdp_ast_free_status status)
1665 {
1666 	struct dp_ast_free_cb_params *param =
1667 		(struct dp_ast_free_cb_params *)cookie;
1668 	struct dp_soc *soc = (struct dp_soc *)dp_soc;
1669 	struct dp_peer *peer = NULL;
1670 	QDF_STATUS err = QDF_STATUS_SUCCESS;
1671 
1672 	if (status != CDP_TXRX_AST_DELETED) {
1673 		qdf_mem_free(cookie);
1674 		return;
1675 	}
1676 
1677 	peer = dp_peer_find_hash_find(soc, &param->peer_mac_addr.raw[0],
1678 				      0, param->vdev_id, DP_MOD_ID_AST);
1679 	if (peer) {
1680 		err = dp_peer_add_ast(soc, peer,
1681 				      &param->mac_addr.raw[0],
1682 				      param->type,
1683 				      param->flags);
1684 
1685 		dp_hmwds_ast_add_notify(peer, &param->mac_addr.raw[0],
1686 					param->type, err, false);
1687 
1688 		dp_peer_unref_delete(peer, DP_MOD_ID_AST);
1689 	}
1690 	qdf_mem_free(cookie);
1691 }
1692 
1693 QDF_STATUS dp_peer_add_ast(struct dp_soc *soc,
1694 			   struct dp_peer *peer,
1695 			   uint8_t *mac_addr,
1696 			   enum cdp_txrx_ast_entry_type type,
1697 			   uint32_t flags)
1698 {
1699 	struct dp_ast_entry *ast_entry = NULL;
1700 	struct dp_vdev *vdev = NULL;
1701 	struct dp_pdev *pdev = NULL;
1702 	txrx_ast_free_cb cb = NULL;
1703 	void *cookie = NULL;
1704 	struct dp_peer *vap_bss_peer = NULL;
1705 	bool is_peer_found = false;
1706 	int status = 0;
1707 
1708 	if (soc->ast_offload_support)
1709 		return QDF_STATUS_E_INVAL;
1710 
1711 	vdev = peer->vdev;
1712 	if (!vdev) {
1713 		dp_peer_err("%pK: Peers vdev is NULL", soc);
1714 		QDF_ASSERT(0);
1715 		return QDF_STATUS_E_INVAL;
1716 	}
1717 
1718 	pdev = vdev->pdev;
1719 
1720 	is_peer_found = dp_peer_exist_on_pdev(soc, mac_addr, 0, pdev);
1721 
1722 	qdf_spin_lock_bh(&soc->ast_lock);
1723 
1724 	if (!dp_peer_state_cmp(peer, DP_PEER_STATE_ACTIVE)) {
1725 		if ((type != CDP_TXRX_AST_TYPE_STATIC) &&
1726 		    (type != CDP_TXRX_AST_TYPE_SELF)) {
1727 			qdf_spin_unlock_bh(&soc->ast_lock);
1728 			return QDF_STATUS_E_BUSY;
1729 		}
1730 	}
1731 
1732 	dp_peer_debug("%pK: pdevid: %u vdev: %u  ast_entry->type: %d flags: 0x%x peer_mac: " QDF_MAC_ADDR_FMT " peer: %pK mac " QDF_MAC_ADDR_FMT,
1733 		      soc, pdev->pdev_id, vdev->vdev_id, type, flags,
1734 		      QDF_MAC_ADDR_REF(peer->mac_addr.raw), peer,
1735 		      QDF_MAC_ADDR_REF(mac_addr));
1736 
1737 	/* fw supports only 2 times the max_peers ast entries */
1738 	if (soc->num_ast_entries >=
1739 	    wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)) {
1740 		qdf_spin_unlock_bh(&soc->ast_lock);
1741 		dp_peer_err("%pK: Max ast entries reached", soc);
1742 		return QDF_STATUS_E_RESOURCES;
1743 	}
1744 
1745 	/* If AST entry already exists , just return from here
1746 	 * ast entry with same mac address can exist on different radios
1747 	 * if ast_override support is enabled use search by pdev in this
1748 	 * case
1749 	 */
1750 	if (soc->ast_override_support) {
1751 		ast_entry = dp_peer_ast_hash_find_by_pdevid(soc, mac_addr,
1752 							    pdev->pdev_id);
1753 		if (ast_entry) {
1754 			qdf_spin_unlock_bh(&soc->ast_lock);
1755 			return QDF_STATUS_E_ALREADY;
1756 		}
1757 
1758 		if (is_peer_found) {
1759 			/* During WDS to static roaming, peer is added
1760 			 * to the list before static AST entry create.
1761 			 * So, allow AST entry for STATIC type
1762 			 * even if peer is present
1763 			 */
1764 			if (type != CDP_TXRX_AST_TYPE_STATIC) {
1765 				qdf_spin_unlock_bh(&soc->ast_lock);
1766 				return QDF_STATUS_E_ALREADY;
1767 			}
1768 		}
1769 	} else {
1770 		/* For HWMWDS_SEC entries can be added for same mac address
1771 		 * do not check for existing entry
1772 		 */
1773 		if (type == CDP_TXRX_AST_TYPE_WDS_HM_SEC)
1774 			goto add_ast_entry;
1775 
1776 		ast_entry = dp_peer_ast_hash_find_soc(soc, mac_addr);
1777 
1778 		if (ast_entry) {
1779 			if ((ast_entry->type == CDP_TXRX_AST_TYPE_WDS_HM) &&
1780 			    !ast_entry->delete_in_progress) {
1781 				qdf_spin_unlock_bh(&soc->ast_lock);
1782 				return QDF_STATUS_E_ALREADY;
1783 			}
1784 
1785 			/* Add for HMWDS entry we cannot be ignored if there
1786 			 * is AST entry with same mac address
1787 			 *
1788 			 * if ast entry exists with the requested mac address
1789 			 * send a delete command and register callback which
1790 			 * can take care of adding HMWDS ast entry on delete
1791 			 * confirmation from target
1792 			 */
1793 			if (type == CDP_TXRX_AST_TYPE_WDS_HM) {
1794 				struct dp_ast_free_cb_params *param = NULL;
1795 
1796 				if (ast_entry->type ==
1797 					CDP_TXRX_AST_TYPE_WDS_HM_SEC)
1798 					goto add_ast_entry;
1799 
1800 				/* save existing callback */
1801 				if (ast_entry->callback) {
1802 					cb = ast_entry->callback;
1803 					cookie = ast_entry->cookie;
1804 				}
1805 
1806 				param = qdf_mem_malloc(sizeof(*param));
1807 				if (!param) {
1808 					QDF_TRACE(QDF_MODULE_ID_TXRX,
1809 						  QDF_TRACE_LEVEL_ERROR,
1810 						  "Allocation failed");
1811 					qdf_spin_unlock_bh(&soc->ast_lock);
1812 					return QDF_STATUS_E_NOMEM;
1813 				}
1814 
1815 				qdf_mem_copy(&param->mac_addr.raw[0], mac_addr,
1816 					     QDF_MAC_ADDR_SIZE);
1817 				qdf_mem_copy(&param->peer_mac_addr.raw[0],
1818 					     &peer->mac_addr.raw[0],
1819 					     QDF_MAC_ADDR_SIZE);
1820 				param->type = type;
1821 				param->flags = flags;
1822 				param->vdev_id = vdev->vdev_id;
1823 				ast_entry->callback = dp_peer_free_hmwds_cb;
1824 				ast_entry->pdev_id = vdev->pdev->pdev_id;
1825 				ast_entry->type = type;
1826 				ast_entry->cookie = (void *)param;
1827 				if (!ast_entry->delete_in_progress)
1828 					dp_peer_del_ast(soc, ast_entry);
1829 
1830 				qdf_spin_unlock_bh(&soc->ast_lock);
1831 
1832 				/* Call the saved callback*/
1833 				if (cb) {
1834 					cb(soc->ctrl_psoc,
1835 					   dp_soc_to_cdp_soc(soc),
1836 					   cookie,
1837 					   CDP_TXRX_AST_DELETE_IN_PROGRESS);
1838 				}
1839 				return QDF_STATUS_E_AGAIN;
1840 			}
1841 
1842 			qdf_spin_unlock_bh(&soc->ast_lock);
1843 			return QDF_STATUS_E_ALREADY;
1844 		}
1845 	}
1846 
1847 add_ast_entry:
1848 	ast_entry = (struct dp_ast_entry *)
1849 			qdf_mem_malloc(sizeof(struct dp_ast_entry));
1850 
1851 	if (!ast_entry) {
1852 		qdf_spin_unlock_bh(&soc->ast_lock);
1853 		dp_peer_err("%pK: fail to allocate ast_entry", soc);
1854 		QDF_ASSERT(0);
1855 		return QDF_STATUS_E_NOMEM;
1856 	}
1857 
1858 	qdf_mem_copy(&ast_entry->mac_addr.raw[0], mac_addr, QDF_MAC_ADDR_SIZE);
1859 	ast_entry->pdev_id = vdev->pdev->pdev_id;
1860 	ast_entry->is_mapped = false;
1861 	ast_entry->delete_in_progress = false;
1862 	ast_entry->peer_id = HTT_INVALID_PEER;
1863 	ast_entry->next_hop = 0;
1864 	ast_entry->vdev_id = vdev->vdev_id;
1865 
1866 	switch (type) {
1867 	case CDP_TXRX_AST_TYPE_STATIC:
1868 		peer->self_ast_entry = ast_entry;
1869 		ast_entry->type = CDP_TXRX_AST_TYPE_STATIC;
1870 		if (peer->vdev->opmode == wlan_op_mode_sta)
1871 			ast_entry->type = CDP_TXRX_AST_TYPE_STA_BSS;
1872 		break;
1873 	case CDP_TXRX_AST_TYPE_SELF:
1874 		peer->self_ast_entry = ast_entry;
1875 		ast_entry->type = CDP_TXRX_AST_TYPE_SELF;
1876 		break;
1877 	case CDP_TXRX_AST_TYPE_WDS:
1878 		ast_entry->next_hop = 1;
1879 		ast_entry->type = CDP_TXRX_AST_TYPE_WDS;
1880 		break;
1881 	case CDP_TXRX_AST_TYPE_WDS_HM:
1882 		ast_entry->next_hop = 1;
1883 		ast_entry->type = CDP_TXRX_AST_TYPE_WDS_HM;
1884 		break;
1885 	case CDP_TXRX_AST_TYPE_WDS_HM_SEC:
1886 		ast_entry->next_hop = 1;
1887 		ast_entry->type = CDP_TXRX_AST_TYPE_WDS_HM_SEC;
1888 		ast_entry->peer_id = peer->peer_id;
1889 		TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry,
1890 				  ase_list_elem);
1891 		break;
1892 	case CDP_TXRX_AST_TYPE_DA:
1893 		vap_bss_peer = dp_vdev_bss_peer_ref_n_get(soc, vdev,
1894 							  DP_MOD_ID_AST);
1895 		if (!vap_bss_peer) {
1896 			qdf_spin_unlock_bh(&soc->ast_lock);
1897 			qdf_mem_free(ast_entry);
1898 			return QDF_STATUS_E_FAILURE;
1899 		}
1900 		peer = vap_bss_peer;
1901 		ast_entry->next_hop = 1;
1902 		ast_entry->type = CDP_TXRX_AST_TYPE_DA;
1903 		break;
1904 	default:
1905 		dp_peer_err("%pK: Incorrect AST entry type", soc);
1906 	}
1907 
1908 	ast_entry->is_active = TRUE;
1909 	DP_STATS_INC(soc, ast.added, 1);
1910 	soc->num_ast_entries++;
1911 	dp_peer_ast_hash_add(soc, ast_entry);
1912 
1913 	if ((ast_entry->type != CDP_TXRX_AST_TYPE_STATIC) &&
1914 	    (ast_entry->type != CDP_TXRX_AST_TYPE_SELF) &&
1915 	    (ast_entry->type != CDP_TXRX_AST_TYPE_STA_BSS) &&
1916 	    (ast_entry->type != CDP_TXRX_AST_TYPE_WDS_HM_SEC))
1917 		status = dp_add_wds_entry_wrapper(soc,
1918 						  peer,
1919 						  mac_addr,
1920 						  flags,
1921 						  ast_entry->type);
1922 
1923 	if (vap_bss_peer)
1924 		dp_peer_unref_delete(vap_bss_peer, DP_MOD_ID_AST);
1925 
1926 	qdf_spin_unlock_bh(&soc->ast_lock);
1927 	return qdf_status_from_os_return(status);
1928 }
1929 
1930 qdf_export_symbol(dp_peer_add_ast);
1931 
1932 void dp_peer_free_ast_entry(struct dp_soc *soc,
1933 			    struct dp_ast_entry *ast_entry)
1934 {
1935 	/*
1936 	 * NOTE: Ensure that call to this API is done
1937 	 * after soc->ast_lock is taken
1938 	 */
1939 	dp_peer_debug("type: %d ID: %u vid: %u mac_addr: " QDF_MAC_ADDR_FMT,
1940 		      ast_entry->type, ast_entry->peer_id, ast_entry->vdev_id,
1941 		      QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw));
1942 
1943 	ast_entry->callback = NULL;
1944 	ast_entry->cookie = NULL;
1945 
1946 	DP_STATS_INC(soc, ast.deleted, 1);
1947 	dp_peer_ast_hash_remove(soc, ast_entry);
1948 	dp_peer_ast_cleanup(soc, ast_entry);
1949 	qdf_mem_free(ast_entry);
1950 	soc->num_ast_entries--;
1951 }
1952 
1953 void dp_peer_unlink_ast_entry(struct dp_soc *soc,
1954 			      struct dp_ast_entry *ast_entry,
1955 			      struct dp_peer *peer)
1956 {
1957 	if (!peer) {
1958 		dp_info_rl("NULL peer");
1959 		return;
1960 	}
1961 
1962 	if (ast_entry->peer_id == HTT_INVALID_PEER) {
1963 		dp_info_rl("Invalid peer id in AST entry mac addr:"QDF_MAC_ADDR_FMT" type:%d",
1964 			  QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw),
1965 			  ast_entry->type);
1966 		return;
1967 	}
1968 	/*
1969 	 * NOTE: Ensure that call to this API is done
1970 	 * after soc->ast_lock is taken
1971 	 */
1972 
1973 	qdf_assert_always(ast_entry->peer_id == peer->peer_id);
1974 	TAILQ_REMOVE(&peer->ast_entry_list, ast_entry, ase_list_elem);
1975 
1976 	if (ast_entry == peer->self_ast_entry)
1977 		peer->self_ast_entry = NULL;
1978 
1979 	/*
1980 	 * release the reference only if it is mapped
1981 	 * to ast_table
1982 	 */
1983 	if (ast_entry->is_mapped)
1984 		soc->ast_table[ast_entry->ast_idx] = NULL;
1985 
1986 	ast_entry->peer_id = HTT_INVALID_PEER;
1987 }
1988 
1989 void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry)
1990 {
1991 	struct dp_peer *peer = NULL;
1992 
1993 	if (soc->ast_offload_support)
1994 		return;
1995 
1996 	if (!ast_entry) {
1997 		dp_info_rl("NULL AST entry");
1998 		return;
1999 	}
2000 
2001 	if (ast_entry->delete_in_progress) {
2002 		dp_info_rl("AST entry deletion in progress mac addr:"QDF_MAC_ADDR_FMT" type:%d",
2003 			  QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw),
2004 			  ast_entry->type);
2005 		return;
2006 	}
2007 
2008 	dp_peer_debug("call by %ps: ID: %u vid: %u mac_addr: " QDF_MAC_ADDR_FMT,
2009 		      (void *)_RET_IP_, ast_entry->peer_id, ast_entry->vdev_id,
2010 		      QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw));
2011 
2012 	ast_entry->delete_in_progress = true;
2013 
2014 	/* In teardown del ast is called after setting logical delete state
2015 	 * use __dp_peer_get_ref_by_id to get the reference irrespective of
2016 	 * state
2017 	 */
2018 	peer = __dp_peer_get_ref_by_id(soc, ast_entry->peer_id,
2019 				       DP_MOD_ID_AST);
2020 
2021 	dp_peer_ast_send_wds_del(soc, ast_entry, peer);
2022 
2023 	/* Remove SELF and STATIC entries in teardown itself */
2024 	if (!ast_entry->next_hop)
2025 		dp_peer_unlink_ast_entry(soc, ast_entry, peer);
2026 
2027 	if (ast_entry->is_mapped)
2028 		soc->ast_table[ast_entry->ast_idx] = NULL;
2029 
2030 	/* if peer map v2 is enabled we are not freeing ast entry
2031 	 * here and it is supposed to be freed in unmap event (after
2032 	 * we receive delete confirmation from target)
2033 	 *
2034 	 * if peer_id is invalid we did not get the peer map event
2035 	 * for the peer free ast entry from here only in this case
2036 	 */
2037 	if (dp_peer_ast_free_in_unmap_supported(soc, ast_entry))
2038 		goto end;
2039 
2040 	/* for WDS secondary entry ast_entry->next_hop would be set so
2041 	 * unlinking has to be done explicitly here.
2042 	 * As this entry is not a mapped entry unmap notification from
2043 	 * FW will not come. Hence unlinkling is done right here.
2044 	 */
2045 
2046 	if (ast_entry->type == CDP_TXRX_AST_TYPE_WDS_HM_SEC)
2047 		dp_peer_unlink_ast_entry(soc, ast_entry, peer);
2048 
2049 	dp_peer_free_ast_entry(soc, ast_entry);
2050 
2051 end:
2052 	if (peer)
2053 		dp_peer_unref_delete(peer, DP_MOD_ID_AST);
2054 }
2055 
2056 int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer,
2057 		       struct dp_ast_entry *ast_entry, uint32_t flags)
2058 {
2059 	int ret = -1;
2060 	struct dp_peer *old_peer;
2061 
2062 	if (soc->ast_offload_support)
2063 		return QDF_STATUS_E_INVAL;
2064 
2065 	dp_peer_debug("%pK: ast_entry->type: %d pdevid: %u vdevid: %u flags: 0x%x mac_addr: " QDF_MAC_ADDR_FMT " peer_mac: " QDF_MAC_ADDR_FMT "\n",
2066 		      soc, ast_entry->type, peer->vdev->pdev->pdev_id,
2067 		      peer->vdev->vdev_id, flags,
2068 		      QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw),
2069 		      QDF_MAC_ADDR_REF(peer->mac_addr.raw));
2070 
2071 	/* Do not send AST update in below cases
2072 	 *  1) Ast entry delete has already triggered
2073 	 *  2) Peer delete is already triggered
2074 	 *  3) We did not get the HTT map for create event
2075 	 */
2076 	if (ast_entry->delete_in_progress ||
2077 	    !dp_peer_state_cmp(peer, DP_PEER_STATE_ACTIVE) ||
2078 	    !ast_entry->is_mapped)
2079 		return ret;
2080 
2081 	if ((ast_entry->type == CDP_TXRX_AST_TYPE_STATIC) ||
2082 	    (ast_entry->type == CDP_TXRX_AST_TYPE_SELF) ||
2083 	    (ast_entry->type == CDP_TXRX_AST_TYPE_STA_BSS) ||
2084 	    (ast_entry->type == CDP_TXRX_AST_TYPE_WDS_HM_SEC))
2085 		return 0;
2086 
2087 	/*
2088 	 * Avoids flood of WMI update messages sent to FW for same peer.
2089 	 */
2090 	if (qdf_unlikely(ast_entry->peer_id == peer->peer_id) &&
2091 	    (ast_entry->type == CDP_TXRX_AST_TYPE_WDS) &&
2092 	    (ast_entry->vdev_id == peer->vdev->vdev_id) &&
2093 	    (ast_entry->is_active))
2094 		return 0;
2095 
2096 	old_peer = dp_peer_get_ref_by_id(soc, ast_entry->peer_id,
2097 					 DP_MOD_ID_AST);
2098 	if (!old_peer)
2099 		return 0;
2100 
2101 	TAILQ_REMOVE(&old_peer->ast_entry_list, ast_entry, ase_list_elem);
2102 
2103 	dp_peer_unref_delete(old_peer, DP_MOD_ID_AST);
2104 
2105 	ast_entry->peer_id = peer->peer_id;
2106 	ast_entry->type = CDP_TXRX_AST_TYPE_WDS;
2107 	ast_entry->pdev_id = peer->vdev->pdev->pdev_id;
2108 	ast_entry->vdev_id = peer->vdev->vdev_id;
2109 	ast_entry->is_active = TRUE;
2110 	TAILQ_INSERT_TAIL(&peer->ast_entry_list, ast_entry, ase_list_elem);
2111 
2112 	ret = dp_update_wds_entry_wrapper(soc,
2113 					  peer,
2114 					  ast_entry->mac_addr.raw,
2115 					  flags);
2116 
2117 	return ret;
2118 }
2119 
2120 uint8_t dp_peer_ast_get_pdev_id(struct dp_soc *soc,
2121 				struct dp_ast_entry *ast_entry)
2122 {
2123 	return ast_entry->pdev_id;
2124 }
2125 
2126 uint8_t dp_peer_ast_get_next_hop(struct dp_soc *soc,
2127 				struct dp_ast_entry *ast_entry)
2128 {
2129 	return ast_entry->next_hop;
2130 }
2131 
2132 void dp_peer_ast_set_type(struct dp_soc *soc,
2133 				struct dp_ast_entry *ast_entry,
2134 				enum cdp_txrx_ast_entry_type type)
2135 {
2136 	ast_entry->type = type;
2137 }
2138 
2139 void dp_peer_ast_send_wds_del(struct dp_soc *soc,
2140 			      struct dp_ast_entry *ast_entry,
2141 			      struct dp_peer *peer)
2142 {
2143 	bool delete_in_fw = false;
2144 
2145 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_TRACE,
2146 		  "%s: ast_entry->type: %d pdevid: %u vdev: %u mac_addr: "QDF_MAC_ADDR_FMT" next_hop: %u peer_id: %uM\n",
2147 		  __func__, ast_entry->type, ast_entry->pdev_id,
2148 		  ast_entry->vdev_id,
2149 		  QDF_MAC_ADDR_REF(ast_entry->mac_addr.raw),
2150 		  ast_entry->next_hop, ast_entry->peer_id);
2151 
2152 	/*
2153 	 * If peer state is logical delete, the peer is about to get
2154 	 * teared down with a peer delete command to firmware,
2155 	 * which will cleanup all the wds ast entries.
2156 	 * So, no need to send explicit wds ast delete to firmware.
2157 	 */
2158 	if (ast_entry->next_hop) {
2159 		if (peer && dp_peer_state_cmp(peer,
2160 					      DP_PEER_STATE_LOGICAL_DELETE))
2161 			delete_in_fw = false;
2162 		else
2163 			delete_in_fw = true;
2164 
2165 		dp_del_wds_entry_wrapper(soc,
2166 					 ast_entry->vdev_id,
2167 					 ast_entry->mac_addr.raw,
2168 					 ast_entry->type,
2169 					 delete_in_fw);
2170 	}
2171 }
2172 #else
2173 void dp_peer_free_ast_entry(struct dp_soc *soc,
2174 			    struct dp_ast_entry *ast_entry)
2175 {
2176 }
2177 
2178 void dp_peer_unlink_ast_entry(struct dp_soc *soc,
2179 			      struct dp_ast_entry *ast_entry,
2180 			      struct dp_peer *peer)
2181 {
2182 }
2183 
2184 void dp_peer_ast_hash_remove(struct dp_soc *soc,
2185 			     struct dp_ast_entry *ase)
2186 {
2187 }
2188 
2189 struct dp_ast_entry *dp_peer_ast_hash_find_by_vdevid(struct dp_soc *soc,
2190 						     uint8_t *ast_mac_addr,
2191 						     uint8_t vdev_id)
2192 {
2193 	return NULL;
2194 }
2195 
2196 QDF_STATUS dp_peer_add_ast(struct dp_soc *soc,
2197 			   struct dp_peer *peer,
2198 			   uint8_t *mac_addr,
2199 			   enum cdp_txrx_ast_entry_type type,
2200 			   uint32_t flags)
2201 {
2202 	return QDF_STATUS_E_FAILURE;
2203 }
2204 
2205 void dp_peer_del_ast(struct dp_soc *soc, struct dp_ast_entry *ast_entry)
2206 {
2207 }
2208 
2209 int dp_peer_update_ast(struct dp_soc *soc, struct dp_peer *peer,
2210 			struct dp_ast_entry *ast_entry, uint32_t flags)
2211 {
2212 	return 1;
2213 }
2214 
2215 struct dp_ast_entry *dp_peer_ast_hash_find_soc(struct dp_soc *soc,
2216 					       uint8_t *ast_mac_addr)
2217 {
2218 	return NULL;
2219 }
2220 
2221 struct dp_ast_entry *dp_peer_ast_hash_find_soc_by_type(
2222 					struct dp_soc *soc,
2223 					uint8_t *ast_mac_addr,
2224 					enum cdp_txrx_ast_entry_type type)
2225 {
2226 	return NULL;
2227 }
2228 
2229 static inline
2230 QDF_STATUS dp_peer_host_add_map_ast(struct dp_soc *soc, uint16_t peer_id,
2231 				    uint8_t *mac_addr, uint16_t hw_peer_id,
2232 				    uint8_t vdev_id, uint16_t ast_hash,
2233 				    uint8_t is_wds)
2234 {
2235 	return QDF_STATUS_SUCCESS;
2236 }
2237 
2238 struct dp_ast_entry *dp_peer_ast_hash_find_by_pdevid(struct dp_soc *soc,
2239 						     uint8_t *ast_mac_addr,
2240 						     uint8_t pdev_id)
2241 {
2242 	return NULL;
2243 }
2244 
2245 QDF_STATUS dp_peer_ast_hash_attach(struct dp_soc *soc)
2246 {
2247 	return QDF_STATUS_SUCCESS;
2248 }
2249 
2250 static inline QDF_STATUS dp_peer_map_ast(struct dp_soc *soc,
2251 					 struct dp_peer *peer,
2252 					 uint8_t *mac_addr,
2253 					 uint16_t hw_peer_id,
2254 					 uint8_t vdev_id,
2255 					 uint16_t ast_hash,
2256 					 uint8_t is_wds)
2257 {
2258 	return QDF_STATUS_SUCCESS;
2259 }
2260 
2261 void dp_peer_ast_hash_detach(struct dp_soc *soc)
2262 {
2263 }
2264 
2265 void dp_peer_ast_set_type(struct dp_soc *soc,
2266 				struct dp_ast_entry *ast_entry,
2267 				enum cdp_txrx_ast_entry_type type)
2268 {
2269 }
2270 
2271 uint8_t dp_peer_ast_get_pdev_id(struct dp_soc *soc,
2272 				struct dp_ast_entry *ast_entry)
2273 {
2274 	return 0xff;
2275 }
2276 
2277 uint8_t dp_peer_ast_get_next_hop(struct dp_soc *soc,
2278 				 struct dp_ast_entry *ast_entry)
2279 {
2280 	return 0xff;
2281 }
2282 
2283 void dp_peer_ast_send_wds_del(struct dp_soc *soc,
2284 			      struct dp_ast_entry *ast_entry,
2285 			      struct dp_peer *peer)
2286 {
2287 }
2288 
2289 static inline
2290 void dp_peer_unmap_ipa_evt(struct dp_soc *soc, uint16_t peer_id,
2291 			   uint8_t vdev_id, uint8_t *mac_addr)
2292 {
2293 }
2294 #endif
2295 
2296 #ifdef WLAN_FEATURE_MULTI_AST_DEL
2297 void dp_peer_ast_send_multi_wds_del(
2298 		struct dp_soc *soc, uint8_t vdev_id,
2299 		struct peer_del_multi_wds_entries *wds_list)
2300 {
2301 	struct cdp_soc_t *cdp_soc = &soc->cdp_soc;
2302 
2303 	if (cdp_soc && cdp_soc->ol_ops &&
2304 	    cdp_soc->ol_ops->peer_del_multi_wds_entry)
2305 		cdp_soc->ol_ops->peer_del_multi_wds_entry(soc->ctrl_psoc,
2306 							  vdev_id, wds_list);
2307 }
2308 #endif
2309 
2310 #ifdef FEATURE_WDS
2311 /**
2312  * dp_peer_ast_free_wds_entries() - Free wds ast entries associated with peer
2313  * @soc: soc handle
2314  * @peer: peer handle
2315  *
2316  * Free all the wds ast entries associated with peer
2317  *
2318  * Return: Number of wds ast entries freed
2319  */
2320 static uint32_t dp_peer_ast_free_wds_entries(struct dp_soc *soc,
2321 					     struct dp_peer *peer)
2322 {
2323 	TAILQ_HEAD(, dp_ast_entry) ast_local_list = {0};
2324 	struct dp_ast_entry *ast_entry, *temp_ast_entry;
2325 	uint32_t num_ast = 0;
2326 
2327 	TAILQ_INIT(&ast_local_list);
2328 	qdf_spin_lock_bh(&soc->ast_lock);
2329 
2330 	DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, temp_ast_entry) {
2331 		if (ast_entry->next_hop)
2332 			num_ast++;
2333 
2334 		if (ast_entry->is_mapped)
2335 			soc->ast_table[ast_entry->ast_idx] = NULL;
2336 
2337 		dp_peer_unlink_ast_entry(soc, ast_entry, peer);
2338 		DP_STATS_INC(soc, ast.deleted, 1);
2339 		dp_peer_ast_hash_remove(soc, ast_entry);
2340 		TAILQ_INSERT_TAIL(&ast_local_list, ast_entry,
2341 				  ase_list_elem);
2342 		soc->num_ast_entries--;
2343 	}
2344 
2345 	qdf_spin_unlock_bh(&soc->ast_lock);
2346 
2347 	TAILQ_FOREACH_SAFE(ast_entry, &ast_local_list, ase_list_elem,
2348 			   temp_ast_entry) {
2349 		if (ast_entry->callback)
2350 			ast_entry->callback(soc->ctrl_psoc,
2351 					    dp_soc_to_cdp_soc(soc),
2352 					    ast_entry->cookie,
2353 					    CDP_TXRX_AST_DELETED);
2354 
2355 		qdf_mem_free(ast_entry);
2356 	}
2357 
2358 	return num_ast;
2359 }
2360 /**
2361  * dp_peer_clean_wds_entries() - Clean wds ast entries and compare
2362  * @soc: soc handle
2363  * @peer: peer handle
2364  * @free_wds_count: number of wds entries freed by FW with peer delete
2365  *
2366  * Free all the wds ast entries associated with peer and compare with
2367  * the value received from firmware
2368  *
2369  * Return: Number of wds ast entries freed
2370  */
2371 static void
2372 dp_peer_clean_wds_entries(struct dp_soc *soc, struct dp_peer *peer,
2373 			  uint32_t free_wds_count)
2374 {
2375 	uint32_t wds_deleted = 0;
2376 	bool ast_ind_disable;
2377 
2378 	if (soc->ast_offload_support && !soc->host_ast_db_enable)
2379 		return;
2380 
2381 	ast_ind_disable = wlan_cfg_get_ast_indication_disable
2382 		(soc->wlan_cfg_ctx);
2383 
2384 	wds_deleted = dp_peer_ast_free_wds_entries(soc, peer);
2385 	if ((DP_PEER_WDS_COUNT_INVALID != free_wds_count) &&
2386 	    (free_wds_count != wds_deleted) && !ast_ind_disable) {
2387 		DP_STATS_INC(soc, ast.ast_mismatch, 1);
2388 		dp_alert("For peer %pK (mac: "QDF_MAC_ADDR_FMT")number of wds entries deleted by fw = %d during peer delete is not same as the numbers deleted by host = %d",
2389 			 peer, peer->mac_addr.raw, free_wds_count,
2390 			 wds_deleted);
2391 	}
2392 }
2393 
2394 #else
2395 static void
2396 dp_peer_clean_wds_entries(struct dp_soc *soc, struct dp_peer *peer,
2397 			  uint32_t free_wds_count)
2398 {
2399 	struct dp_ast_entry *ast_entry, *temp_ast_entry;
2400 
2401 	qdf_spin_lock_bh(&soc->ast_lock);
2402 
2403 	DP_PEER_ITERATE_ASE_LIST(peer, ast_entry, temp_ast_entry) {
2404 		dp_peer_unlink_ast_entry(soc, ast_entry, peer);
2405 
2406 		if (ast_entry->is_mapped)
2407 			soc->ast_table[ast_entry->ast_idx] = NULL;
2408 
2409 		dp_peer_free_ast_entry(soc, ast_entry);
2410 	}
2411 
2412 	peer->self_ast_entry = NULL;
2413 	qdf_spin_unlock_bh(&soc->ast_lock);
2414 }
2415 #endif
2416 
2417 /**
2418  * dp_peer_ast_free_entry_by_mac() - find ast entry by MAC address and delete
2419  * @soc: soc handle
2420  * @peer: peer handle
2421  * @vdev_id: vdev_id
2422  * @mac_addr: mac address of the AST entry to searc and delete
2423  *
2424  * find the ast entry from the peer list using the mac address and free
2425  * the entry.
2426  *
2427  * Return: SUCCESS or NOENT
2428  */
2429 static int dp_peer_ast_free_entry_by_mac(struct dp_soc *soc,
2430 					 struct dp_peer *peer,
2431 					 uint8_t vdev_id,
2432 					 uint8_t *mac_addr)
2433 {
2434 	struct dp_ast_entry *ast_entry;
2435 	void *cookie = NULL;
2436 	txrx_ast_free_cb cb = NULL;
2437 
2438 	/*
2439 	 * release the reference only if it is mapped
2440 	 * to ast_table
2441 	 */
2442 
2443 	qdf_spin_lock_bh(&soc->ast_lock);
2444 
2445 	ast_entry = dp_peer_ast_hash_find_by_vdevid(soc, mac_addr, vdev_id);
2446 	if (!ast_entry) {
2447 		qdf_spin_unlock_bh(&soc->ast_lock);
2448 		return QDF_STATUS_E_NOENT;
2449 	} else if (ast_entry->is_mapped) {
2450 		soc->ast_table[ast_entry->ast_idx] = NULL;
2451 	}
2452 
2453 	cb = ast_entry->callback;
2454 	cookie = ast_entry->cookie;
2455 
2456 
2457 	dp_peer_unlink_ast_entry(soc, ast_entry, peer);
2458 
2459 	dp_peer_free_ast_entry(soc, ast_entry);
2460 
2461 	qdf_spin_unlock_bh(&soc->ast_lock);
2462 
2463 	if (cb) {
2464 		cb(soc->ctrl_psoc,
2465 		   dp_soc_to_cdp_soc(soc),
2466 		   cookie,
2467 		   CDP_TXRX_AST_DELETED);
2468 	}
2469 
2470 	return QDF_STATUS_SUCCESS;
2471 }
2472 
2473 void dp_peer_find_hash_erase(struct dp_soc *soc)
2474 {
2475 	int i;
2476 
2477 	/*
2478 	 * Not really necessary to take peer_ref_mutex lock - by this point,
2479 	 * it's known that the soc is no longer in use.
2480 	 */
2481 	for (i = 0; i <= soc->peer_hash.mask; i++) {
2482 		if (!TAILQ_EMPTY(&soc->peer_hash.bins[i])) {
2483 			struct dp_peer *peer, *peer_next;
2484 
2485 			/*
2486 			 * TAILQ_FOREACH_SAFE must be used here to avoid any
2487 			 * memory access violation after peer is freed
2488 			 */
2489 			TAILQ_FOREACH_SAFE(peer, &soc->peer_hash.bins[i],
2490 				hash_list_elem, peer_next) {
2491 				/*
2492 				 * Don't remove the peer from the hash table -
2493 				 * that would modify the list we are currently
2494 				 * traversing, and it's not necessary anyway.
2495 				 */
2496 				/*
2497 				 * Artificially adjust the peer's ref count to
2498 				 * 1, so it will get deleted by
2499 				 * dp_peer_unref_delete.
2500 				 */
2501 				/* set to zero */
2502 				qdf_atomic_init(&peer->ref_cnt);
2503 				for (i = 0; i < DP_MOD_ID_MAX; i++)
2504 					qdf_atomic_init(&peer->mod_refs[i]);
2505 				/* incr to one */
2506 				qdf_atomic_inc(&peer->ref_cnt);
2507 				qdf_atomic_inc(&peer->mod_refs
2508 						[DP_MOD_ID_CONFIG]);
2509 				dp_peer_unref_delete(peer,
2510 						     DP_MOD_ID_CONFIG);
2511 			}
2512 		}
2513 	}
2514 }
2515 
2516 void dp_peer_ast_table_detach(struct dp_soc *soc)
2517 {
2518 	if (soc->ast_table) {
2519 		qdf_mem_free(soc->ast_table);
2520 		soc->ast_table = NULL;
2521 	}
2522 }
2523 
2524 void dp_peer_find_map_detach(struct dp_soc *soc)
2525 {
2526 	struct dp_peer *peer = NULL;
2527 	uint32_t i = 0;
2528 
2529 	if (soc->peer_id_to_obj_map) {
2530 		for (i = 0; i < soc->max_peer_id; i++) {
2531 			peer = soc->peer_id_to_obj_map[i];
2532 			if (peer)
2533 				dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
2534 		}
2535 		qdf_mem_free(soc->peer_id_to_obj_map);
2536 		soc->peer_id_to_obj_map = NULL;
2537 		qdf_spinlock_destroy(&soc->peer_map_lock);
2538 	}
2539 }
2540 
2541 #ifndef AST_OFFLOAD_ENABLE
2542 QDF_STATUS dp_peer_find_attach(struct dp_soc *soc)
2543 {
2544 	QDF_STATUS status;
2545 
2546 	status = dp_peer_find_map_attach(soc);
2547 	if (!QDF_IS_STATUS_SUCCESS(status))
2548 		return status;
2549 
2550 	status = dp_peer_find_hash_attach(soc);
2551 	if (!QDF_IS_STATUS_SUCCESS(status))
2552 		goto map_detach;
2553 
2554 	status = dp_peer_ast_table_attach(soc);
2555 	if (!QDF_IS_STATUS_SUCCESS(status))
2556 		goto hash_detach;
2557 
2558 	status = dp_peer_ast_hash_attach(soc);
2559 	if (!QDF_IS_STATUS_SUCCESS(status))
2560 		goto ast_table_detach;
2561 
2562 	status = dp_peer_mec_hash_attach(soc);
2563 	if (QDF_IS_STATUS_SUCCESS(status)) {
2564 		dp_soc_wds_attach(soc);
2565 		return status;
2566 	}
2567 
2568 	dp_peer_ast_hash_detach(soc);
2569 ast_table_detach:
2570 	dp_peer_ast_table_detach(soc);
2571 hash_detach:
2572 	dp_peer_find_hash_detach(soc);
2573 map_detach:
2574 	dp_peer_find_map_detach(soc);
2575 
2576 	return status;
2577 }
2578 #else
2579 QDF_STATUS dp_peer_find_attach(struct dp_soc *soc)
2580 {
2581 	QDF_STATUS status;
2582 
2583 	status = dp_peer_find_map_attach(soc);
2584 	if (!QDF_IS_STATUS_SUCCESS(status))
2585 		return status;
2586 
2587 	status = dp_peer_find_hash_attach(soc);
2588 	if (!QDF_IS_STATUS_SUCCESS(status))
2589 		goto map_detach;
2590 
2591 	return status;
2592 map_detach:
2593 	dp_peer_find_map_detach(soc);
2594 
2595 	return status;
2596 }
2597 #endif
2598 
2599 #ifdef REO_SHARED_QREF_TABLE_EN
2600 void dp_peer_rx_reo_shared_qaddr_delete(struct dp_soc *soc,
2601 					struct dp_peer *peer)
2602 {
2603 	uint8_t tid;
2604 	uint16_t peer_id;
2605 	uint32_t max_list_size;
2606 
2607 	max_list_size = soc->wlan_cfg_ctx->qref_control_size;
2608 
2609 	peer_id = peer->peer_id;
2610 
2611 	if (peer_id > soc->max_peer_id)
2612 		return;
2613 	if (IS_MLO_DP_LINK_PEER(peer))
2614 		return;
2615 
2616 	if (max_list_size) {
2617 		unsigned long curr_ts = qdf_get_system_timestamp();
2618 		struct dp_peer *primary_peer = peer;
2619 		uint16_t chip_id = 0xFFFF;
2620 		uint32_t qref_index;
2621 
2622 		qref_index = soc->shared_qaddr_del_idx;
2623 
2624 		soc->list_shared_qaddr_del[qref_index].peer_id =
2625 							  primary_peer->peer_id;
2626 		soc->list_shared_qaddr_del[qref_index].ts_qaddr_del = curr_ts;
2627 		soc->list_shared_qaddr_del[qref_index].chip_id = chip_id;
2628 		soc->shared_qaddr_del_idx++;
2629 
2630 		if (soc->shared_qaddr_del_idx == max_list_size)
2631 			soc->shared_qaddr_del_idx = 0;
2632 	}
2633 
2634 	if (hal_reo_shared_qaddr_is_enable(soc->hal_soc)) {
2635 		for (tid = 0; tid < DP_MAX_TIDS; tid++) {
2636 			hal_reo_shared_qaddr_write(soc->hal_soc,
2637 						   peer_id, tid, 0);
2638 		}
2639 	}
2640 }
2641 #endif
2642 
2643 /**
2644  * dp_peer_find_add_id() - map peer_id with peer
2645  * @soc: soc handle
2646  * @peer_mac_addr: peer mac address
2647  * @peer_id: peer id to be mapped
2648  * @hw_peer_id: HW ast index
2649  * @vdev_id: vdev_id
2650  * @peer_type: peer type (link or MLD)
2651  *
2652  * return: peer in success
2653  *         NULL in failure
2654  */
2655 static inline struct dp_peer *dp_peer_find_add_id(struct dp_soc *soc,
2656 	uint8_t *peer_mac_addr, uint16_t peer_id, uint16_t hw_peer_id,
2657 	uint8_t vdev_id, enum cdp_peer_type peer_type)
2658 {
2659 	struct dp_peer *peer;
2660 	struct cdp_peer_info peer_info = { 0 };
2661 
2662 	QDF_ASSERT(peer_id <= soc->max_peer_id);
2663 	/* check if there's already a peer object with this MAC address */
2664 	DP_PEER_INFO_PARAMS_INIT(&peer_info, vdev_id, peer_mac_addr,
2665 				 false, peer_type);
2666 	peer = dp_peer_hash_find_wrapper(soc, &peer_info, DP_MOD_ID_CONFIG);
2667 	dp_peer_debug("%pK: peer %pK ID %d vid %d mac " QDF_MAC_ADDR_FMT,
2668 		      soc, peer, peer_id, vdev_id,
2669 		      QDF_MAC_ADDR_REF(peer_mac_addr));
2670 
2671 	if (peer) {
2672 		/* peer's ref count was already incremented by
2673 		 * peer_find_hash_find
2674 		 */
2675 		dp_peer_info("%pK: ref_cnt: %d", soc,
2676 			     qdf_atomic_read(&peer->ref_cnt));
2677 
2678 		/*
2679 		 * if peer is in logical delete CP triggered delete before map
2680 		 * is received ignore this event
2681 		 */
2682 		if (dp_peer_state_cmp(peer, DP_PEER_STATE_LOGICAL_DELETE)) {
2683 			dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
2684 			dp_alert("Peer %pK["QDF_MAC_ADDR_FMT"] logical delete state vid %d",
2685 				 peer, QDF_MAC_ADDR_REF(peer_mac_addr),
2686 				 vdev_id);
2687 			return NULL;
2688 		}
2689 
2690 		if (peer->peer_id == HTT_INVALID_PEER) {
2691 			if (!IS_MLO_DP_MLD_PEER(peer))
2692 				dp_monitor_peer_tid_peer_id_update(soc, peer,
2693 								   peer_id);
2694 		} else {
2695 			dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
2696 			QDF_ASSERT(0);
2697 			return NULL;
2698 		}
2699 		dp_peer_find_id_to_obj_add(soc, peer, peer_id);
2700 		if (soc->arch_ops.dp_partner_chips_map)
2701 			soc->arch_ops.dp_partner_chips_map(soc, peer, peer_id);
2702 
2703 		dp_peer_update_state(soc, peer, DP_PEER_STATE_ACTIVE);
2704 		return peer;
2705 	}
2706 
2707 	return NULL;
2708 }
2709 
2710 #ifdef WLAN_FEATURE_11BE_MLO
2711 #ifdef DP_USE_REDUCED_PEER_ID_FIELD_WIDTH
2712 uint16_t dp_gen_ml_peer_id(struct dp_soc *soc, uint16_t peer_id)
2713 {
2714 	return ((peer_id & soc->peer_id_mask) | (1 << soc->peer_id_shift));
2715 }
2716 #else
2717 uint16_t dp_gen_ml_peer_id(struct dp_soc *soc, uint16_t peer_id)
2718 {
2719 	return (peer_id | (1 << HTT_RX_PEER_META_DATA_V1_ML_PEER_VALID_S));
2720 }
2721 #endif
2722 
2723 QDF_STATUS
2724 dp_rx_mlo_peer_map_handler(struct dp_soc *soc, uint16_t peer_id,
2725 			   uint8_t *peer_mac_addr,
2726 			   struct dp_mlo_flow_override_info *mlo_flow_info,
2727 			   struct dp_mlo_link_info *mlo_link_info)
2728 {
2729 	struct dp_peer *peer = NULL;
2730 	uint16_t hw_peer_id = mlo_flow_info[0].ast_idx;
2731 	uint16_t ast_hash = mlo_flow_info[0].cache_set_num;
2732 	uint8_t vdev_id = 0;
2733 	uint8_t is_wds = 0;
2734 	int i;
2735 	uint16_t ml_peer_id = dp_gen_ml_peer_id(soc, peer_id);
2736 	enum cdp_txrx_ast_entry_type type = CDP_TXRX_AST_TYPE_STATIC;
2737 	QDF_STATUS err = QDF_STATUS_SUCCESS;
2738 	struct dp_soc *primary_soc = NULL;
2739 
2740 	dp_cfg_event_record_peer_map_unmap_evt(soc, DP_CFG_EVENT_MLO_PEER_MAP,
2741 					       NULL, peer_mac_addr,
2742 					       1, peer_id, ml_peer_id, 0,
2743 					       vdev_id);
2744 
2745 	dp_info("mlo_peer_map_event (soc:%pK): peer_id %d ml_peer_id %d, peer_mac "QDF_MAC_ADDR_FMT,
2746 		soc, peer_id, ml_peer_id,
2747 		QDF_MAC_ADDR_REF(peer_mac_addr));
2748 
2749 	DP_STATS_INC(soc, t2h_msg_stats.ml_peer_map, 1);
2750 	/* Get corresponding vdev ID for the peer based
2751 	 * on chip ID obtained from mlo peer_map event
2752 	 */
2753 	for (i = 0; i < DP_MAX_MLO_LINKS; i++) {
2754 		if (mlo_link_info[i].peer_chip_id == dp_get_chip_id(soc)) {
2755 			vdev_id = mlo_link_info[i].vdev_id;
2756 			break;
2757 		}
2758 	}
2759 
2760 	peer = dp_peer_find_add_id(soc, peer_mac_addr, ml_peer_id,
2761 				   hw_peer_id, vdev_id, CDP_MLD_PEER_TYPE);
2762 	if (peer) {
2763 		if (wlan_op_mode_sta == peer->vdev->opmode &&
2764 		    qdf_mem_cmp(peer->mac_addr.raw,
2765 				peer->vdev->mld_mac_addr.raw,
2766 				QDF_MAC_ADDR_SIZE) != 0) {
2767 			dp_peer_info("%pK: STA vdev bss_peer!!!!", soc);
2768 			peer->bss_peer = 1;
2769 			if (peer->txrx_peer)
2770 				peer->txrx_peer->bss_peer = 1;
2771 		}
2772 
2773 		if (peer->vdev->opmode == wlan_op_mode_sta) {
2774 			peer->vdev->bss_ast_hash = ast_hash;
2775 			peer->vdev->bss_ast_idx = hw_peer_id;
2776 		}
2777 
2778 		/* Add ast entry incase self ast entry is
2779 		 * deleted due to DP CP sync issue
2780 		 *
2781 		 * self_ast_entry is modified in peer create
2782 		 * and peer unmap path which cannot run in
2783 		 * parllel with peer map, no lock need before
2784 		 * referring it
2785 		 */
2786 		if (!peer->self_ast_entry) {
2787 			dp_info("Add self ast from map "QDF_MAC_ADDR_FMT,
2788 				QDF_MAC_ADDR_REF(peer_mac_addr));
2789 			dp_peer_add_ast(soc, peer,
2790 					peer_mac_addr,
2791 					type, 0);
2792 		}
2793 		/* If peer setup and hence rx_tid setup got called
2794 		 * before htt peer map then Qref write to LUT did not
2795 		 * happen in rx_tid setup as peer_id was invalid.
2796 		 * So defer Qref write to peer map handler. Check if
2797 		 * rx_tid qdesc for tid 0 is already setup and perform
2798 		 * qref write to LUT for Tid 0 and 16.
2799 		 *
2800 		 * Peer map could be obtained on assoc link, hence
2801 		 * change to primary link's soc.
2802 		 */
2803 		primary_soc = peer->vdev->pdev->soc;
2804 		if (hal_reo_shared_qaddr_is_enable(primary_soc->hal_soc) &&
2805 		    peer->rx_tid[0].hw_qdesc_vaddr_unaligned) {
2806 			hal_reo_shared_qaddr_write(primary_soc->hal_soc,
2807 						   ml_peer_id,
2808 						   0,
2809 						   peer->rx_tid[0].hw_qdesc_paddr);
2810 			hal_reo_shared_qaddr_write(primary_soc->hal_soc,
2811 						   ml_peer_id,
2812 						   DP_NON_QOS_TID,
2813 						   peer->rx_tid[DP_NON_QOS_TID].hw_qdesc_paddr);
2814 		}
2815 	}
2816 
2817 	if (!primary_soc)
2818 		primary_soc = soc;
2819 
2820 	err = dp_peer_map_ast(soc, peer, peer_mac_addr, hw_peer_id,
2821 			      vdev_id, ast_hash, is_wds);
2822 
2823 	/*
2824 	 * If AST offload and host AST DB is enabled, populate AST entries on
2825 	 * host based on mlo peer map event from FW
2826 	 */
2827 	if (peer && soc->ast_offload_support && soc->host_ast_db_enable) {
2828 		dp_peer_host_add_map_ast(primary_soc, ml_peer_id, peer_mac_addr,
2829 					 hw_peer_id, vdev_id,
2830 					 ast_hash, is_wds);
2831 	}
2832 
2833 	return err;
2834 }
2835 #endif
2836 
2837 #ifdef DP_RX_UDP_OVER_PEER_ROAM
2838 void dp_rx_reset_roaming_peer(struct dp_soc *soc, uint8_t vdev_id,
2839 			      uint8_t *peer_mac_addr)
2840 {
2841 	struct dp_vdev *vdev = NULL;
2842 
2843 	vdev = dp_vdev_get_ref_by_id(soc, vdev_id, DP_MOD_ID_HTT);
2844 	if (vdev) {
2845 		if (qdf_mem_cmp(vdev->roaming_peer_mac.raw, peer_mac_addr,
2846 				QDF_MAC_ADDR_SIZE) == 0) {
2847 			vdev->roaming_peer_status =
2848 						WLAN_ROAM_PEER_AUTH_STATUS_NONE;
2849 			qdf_mem_zero(vdev->roaming_peer_mac.raw,
2850 				     QDF_MAC_ADDR_SIZE);
2851 		}
2852 		dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_HTT);
2853 	}
2854 }
2855 #endif
2856 
2857 #ifdef WLAN_SUPPORT_PPEDS
2858 static void
2859 dp_tx_ppeds_cfg_astidx_cache_mapping(struct dp_soc *soc, struct dp_vdev *vdev,
2860 				     bool peer_map)
2861 {
2862 	if (soc->arch_ops.dp_tx_ppeds_cfg_astidx_cache_mapping)
2863 		soc->arch_ops.dp_tx_ppeds_cfg_astidx_cache_mapping(soc, vdev,
2864 								   peer_map);
2865 }
2866 #else
2867 static void
2868 dp_tx_ppeds_cfg_astidx_cache_mapping(struct dp_soc *soc, struct dp_vdev *vdev,
2869 				     bool peer_map)
2870 {
2871 }
2872 #endif
2873 
2874 QDF_STATUS
2875 dp_rx_peer_map_handler(struct dp_soc *soc, uint16_t peer_id,
2876 		       uint16_t hw_peer_id, uint8_t vdev_id,
2877 		       uint8_t *peer_mac_addr, uint16_t ast_hash,
2878 		       uint8_t is_wds)
2879 {
2880 	struct dp_peer *peer = NULL;
2881 	struct dp_vdev *vdev = NULL;
2882 	enum cdp_txrx_ast_entry_type type = CDP_TXRX_AST_TYPE_STATIC;
2883 	QDF_STATUS err = QDF_STATUS_SUCCESS;
2884 
2885 	dp_cfg_event_record_peer_map_unmap_evt(soc, DP_CFG_EVENT_PEER_MAP,
2886 					       NULL, peer_mac_addr, 1, peer_id,
2887 					       0, 0, vdev_id);
2888 	dp_info("peer_map_event (soc:%pK): peer_id %d, hw_peer_id %d, peer_mac "QDF_MAC_ADDR_FMT", vdev_id %d",
2889 		soc, peer_id, hw_peer_id,
2890 		QDF_MAC_ADDR_REF(peer_mac_addr), vdev_id);
2891 	DP_STATS_INC(soc, t2h_msg_stats.peer_map, 1);
2892 
2893 	/* Peer map event for WDS ast entry get the peer from
2894 	 * obj map
2895 	 */
2896 	if (is_wds) {
2897 		if (!soc->ast_offload_support) {
2898 			peer = dp_peer_get_ref_by_id(soc, peer_id,
2899 						     DP_MOD_ID_HTT);
2900 
2901 			err = dp_peer_map_ast(soc, peer, peer_mac_addr,
2902 					      hw_peer_id,
2903 					      vdev_id, ast_hash, is_wds);
2904 			if (peer)
2905 				dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
2906 		}
2907 	} else {
2908 		/*
2909 		 * It's the responsibility of the CP and FW to ensure
2910 		 * that peer is created successfully. Ideally DP should
2911 		 * not hit the below condition for directly associated
2912 		 * peers.
2913 		 */
2914 		if ((!soc->ast_offload_support) && ((hw_peer_id < 0) ||
2915 		    (hw_peer_id >=
2916 		     wlan_cfg_get_max_ast_idx(soc->wlan_cfg_ctx)))) {
2917 			dp_peer_err("%pK: invalid hw_peer_id: %d", soc, hw_peer_id);
2918 			qdf_assert_always(0);
2919 		}
2920 
2921 		peer = dp_peer_find_add_id(soc, peer_mac_addr, peer_id,
2922 					   hw_peer_id, vdev_id,
2923 					   CDP_LINK_PEER_TYPE);
2924 
2925 		if (peer) {
2926 			bool peer_map = true;
2927 
2928 			/* Updating ast_hash and ast_idx in peer level */
2929 			peer->ast_hash = ast_hash;
2930 			peer->ast_idx = hw_peer_id;
2931 			vdev = peer->vdev;
2932 			/* Only check for STA Vdev and peer is not for TDLS */
2933 			if (wlan_op_mode_sta == vdev->opmode &&
2934 			    !peer->is_tdls_peer) {
2935 				if (qdf_mem_cmp(peer->mac_addr.raw,
2936 						vdev->mac_addr.raw,
2937 						QDF_MAC_ADDR_SIZE) != 0) {
2938 					dp_info("%pK: STA vdev bss_peer", soc);
2939 					peer->bss_peer = 1;
2940 					if (peer->txrx_peer)
2941 						peer->txrx_peer->bss_peer = 1;
2942 				}
2943 
2944 				dp_info("bss ast_hash 0x%x, ast_index 0x%x",
2945 					ast_hash, hw_peer_id);
2946 				vdev->bss_ast_hash = ast_hash;
2947 				vdev->bss_ast_idx = hw_peer_id;
2948 
2949 				dp_tx_ppeds_cfg_astidx_cache_mapping(soc, vdev,
2950 								     peer_map);
2951 			}
2952 
2953 			/* Add ast entry incase self ast entry is
2954 			 * deleted due to DP CP sync issue
2955 			 *
2956 			 * self_ast_entry is modified in peer create
2957 			 * and peer unmap path which cannot run in
2958 			 * parllel with peer map, no lock need before
2959 			 * referring it
2960 			 */
2961 			if (!soc->ast_offload_support &&
2962 				!peer->self_ast_entry) {
2963 				dp_info("Add self ast from map "QDF_MAC_ADDR_FMT,
2964 					QDF_MAC_ADDR_REF(peer_mac_addr));
2965 				dp_peer_add_ast(soc, peer,
2966 						peer_mac_addr,
2967 						type, 0);
2968 			}
2969 
2970 			/* If peer setup and hence rx_tid setup got called
2971 			 * before htt peer map then Qref write to LUT did
2972 			 * not happen in rx_tid setup as peer_id was invalid.
2973 			 * So defer Qref write to peer map handler. Check if
2974 			 * rx_tid qdesc for tid 0 is already setup perform qref
2975 			 * write to LUT for Tid 0 and 16.
2976 			 */
2977 			if (hal_reo_shared_qaddr_is_enable(soc->hal_soc) &&
2978 			    peer->rx_tid[0].hw_qdesc_vaddr_unaligned &&
2979 			    !IS_MLO_DP_LINK_PEER(peer)) {
2980 				add_entry_write_list(soc, peer, 0);
2981 				hal_reo_shared_qaddr_write(soc->hal_soc,
2982 							   peer_id,
2983 							   0,
2984 							   peer->rx_tid[0].hw_qdesc_paddr);
2985 				add_entry_write_list(soc, peer, DP_NON_QOS_TID);
2986 				hal_reo_shared_qaddr_write(soc->hal_soc,
2987 							   peer_id,
2988 							   DP_NON_QOS_TID,
2989 							   peer->rx_tid[DP_NON_QOS_TID].hw_qdesc_paddr);
2990 			}
2991 		}
2992 
2993 		err = dp_peer_map_ast(soc, peer, peer_mac_addr, hw_peer_id,
2994 				      vdev_id, ast_hash, is_wds);
2995 	}
2996 
2997 	dp_rx_reset_roaming_peer(soc, vdev_id, peer_mac_addr);
2998 
2999 	/*
3000 	 * If AST offload and host AST DB is enabled, populate AST entries on
3001 	 * host based on peer map event from FW
3002 	 */
3003 	if (soc->ast_offload_support && soc->host_ast_db_enable) {
3004 		dp_peer_host_add_map_ast(soc, peer_id, peer_mac_addr,
3005 					 hw_peer_id, vdev_id,
3006 					 ast_hash, is_wds);
3007 	}
3008 
3009 	return err;
3010 }
3011 
3012 void
3013 dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id,
3014 			 uint8_t vdev_id, uint8_t *mac_addr,
3015 			 uint8_t is_wds, uint32_t free_wds_count)
3016 {
3017 	struct dp_peer *peer;
3018 	struct dp_vdev *vdev = NULL;
3019 
3020 	DP_STATS_INC(soc, t2h_msg_stats.peer_unmap, 1);
3021 
3022 	/*
3023 	 * If FW AST offload is enabled and host AST DB is enabled,
3024 	 * the AST entries are created during peer map from FW.
3025 	 */
3026 	if (soc->ast_offload_support && is_wds) {
3027 		if (!soc->host_ast_db_enable)
3028 			return;
3029 	}
3030 
3031 	peer = __dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_HTT);
3032 
3033 	/*
3034 	 * Currently peer IDs are assigned for vdevs as well as peers.
3035 	 * If the peer ID is for a vdev, then the peer pointer stored
3036 	 * in peer_id_to_obj_map will be NULL.
3037 	 */
3038 	if (!peer) {
3039 		dp_err("Received unmap event for invalid peer_id %u",
3040 		       peer_id);
3041 		DP_STATS_INC(soc, t2h_msg_stats.invalid_peer_unmap, 1);
3042 		return;
3043 	}
3044 
3045 	vdev = peer->vdev;
3046 
3047 	if (peer->txrx_peer) {
3048 		struct cdp_txrx_peer_params_update params = {0};
3049 
3050 		params.vdev_id = vdev->vdev_id;
3051 		params.peer_mac = peer->mac_addr.raw;
3052 		params.chip_id = dp_get_chip_id(soc);
3053 		params.pdev_id = vdev->pdev->pdev_id;
3054 
3055 		dp_wdi_event_handler(WDI_EVENT_PEER_UNMAP, soc,
3056 				     (void *)&params, peer_id,
3057 				     WDI_NO_VAL, vdev->pdev->pdev_id);
3058 	}
3059 
3060 	/*
3061 	 * In scenario where assoc peer soc id is different from
3062 	 * primary soc id, reset the soc to point to primary psoc.
3063 	 * Since map is received on primary soc, the unmap should
3064 	 * also delete ast on primary soc.
3065 	 */
3066 	soc = peer->vdev->pdev->soc;
3067 
3068 	/* If V2 Peer map messages are enabled AST entry has to be
3069 	 * freed here
3070 	 */
3071 	if (is_wds) {
3072 		if (!dp_peer_ast_free_entry_by_mac(soc, peer, vdev_id,
3073 						   mac_addr)) {
3074 			dp_peer_unmap_ipa_evt(soc, peer_id, vdev_id, mac_addr);
3075 			dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
3076 			return;
3077 		}
3078 
3079 		dp_alert("AST entry not found with peer %pK peer_id %u peer_mac "QDF_MAC_ADDR_FMT" mac_addr "QDF_MAC_ADDR_FMT" vdev_id %u next_hop %u",
3080 			  peer, peer->peer_id,
3081 			  QDF_MAC_ADDR_REF(peer->mac_addr.raw),
3082 			  QDF_MAC_ADDR_REF(mac_addr), vdev_id,
3083 			  is_wds);
3084 
3085 		dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
3086 		return;
3087 	}
3088 
3089 	dp_peer_clean_wds_entries(soc, peer, free_wds_count);
3090 
3091 	dp_cfg_event_record_peer_map_unmap_evt(soc, DP_CFG_EVENT_PEER_UNMAP,
3092 					       peer, mac_addr, 0, peer_id,
3093 					       0, 0, vdev_id);
3094 	dp_info("peer_unmap_event (soc:%pK) peer_id %d peer %pK",
3095 		soc, peer_id, peer);
3096 
3097 	/* Clear entries in Qref LUT */
3098 	/* TODO: Check if this is to be called from
3099 	 * dp_peer_delete for MLO case if there is race between
3100 	 * new peer id assignment and still not having received
3101 	 * peer unmap for MLD peer with same peer id.
3102 	 */
3103 	dp_peer_rx_reo_shared_qaddr_delete(soc, peer);
3104 
3105 	vdev = peer->vdev;
3106 
3107 	/* only if peer is in STA mode and not tdls peer */
3108 	if (wlan_op_mode_sta == vdev->opmode && !peer->is_tdls_peer) {
3109 		bool peer_map = false;
3110 
3111 		dp_tx_ppeds_cfg_astidx_cache_mapping(soc, vdev, peer_map);
3112 	}
3113 
3114 	dp_peer_find_id_to_obj_remove(soc, peer_id);
3115 
3116 	if (soc->arch_ops.dp_partner_chips_unmap)
3117 		soc->arch_ops.dp_partner_chips_unmap(soc, peer_id);
3118 
3119 	peer->peer_id = HTT_INVALID_PEER;
3120 
3121 	/*
3122 	 *	 Reset ast flow mapping table
3123 	 */
3124 	if (!soc->ast_offload_support)
3125 		dp_peer_reset_flowq_map(peer);
3126 
3127 	if (soc->cdp_soc.ol_ops->peer_unmap_event) {
3128 		soc->cdp_soc.ol_ops->peer_unmap_event(soc->ctrl_psoc,
3129 				peer_id, vdev_id, mac_addr);
3130 	}
3131 
3132 	dp_update_vdev_stats_on_peer_unmap(vdev, peer);
3133 
3134 	dp_peer_update_state(soc, peer, DP_PEER_STATE_INACTIVE);
3135 	dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
3136 	/*
3137 	 * Remove a reference to the peer.
3138 	 * If there are no more references, delete the peer object.
3139 	 */
3140 	dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
3141 }
3142 
3143 #if defined(WLAN_FEATURE_11BE_MLO) && defined(DP_MLO_LINK_STATS_SUPPORT)
3144 enum dp_bands dp_freq_to_band(qdf_freq_t freq)
3145 {
3146 	if (REG_IS_24GHZ_CH_FREQ(freq))
3147 		return DP_BAND_2GHZ;
3148 	else if (REG_IS_5GHZ_FREQ(freq) || REG_IS_49GHZ_FREQ(freq))
3149 		return DP_BAND_5GHZ;
3150 	else if (REG_IS_6GHZ_FREQ(freq))
3151 		return DP_BAND_6GHZ;
3152 	return DP_BAND_INVALID;
3153 }
3154 
3155 void dp_map_link_id_band(struct dp_peer *peer)
3156 {
3157 	struct dp_txrx_peer *txrx_peer = NULL;
3158 	enum dp_bands band;
3159 
3160 	txrx_peer = dp_get_txrx_peer(peer);
3161 	if (txrx_peer) {
3162 		band = dp_freq_to_band(peer->freq);
3163 		txrx_peer->band[peer->link_id + 1] = band;
3164 		dp_info("Band(Freq: %u): %u mapped to Link ID: %u",
3165 			peer->freq, band, peer->link_id);
3166 	} else {
3167 		dp_info("txrx_peer NULL for peer: " QDF_MAC_ADDR_FMT,
3168 			QDF_MAC_ADDR_REF(peer->mac_addr.raw));
3169 	}
3170 }
3171 
3172 QDF_STATUS
3173 dp_rx_peer_ext_evt(struct dp_soc *soc, struct dp_peer_ext_evt_info *info)
3174 {
3175 	struct dp_peer *peer = NULL;
3176 	struct cdp_peer_info peer_info = { 0 };
3177 
3178 	QDF_ASSERT(info->peer_id <= soc->max_peer_id);
3179 
3180 	DP_PEER_INFO_PARAMS_INIT(&peer_info, info->vdev_id, info->peer_mac_addr,
3181 				 false, CDP_LINK_PEER_TYPE);
3182 	peer = dp_peer_hash_find_wrapper(soc, &peer_info, DP_MOD_ID_CONFIG);
3183 
3184 	if (!peer) {
3185 		dp_err("peer NULL, id %u, MAC " QDF_MAC_ADDR_FMT ", vdev_id %u",
3186 		       info->peer_id, QDF_MAC_ADDR_REF(info->peer_mac_addr),
3187 		       info->vdev_id);
3188 
3189 		return QDF_STATUS_E_FAILURE;
3190 	}
3191 
3192 	peer->link_id = info->link_id;
3193 	peer->link_id_valid = info->link_id_valid;
3194 
3195 	if (peer->freq)
3196 		dp_map_link_id_band(peer);
3197 
3198 	dp_peer_unref_delete(peer, DP_MOD_ID_CONFIG);
3199 
3200 	return QDF_STATUS_SUCCESS;
3201 }
3202 #endif
3203 #ifdef WLAN_FEATURE_11BE_MLO
3204 void dp_rx_mlo_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id)
3205 {
3206 	uint16_t ml_peer_id = dp_gen_ml_peer_id(soc, peer_id);
3207 	uint8_t mac_addr[QDF_MAC_ADDR_SIZE] = {0};
3208 	uint8_t vdev_id = DP_VDEV_ALL;
3209 	uint8_t is_wds = 0;
3210 
3211 	dp_cfg_event_record_peer_map_unmap_evt(soc, DP_CFG_EVENT_MLO_PEER_UNMAP,
3212 					       NULL, mac_addr, 0, peer_id,
3213 					       0, 0, vdev_id);
3214 	dp_info("MLO peer_unmap_event (soc:%pK) peer_id %d",
3215 		soc, peer_id);
3216 	DP_STATS_INC(soc, t2h_msg_stats.ml_peer_unmap, 1);
3217 
3218 	dp_rx_peer_unmap_handler(soc, ml_peer_id, vdev_id,
3219 				 mac_addr, is_wds,
3220 				 DP_PEER_WDS_COUNT_INVALID);
3221 }
3222 #endif
3223 
3224 #ifndef AST_OFFLOAD_ENABLE
3225 void
3226 dp_peer_find_detach(struct dp_soc *soc)
3227 {
3228 	dp_soc_wds_detach(soc);
3229 	dp_peer_find_map_detach(soc);
3230 	dp_peer_find_hash_detach(soc);
3231 	dp_peer_ast_hash_detach(soc);
3232 	dp_peer_ast_table_detach(soc);
3233 	dp_peer_mec_hash_detach(soc);
3234 }
3235 #else
3236 void
3237 dp_peer_find_detach(struct dp_soc *soc)
3238 {
3239 	dp_peer_find_map_detach(soc);
3240 	dp_peer_find_hash_detach(soc);
3241 }
3242 #endif
3243 
3244 void dp_peer_rx_init(struct dp_pdev *pdev, struct dp_peer *peer)
3245 {
3246 	dp_peer_rx_tid_setup(peer);
3247 
3248 	peer->active_ba_session_cnt = 0;
3249 	peer->hw_buffer_size = 0;
3250 	peer->kill_256_sessions = 0;
3251 
3252 	/*
3253 	 * Set security defaults: no PN check, no security. The target may
3254 	 * send a HTT SEC_IND message to overwrite these defaults.
3255 	 */
3256 	if (peer->txrx_peer)
3257 		peer->txrx_peer->security[dp_sec_ucast].sec_type =
3258 			peer->txrx_peer->security[dp_sec_mcast].sec_type =
3259 				cdp_sec_type_none;
3260 }
3261 
3262 #ifdef WLAN_FEATURE_11BE_MLO
3263 static void dp_peer_rx_init_reorder_queue(struct dp_pdev *pdev,
3264 					  struct dp_peer *peer)
3265 {
3266 	struct dp_soc *soc = pdev->soc;
3267 	struct dp_peer *mld_peer = DP_GET_MLD_PEER_FROM_PEER(peer);
3268 	struct dp_rx_tid *rx_tid = NULL;
3269 	uint32_t ba_window_size, tid;
3270 	QDF_STATUS status;
3271 
3272 	if (dp_get_peer_vdev_roaming_in_progress(peer))
3273 		return;
3274 
3275 	tid = DP_NON_QOS_TID;
3276 	rx_tid = &mld_peer->rx_tid[tid];
3277 	ba_window_size = rx_tid->ba_status == DP_RX_BA_ACTIVE ?
3278 					rx_tid->ba_win_size : 1;
3279 	status = dp_peer_rx_reorder_queue_setup(soc, peer, BIT(tid), ba_window_size);
3280 	/* Do not return on failure, continue for other tids. */
3281 	dp_info("peer %pK " QDF_MAC_ADDR_FMT " type %d setup tid %d ba_win_size %d%s",
3282 		peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw),
3283 		peer->peer_type, tid, ba_window_size,
3284 		QDF_IS_STATUS_SUCCESS(status) ? " SUCCESS" : " FAILED");
3285 
3286 	for (tid = 0; tid < DP_MAX_TIDS - 1; tid++) {
3287 		rx_tid = &mld_peer->rx_tid[tid];
3288 		ba_window_size = rx_tid->ba_status == DP_RX_BA_ACTIVE ?
3289 						rx_tid->ba_win_size : 1;
3290 		status = dp_peer_rx_reorder_queue_setup(soc, peer, BIT(tid),
3291 							ba_window_size);
3292 		/* Do not return on failure, continue for other tids. */
3293 		dp_info("peer %pK " QDF_MAC_ADDR_FMT " type %d setup tid %d ba_win_size %d%s",
3294 			peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw),
3295 			peer->peer_type, tid, ba_window_size,
3296 			QDF_IS_STATUS_SUCCESS(status) ? " SUCCESS" : " FAILED");
3297 	}
3298 }
3299 
3300 void dp_peer_rx_init_wrapper(struct dp_pdev *pdev, struct dp_peer *peer,
3301 			     struct cdp_peer_setup_info *setup_info)
3302 {
3303 	if (setup_info && !setup_info->is_first_link)
3304 		dp_peer_rx_init_reorder_queue(pdev, peer);
3305 	else
3306 		dp_peer_rx_init(pdev, peer);
3307 }
3308 #else
3309 void dp_peer_rx_init_wrapper(struct dp_pdev *pdev, struct dp_peer *peer,
3310 			     struct cdp_peer_setup_info *setup_info)
3311 {
3312 	dp_peer_rx_init(pdev, peer);
3313 }
3314 #endif
3315 
3316 void dp_peer_cleanup(struct dp_vdev *vdev, struct dp_peer *peer)
3317 {
3318 	enum wlan_op_mode vdev_opmode;
3319 	uint8_t vdev_mac_addr[QDF_MAC_ADDR_SIZE];
3320 	struct dp_pdev *pdev = vdev->pdev;
3321 	struct dp_soc *soc = pdev->soc;
3322 
3323 	/* save vdev related member in case vdev freed */
3324 	vdev_opmode = vdev->opmode;
3325 
3326 	if (!IS_MLO_DP_MLD_PEER(peer))
3327 		dp_monitor_peer_tx_cleanup(vdev, peer);
3328 
3329 	if (vdev_opmode != wlan_op_mode_monitor)
3330 	/* cleanup the Rx reorder queues for this peer */
3331 		dp_peer_rx_cleanup(vdev, peer);
3332 
3333 	dp_peer_rx_tids_destroy(peer);
3334 
3335 	if (IS_MLO_DP_LINK_PEER(peer))
3336 		dp_link_peer_del_mld_peer(peer);
3337 	if (IS_MLO_DP_MLD_PEER(peer))
3338 		dp_mld_peer_deinit_link_peers_info(peer);
3339 
3340 	qdf_mem_copy(vdev_mac_addr, vdev->mac_addr.raw,
3341 		     QDF_MAC_ADDR_SIZE);
3342 
3343 	if (soc->cdp_soc.ol_ops->peer_unref_delete)
3344 		soc->cdp_soc.ol_ops->peer_unref_delete(
3345 				soc->ctrl_psoc,
3346 				vdev->pdev->pdev_id,
3347 				peer->mac_addr.raw, vdev_mac_addr,
3348 				vdev_opmode);
3349 }
3350 
3351 QDF_STATUS
3352 dp_set_key_sec_type_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id,
3353 			  uint8_t *peer_mac, enum cdp_sec_type sec_type,
3354 			  bool is_unicast)
3355 {
3356 	struct dp_peer *peer =
3357 			dp_peer_get_tgt_peer_hash_find((struct dp_soc *)soc,
3358 						       peer_mac, 0, vdev_id,
3359 						       DP_MOD_ID_CDP);
3360 	int sec_index;
3361 
3362 	if (!peer) {
3363 		dp_peer_debug("%pK: Peer is NULL!\n", soc);
3364 		return QDF_STATUS_E_FAILURE;
3365 	}
3366 
3367 	if (!peer->txrx_peer) {
3368 		dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3369 		dp_peer_debug("%pK: txrx peer is NULL!\n", soc);
3370 		return QDF_STATUS_E_FAILURE;
3371 	}
3372 
3373 	dp_peer_info("%pK: key sec spec for peer %pK " QDF_MAC_ADDR_FMT ": %s key of type %d",
3374 		     soc, peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw),
3375 		     is_unicast ? "ucast" : "mcast", sec_type);
3376 
3377 	sec_index = is_unicast ? dp_sec_ucast : dp_sec_mcast;
3378 	peer->txrx_peer->security[sec_index].sec_type = sec_type;
3379 
3380 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3381 
3382 	return QDF_STATUS_SUCCESS;
3383 }
3384 
3385 void
3386 dp_rx_sec_ind_handler(struct dp_soc *soc, uint16_t peer_id,
3387 		      enum cdp_sec_type sec_type, int is_unicast,
3388 		      u_int32_t *michael_key,
3389 		      u_int32_t *rx_pn)
3390 {
3391 	struct dp_peer *peer;
3392 	struct dp_txrx_peer *txrx_peer;
3393 	int sec_index;
3394 
3395 	peer = dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_HTT);
3396 	if (!peer) {
3397 		dp_peer_err("Couldn't find peer from ID %d - skipping security inits",
3398 			    peer_id);
3399 		return;
3400 	}
3401 	txrx_peer = dp_get_txrx_peer(peer);
3402 	if (!txrx_peer) {
3403 		dp_peer_err("Couldn't find txrx peer from ID %d - skipping security inits",
3404 			    peer_id);
3405 		return;
3406 	}
3407 
3408 	dp_peer_info("%pK: sec spec for peer %pK " QDF_MAC_ADDR_FMT ": %s key of type %d",
3409 		     soc, peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw),
3410 			  is_unicast ? "ucast" : "mcast", sec_type);
3411 	sec_index = is_unicast ? dp_sec_ucast : dp_sec_mcast;
3412 
3413 	peer->txrx_peer->security[sec_index].sec_type = sec_type;
3414 #ifdef notyet /* TODO: See if this is required for defrag support */
3415 	/* michael key only valid for TKIP, but for simplicity,
3416 	 * copy it anyway
3417 	 */
3418 	qdf_mem_copy(
3419 		&peer->txrx_peer->security[sec_index].michael_key[0],
3420 		michael_key,
3421 		sizeof(peer->txrx_peer->security[sec_index].michael_key));
3422 #ifdef BIG_ENDIAN_HOST
3423 	OL_IF_SWAPBO(peer->txrx_peer->security[sec_index].michael_key[0],
3424 		     sizeof(peer->txrx_peer->security[sec_index].michael_key));
3425 #endif /* BIG_ENDIAN_HOST */
3426 #endif
3427 
3428 #ifdef notyet /* TODO: Check if this is required for wifi3.0 */
3429 	if (sec_type != cdp_sec_type_wapi) {
3430 		qdf_mem_zero(peer->tids_last_pn_valid, _EXT_TIDS);
3431 	} else {
3432 		for (i = 0; i < DP_MAX_TIDS; i++) {
3433 			/*
3434 			 * Setting PN valid bit for WAPI sec_type,
3435 			 * since WAPI PN has to be started with predefined value
3436 			 */
3437 			peer->tids_last_pn_valid[i] = 1;
3438 			qdf_mem_copy(
3439 				(u_int8_t *) &peer->tids_last_pn[i],
3440 				(u_int8_t *) rx_pn, sizeof(union htt_rx_pn_t));
3441 			peer->tids_last_pn[i].pn128[1] =
3442 				qdf_cpu_to_le64(peer->tids_last_pn[i].pn128[1]);
3443 			peer->tids_last_pn[i].pn128[0] =
3444 				qdf_cpu_to_le64(peer->tids_last_pn[i].pn128[0]);
3445 		}
3446 	}
3447 #endif
3448 	/* TODO: Update HW TID queue with PN check parameters (pn type for
3449 	 * all security types and last pn for WAPI) once REO command API
3450 	 * is available
3451 	 */
3452 
3453 	dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
3454 }
3455 
3456 #ifdef QCA_PEER_EXT_STATS
3457 QDF_STATUS dp_peer_delay_stats_ctx_alloc(struct dp_soc *soc,
3458 					 struct dp_txrx_peer *txrx_peer)
3459 {
3460 	uint8_t tid, ctx_id;
3461 
3462 	if (!soc || !txrx_peer) {
3463 		dp_warn("Null soc%pK or peer%pK", soc, txrx_peer);
3464 		return QDF_STATUS_E_INVAL;
3465 	}
3466 
3467 	if (!wlan_cfg_is_peer_ext_stats_enabled(soc->wlan_cfg_ctx))
3468 		return QDF_STATUS_SUCCESS;
3469 
3470 	/*
3471 	 * Allocate memory for peer extended stats.
3472 	 */
3473 	txrx_peer->delay_stats =
3474 			qdf_mem_malloc(sizeof(struct dp_peer_delay_stats));
3475 	if (!txrx_peer->delay_stats) {
3476 		dp_err("Peer extended stats obj alloc failed!!");
3477 		return QDF_STATUS_E_NOMEM;
3478 	}
3479 
3480 	for (tid = 0; tid < CDP_MAX_DATA_TIDS; tid++) {
3481 		for (ctx_id = 0; ctx_id < CDP_MAX_TXRX_CTX; ctx_id++) {
3482 			struct cdp_delay_tx_stats *tx_delay =
3483 			&txrx_peer->delay_stats->delay_tid_stats[tid][ctx_id].tx_delay;
3484 			struct cdp_delay_rx_stats *rx_delay =
3485 			&txrx_peer->delay_stats->delay_tid_stats[tid][ctx_id].rx_delay;
3486 
3487 			dp_hist_init(&tx_delay->tx_swq_delay,
3488 				     CDP_HIST_TYPE_SW_ENQEUE_DELAY);
3489 			dp_hist_init(&tx_delay->hwtx_delay,
3490 				     CDP_HIST_TYPE_HW_COMP_DELAY);
3491 			dp_hist_init(&rx_delay->to_stack_delay,
3492 				     CDP_HIST_TYPE_REAP_STACK);
3493 		}
3494 	}
3495 
3496 	return QDF_STATUS_SUCCESS;
3497 }
3498 
3499 void dp_peer_delay_stats_ctx_dealloc(struct dp_soc *soc,
3500 				     struct dp_txrx_peer *txrx_peer)
3501 {
3502 	if (!txrx_peer) {
3503 		dp_warn("peer_ext dealloc failed due to NULL peer object");
3504 		return;
3505 	}
3506 
3507 	if (!wlan_cfg_is_peer_ext_stats_enabled(soc->wlan_cfg_ctx))
3508 		return;
3509 
3510 	if (!txrx_peer->delay_stats)
3511 		return;
3512 
3513 	qdf_mem_free(txrx_peer->delay_stats);
3514 	txrx_peer->delay_stats = NULL;
3515 }
3516 
3517 void dp_peer_delay_stats_ctx_clr(struct dp_txrx_peer *txrx_peer)
3518 {
3519 	if (txrx_peer->delay_stats)
3520 		qdf_mem_zero(txrx_peer->delay_stats,
3521 			     sizeof(struct dp_peer_delay_stats));
3522 }
3523 #endif
3524 
3525 #ifdef WLAN_PEER_JITTER
3526 QDF_STATUS dp_peer_jitter_stats_ctx_alloc(struct dp_pdev *pdev,
3527 					  struct dp_txrx_peer *txrx_peer)
3528 {
3529 	if (!pdev || !txrx_peer) {
3530 		dp_warn("Null pdev or peer");
3531 		return QDF_STATUS_E_INVAL;
3532 	}
3533 
3534 	if (!wlan_cfg_is_peer_jitter_stats_enabled(pdev->soc->wlan_cfg_ctx))
3535 		return QDF_STATUS_SUCCESS;
3536 
3537 	if (wlan_cfg_get_dp_pdev_nss_enabled(pdev->wlan_cfg_ctx)) {
3538 		/*
3539 		 * Allocate memory on per tid basis when nss is enabled
3540 		 */
3541 		txrx_peer->jitter_stats =
3542 			qdf_mem_malloc(sizeof(struct cdp_peer_tid_stats)
3543 					* DP_MAX_TIDS);
3544 	} else {
3545 		/*
3546 		 * Allocate memory on per tid per ring basis
3547 		 */
3548 		txrx_peer->jitter_stats =
3549 			qdf_mem_malloc(sizeof(struct cdp_peer_tid_stats)
3550 					* DP_MAX_TIDS * CDP_MAX_TXRX_CTX);
3551 	}
3552 
3553 	if (!txrx_peer->jitter_stats) {
3554 		dp_warn("Jitter stats obj alloc failed!!");
3555 		return QDF_STATUS_E_NOMEM;
3556 	}
3557 
3558 	return QDF_STATUS_SUCCESS;
3559 }
3560 
3561 void dp_peer_jitter_stats_ctx_dealloc(struct dp_pdev *pdev,
3562 				      struct dp_txrx_peer *txrx_peer)
3563 {
3564 	if (!pdev || !txrx_peer) {
3565 		dp_warn("Null pdev or peer");
3566 		return;
3567 	}
3568 
3569 	if (!wlan_cfg_is_peer_jitter_stats_enabled(pdev->soc->wlan_cfg_ctx))
3570 		return;
3571 
3572 	if (txrx_peer->jitter_stats) {
3573 		qdf_mem_free(txrx_peer->jitter_stats);
3574 		txrx_peer->jitter_stats = NULL;
3575 	}
3576 }
3577 
3578 void dp_peer_jitter_stats_ctx_clr(struct dp_txrx_peer *txrx_peer)
3579 {
3580 	struct cdp_peer_tid_stats *jitter_stats = NULL;
3581 
3582 	if (!txrx_peer) {
3583 		dp_warn("Null peer");
3584 		return;
3585 	}
3586 
3587 	if (!wlan_cfg_is_peer_jitter_stats_enabled(txrx_peer->
3588 						   vdev->
3589 						   pdev->soc->wlan_cfg_ctx))
3590 		return;
3591 
3592 	jitter_stats = txrx_peer->jitter_stats;
3593 	if (!jitter_stats)
3594 		return;
3595 
3596 	if (wlan_cfg_get_dp_pdev_nss_enabled(txrx_peer->
3597 					     vdev->pdev->wlan_cfg_ctx))
3598 		qdf_mem_zero(jitter_stats,
3599 			     sizeof(struct cdp_peer_tid_stats) *
3600 			     DP_MAX_TIDS);
3601 
3602 	else
3603 		qdf_mem_zero(jitter_stats,
3604 			     sizeof(struct cdp_peer_tid_stats) *
3605 			     DP_MAX_TIDS * CDP_MAX_TXRX_CTX);
3606 
3607 }
3608 #endif
3609 
3610 #ifdef DP_PEER_EXTENDED_API
3611 /**
3612  * dp_peer_set_bw() - Set bandwidth and mpdu retry count threshold for peer
3613  * @soc: DP soc handle
3614  * @txrx_peer: Core txrx_peer handle
3615  * @set_bw: enum of bandwidth to be set for this peer connection
3616  *
3617  * Return: None
3618  */
3619 static void dp_peer_set_bw(struct dp_soc *soc, struct dp_txrx_peer *txrx_peer,
3620 			   enum cdp_peer_bw set_bw)
3621 {
3622 	if (!txrx_peer)
3623 		return;
3624 
3625 	txrx_peer->bw = set_bw;
3626 
3627 	switch (set_bw) {
3628 	case CDP_160_MHZ:
3629 	case CDP_320_MHZ:
3630 		txrx_peer->mpdu_retry_threshold =
3631 				soc->wlan_cfg_ctx->mpdu_retry_threshold_2;
3632 		break;
3633 	case CDP_20_MHZ:
3634 	case CDP_40_MHZ:
3635 	case CDP_80_MHZ:
3636 	default:
3637 		txrx_peer->mpdu_retry_threshold =
3638 				soc->wlan_cfg_ctx->mpdu_retry_threshold_1;
3639 		break;
3640 	}
3641 
3642 	dp_info("Peer id: %u: BW: %u, mpdu retry threshold: %u",
3643 		txrx_peer->peer_id, txrx_peer->bw,
3644 		txrx_peer->mpdu_retry_threshold);
3645 }
3646 
3647 #ifdef WLAN_FEATURE_11BE_MLO
3648 QDF_STATUS dp_register_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
3649 			    struct ol_txrx_desc_type *sta_desc)
3650 {
3651 	struct dp_peer *peer;
3652 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
3653 
3654 	peer = dp_peer_find_hash_find(soc, sta_desc->peer_addr.bytes,
3655 				      0, DP_VDEV_ALL, DP_MOD_ID_CDP);
3656 
3657 	if (!peer)
3658 		return QDF_STATUS_E_FAULT;
3659 
3660 	qdf_spin_lock_bh(&peer->peer_info_lock);
3661 	peer->state = OL_TXRX_PEER_STATE_CONN;
3662 	qdf_spin_unlock_bh(&peer->peer_info_lock);
3663 
3664 	dp_peer_set_bw(soc, peer->txrx_peer, sta_desc->bw);
3665 
3666 	dp_rx_flush_rx_cached(peer, false);
3667 
3668 	if (IS_MLO_DP_LINK_PEER(peer) && peer->first_link) {
3669 		dp_peer_info("register for mld peer" QDF_MAC_ADDR_FMT,
3670 			     QDF_MAC_ADDR_REF(peer->mld_peer->mac_addr.raw));
3671 		qdf_spin_lock_bh(&peer->mld_peer->peer_info_lock);
3672 		peer->mld_peer->state = peer->state;
3673 		qdf_spin_unlock_bh(&peer->mld_peer->peer_info_lock);
3674 		dp_rx_flush_rx_cached(peer->mld_peer, false);
3675 	}
3676 
3677 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3678 
3679 	return QDF_STATUS_SUCCESS;
3680 }
3681 
3682 QDF_STATUS dp_peer_state_update(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac,
3683 				enum ol_txrx_peer_state state)
3684 {
3685 	struct dp_peer *peer;
3686 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
3687 
3688 	peer =  dp_peer_find_hash_find(soc, peer_mac, 0, DP_VDEV_ALL,
3689 				       DP_MOD_ID_CDP);
3690 	if (!peer) {
3691 		dp_peer_err("%pK: Failed to find peer[" QDF_MAC_ADDR_FMT "]",
3692 			    soc, QDF_MAC_ADDR_REF(peer_mac));
3693 		return QDF_STATUS_E_FAILURE;
3694 	}
3695 	peer->state = state;
3696 	peer->authorize = (state == OL_TXRX_PEER_STATE_AUTH) ? 1 : 0;
3697 
3698 	if (peer->txrx_peer)
3699 		peer->txrx_peer->authorize = peer->authorize;
3700 
3701 	dp_peer_info("peer %pK MAC " QDF_MAC_ADDR_FMT " state %d",
3702 		     peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw),
3703 		     peer->state);
3704 
3705 	if (IS_MLO_DP_LINK_PEER(peer) && peer->first_link) {
3706 		peer->mld_peer->state = peer->state;
3707 		peer->mld_peer->txrx_peer->authorize = peer->authorize;
3708 		dp_peer_info("mld peer %pK MAC " QDF_MAC_ADDR_FMT " state %d",
3709 			     peer->mld_peer,
3710 			     QDF_MAC_ADDR_REF(peer->mld_peer->mac_addr.raw),
3711 			     peer->mld_peer->state);
3712 	}
3713 
3714 	/* ref_cnt is incremented inside dp_peer_find_hash_find().
3715 	 * Decrement it here.
3716 	 */
3717 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3718 
3719 	return QDF_STATUS_SUCCESS;
3720 }
3721 #else
3722 QDF_STATUS dp_register_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
3723 			    struct ol_txrx_desc_type *sta_desc)
3724 {
3725 	struct dp_peer *peer;
3726 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
3727 
3728 	peer = dp_peer_find_hash_find(soc, sta_desc->peer_addr.bytes,
3729 				      0, DP_VDEV_ALL, DP_MOD_ID_CDP);
3730 
3731 	if (!peer)
3732 		return QDF_STATUS_E_FAULT;
3733 
3734 	qdf_spin_lock_bh(&peer->peer_info_lock);
3735 	peer->state = OL_TXRX_PEER_STATE_CONN;
3736 	qdf_spin_unlock_bh(&peer->peer_info_lock);
3737 
3738 	dp_peer_set_bw(soc, peer->txrx_peer, sta_desc->bw);
3739 
3740 	dp_rx_flush_rx_cached(peer, false);
3741 
3742 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3743 
3744 	return QDF_STATUS_SUCCESS;
3745 }
3746 
3747 QDF_STATUS dp_peer_state_update(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac,
3748 				enum ol_txrx_peer_state state)
3749 {
3750 	struct dp_peer *peer;
3751 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
3752 
3753 	peer =  dp_peer_find_hash_find(soc, peer_mac, 0, DP_VDEV_ALL,
3754 				       DP_MOD_ID_CDP);
3755 	if (!peer) {
3756 		dp_peer_err("%pK: Failed to find peer for: [" QDF_MAC_ADDR_FMT "]",
3757 			    soc, QDF_MAC_ADDR_REF(peer_mac));
3758 		return QDF_STATUS_E_FAILURE;
3759 	}
3760 	peer->state = state;
3761 	peer->authorize = (state == OL_TXRX_PEER_STATE_AUTH) ? 1 : 0;
3762 
3763 	if (peer->txrx_peer)
3764 		peer->txrx_peer->authorize = peer->authorize;
3765 
3766 	dp_info("peer %pK state %d", peer, peer->state);
3767 	/* ref_cnt is incremented inside dp_peer_find_hash_find().
3768 	 * Decrement it here.
3769 	 */
3770 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3771 
3772 	return QDF_STATUS_SUCCESS;
3773 }
3774 #endif
3775 
3776 QDF_STATUS
3777 dp_clear_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
3778 	      struct qdf_mac_addr peer_addr)
3779 {
3780 	struct dp_peer *peer;
3781 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
3782 
3783 	peer = dp_peer_find_hash_find(soc, peer_addr.bytes,
3784 				      0, DP_VDEV_ALL, DP_MOD_ID_CDP);
3785 
3786 	if (!peer)
3787 		return QDF_STATUS_E_FAULT;
3788 	if (!peer->valid) {
3789 		dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3790 		return QDF_STATUS_E_FAULT;
3791 	}
3792 
3793 	dp_clear_peer_internal(soc, peer);
3794 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3795 	return QDF_STATUS_SUCCESS;
3796 }
3797 
3798 QDF_STATUS dp_get_vdevid(struct cdp_soc_t *soc_hdl, uint8_t *peer_mac,
3799 			 uint8_t *vdev_id)
3800 {
3801 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
3802 	struct dp_peer *peer =
3803 		dp_peer_find_hash_find(soc, peer_mac, 0, DP_VDEV_ALL,
3804 				       DP_MOD_ID_CDP);
3805 
3806 	if (!peer)
3807 		return QDF_STATUS_E_FAILURE;
3808 
3809 	dp_info("peer %pK vdev %pK vdev id %d",
3810 		peer, peer->vdev, peer->vdev->vdev_id);
3811 	*vdev_id = peer->vdev->vdev_id;
3812 	/* ref_cnt is incremented inside dp_peer_find_hash_find().
3813 	 * Decrement it here.
3814 	 */
3815 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3816 
3817 	return QDF_STATUS_SUCCESS;
3818 }
3819 
3820 struct cdp_vdev *
3821 dp_get_vdev_by_peer_addr(struct cdp_pdev *pdev_handle,
3822 			 struct qdf_mac_addr peer_addr)
3823 {
3824 	struct dp_pdev *pdev = (struct dp_pdev *)pdev_handle;
3825 	struct dp_peer *peer = NULL;
3826 	struct cdp_vdev *vdev = NULL;
3827 
3828 	if (!pdev) {
3829 		dp_peer_info("PDEV not found for peer_addr: " QDF_MAC_ADDR_FMT,
3830 			     QDF_MAC_ADDR_REF(peer_addr.bytes));
3831 		return NULL;
3832 	}
3833 
3834 	peer = dp_peer_find_hash_find(pdev->soc, peer_addr.bytes, 0,
3835 				      DP_VDEV_ALL, DP_MOD_ID_CDP);
3836 	if (!peer) {
3837 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
3838 			  "PDEV not found for peer_addr: "QDF_MAC_ADDR_FMT,
3839 			  QDF_MAC_ADDR_REF(peer_addr.bytes));
3840 		return NULL;
3841 	}
3842 
3843 	vdev = (struct cdp_vdev *)peer->vdev;
3844 
3845 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3846 	return vdev;
3847 }
3848 
3849 struct cdp_vdev *dp_get_vdev_for_peer(void *peer_handle)
3850 {
3851 	struct dp_peer *peer = peer_handle;
3852 
3853 	DP_TRACE(DEBUG, "peer %pK vdev %pK", peer, peer->vdev);
3854 	return (struct cdp_vdev *)peer->vdev;
3855 }
3856 
3857 uint8_t *dp_peer_get_peer_mac_addr(void *peer_handle)
3858 {
3859 	struct dp_peer *peer = peer_handle;
3860 	uint8_t *mac;
3861 
3862 	mac = peer->mac_addr.raw;
3863 	dp_info("peer %pK mac 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
3864 		peer, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
3865 	return peer->mac_addr.raw;
3866 }
3867 
3868 int dp_get_peer_state(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
3869 		      uint8_t *peer_mac, bool slowpath)
3870 {
3871 	enum ol_txrx_peer_state peer_state;
3872 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
3873 	struct cdp_peer_info peer_info = { 0 };
3874 	struct dp_peer *peer;
3875 	struct dp_peer *tgt_peer;
3876 
3877 	DP_PEER_INFO_PARAMS_INIT(&peer_info, vdev_id, peer_mac,
3878 				 false, CDP_WILD_PEER_TYPE);
3879 
3880 	peer =  dp_peer_hash_find_wrapper(soc, &peer_info, DP_MOD_ID_CDP);
3881 
3882 	if (!peer)
3883 		return OL_TXRX_PEER_STATE_INVALID;
3884 
3885 	tgt_peer = dp_get_tgt_peer_from_peer(peer);
3886 	peer_state = tgt_peer->state;
3887 
3888 	if (slowpath)
3889 		dp_peer_info("peer %pK tgt_peer: %pK peer MAC "
3890 			    QDF_MAC_ADDR_FMT " tgt peer MAC "
3891 			    QDF_MAC_ADDR_FMT " tgt peer state %d",
3892 			    peer, tgt_peer, QDF_MAC_ADDR_REF(peer->mac_addr.raw),
3893 			    QDF_MAC_ADDR_REF(tgt_peer->mac_addr.raw),
3894 			    tgt_peer->state);
3895 
3896 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3897 
3898 	return peer_state;
3899 }
3900 
3901 void dp_local_peer_id_pool_init(struct dp_pdev *pdev)
3902 {
3903 	int i;
3904 
3905 	/* point the freelist to the first ID */
3906 	pdev->local_peer_ids.freelist = 0;
3907 
3908 	/* link each ID to the next one */
3909 	for (i = 0; i < OL_TXRX_NUM_LOCAL_PEER_IDS; i++) {
3910 		pdev->local_peer_ids.pool[i] = i + 1;
3911 		pdev->local_peer_ids.map[i] = NULL;
3912 	}
3913 
3914 	/* link the last ID to itself, to mark the end of the list */
3915 	i = OL_TXRX_NUM_LOCAL_PEER_IDS;
3916 	pdev->local_peer_ids.pool[i] = i;
3917 
3918 	qdf_spinlock_create(&pdev->local_peer_ids.lock);
3919 	dp_info("Peer pool init");
3920 }
3921 
3922 void dp_local_peer_id_alloc(struct dp_pdev *pdev, struct dp_peer *peer)
3923 {
3924 	int i;
3925 
3926 	qdf_spin_lock_bh(&pdev->local_peer_ids.lock);
3927 	i = pdev->local_peer_ids.freelist;
3928 	if (pdev->local_peer_ids.pool[i] == i) {
3929 		/* the list is empty, except for the list-end marker */
3930 		peer->local_id = OL_TXRX_INVALID_LOCAL_PEER_ID;
3931 	} else {
3932 		/* take the head ID and advance the freelist */
3933 		peer->local_id = i;
3934 		pdev->local_peer_ids.freelist = pdev->local_peer_ids.pool[i];
3935 		pdev->local_peer_ids.map[i] = peer;
3936 	}
3937 	qdf_spin_unlock_bh(&pdev->local_peer_ids.lock);
3938 	dp_info("peer %pK, local id %d", peer, peer->local_id);
3939 }
3940 
3941 void dp_local_peer_id_free(struct dp_pdev *pdev, struct dp_peer *peer)
3942 {
3943 	int i = peer->local_id;
3944 	if ((i == OL_TXRX_INVALID_LOCAL_PEER_ID) ||
3945 	    (i >= OL_TXRX_NUM_LOCAL_PEER_IDS)) {
3946 		return;
3947 	}
3948 
3949 	/* put this ID on the head of the freelist */
3950 	qdf_spin_lock_bh(&pdev->local_peer_ids.lock);
3951 	pdev->local_peer_ids.pool[i] = pdev->local_peer_ids.freelist;
3952 	pdev->local_peer_ids.freelist = i;
3953 	pdev->local_peer_ids.map[i] = NULL;
3954 	qdf_spin_unlock_bh(&pdev->local_peer_ids.lock);
3955 }
3956 
3957 bool dp_find_peer_exist_on_vdev(struct cdp_soc_t *soc_hdl,
3958 				uint8_t vdev_id, uint8_t *peer_addr)
3959 {
3960 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
3961 	struct dp_peer *peer = NULL;
3962 
3963 	peer = dp_peer_find_hash_find(soc, peer_addr, 0, vdev_id,
3964 				      DP_MOD_ID_CDP);
3965 	if (!peer)
3966 		return false;
3967 
3968 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3969 
3970 	return true;
3971 }
3972 
3973 bool dp_find_peer_exist_on_other_vdev(struct cdp_soc_t *soc_hdl,
3974 				      uint8_t vdev_id, uint8_t *peer_addr,
3975 				      uint16_t max_bssid)
3976 {
3977 	int i;
3978 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
3979 	struct dp_peer *peer = NULL;
3980 
3981 	for (i = 0; i < max_bssid; i++) {
3982 		/* Need to check vdevs other than the vdev_id */
3983 		if (vdev_id == i)
3984 			continue;
3985 		peer = dp_peer_find_hash_find(soc, peer_addr, 0, i,
3986 					      DP_MOD_ID_CDP);
3987 		if (peer) {
3988 			dp_err("Duplicate peer "QDF_MAC_ADDR_FMT" already exist on vdev %d",
3989 			       QDF_MAC_ADDR_REF(peer_addr), i);
3990 			dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
3991 			return true;
3992 		}
3993 	}
3994 
3995 	return false;
3996 }
3997 
3998 void dp_set_peer_as_tdls_peer(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
3999 			      uint8_t *peer_mac, bool val)
4000 {
4001 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
4002 	struct dp_peer *peer = NULL;
4003 
4004 	peer = dp_peer_find_hash_find(soc, peer_mac, 0, vdev_id,
4005 				      DP_MOD_ID_CDP);
4006 	if (!peer) {
4007 		dp_err("Failed to find peer for:" QDF_MAC_ADDR_FMT,
4008 		       QDF_MAC_ADDR_REF(peer_mac));
4009 		return;
4010 	}
4011 
4012 	dp_info("Set tdls flag %d for peer:" QDF_MAC_ADDR_FMT,
4013 		val, QDF_MAC_ADDR_REF(peer_mac));
4014 	peer->is_tdls_peer = val;
4015 
4016 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
4017 }
4018 #endif
4019 
4020 bool dp_find_peer_exist(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
4021 			uint8_t *peer_addr)
4022 {
4023 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
4024 	struct dp_peer *peer = NULL;
4025 
4026 	peer = dp_peer_find_hash_find(soc, peer_addr, 0, DP_VDEV_ALL,
4027 				      DP_MOD_ID_CDP);
4028 	if (peer) {
4029 		dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
4030 		return true;
4031 	}
4032 
4033 	return false;
4034 }
4035 
4036 QDF_STATUS
4037 dp_set_michael_key(struct cdp_soc_t *soc,
4038 		   uint8_t vdev_id,
4039 		   uint8_t *peer_mac,
4040 		   bool is_unicast, uint32_t *key)
4041 {
4042 	uint8_t sec_index = is_unicast ? 1 : 0;
4043 	struct dp_peer *peer =
4044 			dp_peer_get_tgt_peer_hash_find((struct dp_soc *)soc,
4045 						       peer_mac, 0, vdev_id,
4046 						       DP_MOD_ID_CDP);
4047 
4048 	if (!peer) {
4049 		dp_peer_err("%pK: peer not found ", soc);
4050 		return QDF_STATUS_E_FAILURE;
4051 	}
4052 
4053 	qdf_mem_copy(&peer->txrx_peer->security[sec_index].michael_key[0],
4054 		     key, IEEE80211_WEP_MICLEN);
4055 
4056 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
4057 
4058 	return QDF_STATUS_SUCCESS;
4059 }
4060 
4061 
4062 struct dp_peer *dp_vdev_bss_peer_ref_n_get(struct dp_soc *soc,
4063 					   struct dp_vdev *vdev,
4064 					   enum dp_mod_id mod_id)
4065 {
4066 	struct dp_peer *peer = NULL;
4067 
4068 	qdf_spin_lock_bh(&vdev->peer_list_lock);
4069 	TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
4070 		if (peer->bss_peer)
4071 			break;
4072 	}
4073 
4074 	if (!peer) {
4075 		qdf_spin_unlock_bh(&vdev->peer_list_lock);
4076 		return NULL;
4077 	}
4078 
4079 	if (dp_peer_get_ref(soc, peer, mod_id) == QDF_STATUS_SUCCESS) {
4080 		qdf_spin_unlock_bh(&vdev->peer_list_lock);
4081 		return peer;
4082 	}
4083 
4084 	qdf_spin_unlock_bh(&vdev->peer_list_lock);
4085 	return peer;
4086 }
4087 
4088 struct dp_peer *dp_sta_vdev_self_peer_ref_n_get(struct dp_soc *soc,
4089 						struct dp_vdev *vdev,
4090 						enum dp_mod_id mod_id)
4091 {
4092 	struct dp_peer *peer;
4093 
4094 	if (vdev->opmode != wlan_op_mode_sta)
4095 		return NULL;
4096 
4097 	qdf_spin_lock_bh(&vdev->peer_list_lock);
4098 	TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
4099 		if (peer->sta_self_peer)
4100 			break;
4101 	}
4102 
4103 	if (!peer) {
4104 		qdf_spin_unlock_bh(&vdev->peer_list_lock);
4105 		return NULL;
4106 	}
4107 
4108 	if (dp_peer_get_ref(soc, peer, mod_id) == QDF_STATUS_SUCCESS) {
4109 		qdf_spin_unlock_bh(&vdev->peer_list_lock);
4110 		return peer;
4111 	}
4112 
4113 	qdf_spin_unlock_bh(&vdev->peer_list_lock);
4114 	return peer;
4115 }
4116 
4117 void dp_peer_flush_frags(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
4118 			 uint8_t *peer_mac)
4119 {
4120 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
4121 	struct dp_peer *peer = dp_peer_get_tgt_peer_hash_find(soc, peer_mac, 0,
4122 							      vdev_id,
4123 							      DP_MOD_ID_CDP);
4124 	struct dp_txrx_peer *txrx_peer;
4125 	uint8_t tid;
4126 	struct dp_rx_tid_defrag *defrag_rx_tid;
4127 
4128 	if (!peer)
4129 		return;
4130 
4131 	if (!peer->txrx_peer)
4132 		goto fail;
4133 
4134 	dp_info("Flushing fragments for peer " QDF_MAC_ADDR_FMT,
4135 		QDF_MAC_ADDR_REF(peer->mac_addr.raw));
4136 
4137 	txrx_peer = peer->txrx_peer;
4138 
4139 	for (tid = 0; tid < DP_MAX_TIDS; tid++) {
4140 		defrag_rx_tid = &txrx_peer->rx_tid[tid];
4141 
4142 		qdf_spin_lock_bh(&defrag_rx_tid->defrag_tid_lock);
4143 		dp_rx_defrag_waitlist_remove(txrx_peer, tid);
4144 		dp_rx_reorder_flush_frag(txrx_peer, tid);
4145 		qdf_spin_unlock_bh(&defrag_rx_tid->defrag_tid_lock);
4146 	}
4147 fail:
4148 	dp_peer_unref_delete(peer, DP_MOD_ID_CDP);
4149 }
4150 
4151 bool dp_peer_find_by_id_valid(struct dp_soc *soc, uint16_t peer_id)
4152 {
4153 	struct dp_peer *peer = dp_peer_get_ref_by_id(soc, peer_id,
4154 						     DP_MOD_ID_HTT);
4155 
4156 	if (peer) {
4157 		/*
4158 		 * Decrement the peer ref which is taken as part of
4159 		 * dp_peer_get_ref_by_id if PEER_LOCK_REF_PROTECT is enabled
4160 		 */
4161 		dp_peer_unref_delete(peer, DP_MOD_ID_HTT);
4162 
4163 		return true;
4164 	}
4165 
4166 	return false;
4167 }
4168 
4169 qdf_export_symbol(dp_peer_find_by_id_valid);
4170 
4171 #ifdef QCA_MULTIPASS_SUPPORT
4172 void dp_peer_multipass_list_remove(struct dp_peer *peer)
4173 {
4174 	struct dp_vdev *vdev = peer->vdev;
4175 	struct dp_txrx_peer *tpeer = NULL;
4176 	bool found = 0;
4177 
4178 	qdf_spin_lock_bh(&vdev->mpass_peer_mutex);
4179 	TAILQ_FOREACH(tpeer, &vdev->mpass_peer_list, mpass_peer_list_elem) {
4180 		if (tpeer == peer->txrx_peer) {
4181 			found = 1;
4182 			TAILQ_REMOVE(&vdev->mpass_peer_list, peer->txrx_peer,
4183 				     mpass_peer_list_elem);
4184 			break;
4185 		}
4186 	}
4187 
4188 	qdf_spin_unlock_bh(&vdev->mpass_peer_mutex);
4189 
4190 	if (found)
4191 		dp_peer_unref_delete(peer, DP_MOD_ID_TX_MULTIPASS);
4192 }
4193 
4194 /**
4195  * dp_peer_multipass_list_add() - add to new multipass list
4196  * @soc: soc handle
4197  * @peer_mac: mac address
4198  * @vdev_id: vdev id for peer
4199  * @vlan_id: vlan_id
4200  *
4201  * return: void
4202  */
4203 static void dp_peer_multipass_list_add(struct dp_soc *soc, uint8_t *peer_mac,
4204 				       uint8_t vdev_id, uint16_t vlan_id)
4205 {
4206 	struct dp_peer *peer =
4207 			dp_peer_get_tgt_peer_hash_find(soc, peer_mac, 0,
4208 						       vdev_id,
4209 						       DP_MOD_ID_TX_MULTIPASS);
4210 
4211 	if (qdf_unlikely(!peer)) {
4212 		qdf_err("NULL peer");
4213 		return;
4214 	}
4215 
4216 	if (qdf_unlikely(!peer->txrx_peer))
4217 		goto fail;
4218 
4219 	/* If peer already exists in vdev multipass list, do not add it.
4220 	 * This may happen if key install comes twice or re-key
4221 	 * happens for a peer.
4222 	 */
4223 	if (peer->txrx_peer->vlan_id) {
4224 		dp_debug("peer already added to vdev multipass list"
4225 			 "MAC: "QDF_MAC_ADDR_FMT" vlan: %d ",
4226 			 QDF_MAC_ADDR_REF(peer->mac_addr.raw),
4227 			 peer->txrx_peer->vlan_id);
4228 		goto fail;
4229 	}
4230 
4231 	/*
4232 	 * Ref_cnt is incremented inside dp_peer_find_hash_find().
4233 	 * Decrement it when element is deleted from the list.
4234 	 */
4235 	peer->txrx_peer->vlan_id = vlan_id;
4236 	qdf_spin_lock_bh(&peer->txrx_peer->vdev->mpass_peer_mutex);
4237 	TAILQ_INSERT_HEAD(&peer->txrx_peer->vdev->mpass_peer_list,
4238 			  peer->txrx_peer,
4239 			  mpass_peer_list_elem);
4240 	qdf_spin_unlock_bh(&peer->txrx_peer->vdev->mpass_peer_mutex);
4241 	return;
4242 
4243 fail:
4244 	dp_peer_unref_delete(peer, DP_MOD_ID_TX_MULTIPASS);
4245 }
4246 
4247 void dp_peer_set_vlan_id(struct cdp_soc_t *cdp_soc,
4248 			 uint8_t vdev_id, uint8_t *peer_mac,
4249 			 uint16_t vlan_id)
4250 {
4251 	struct dp_soc *soc = (struct dp_soc *)cdp_soc;
4252 	struct dp_vdev *vdev =
4253 		dp_vdev_get_ref_by_id((struct dp_soc *)soc, vdev_id,
4254 				      DP_MOD_ID_TX_MULTIPASS);
4255 
4256 	dp_info("vdev_id %d, vdev %pK, multipass_en %d, peer_mac " QDF_MAC_ADDR_FMT " vlan %d",
4257 		vdev_id, vdev, vdev ? vdev->multipass_en : 0,
4258 		QDF_MAC_ADDR_REF(peer_mac), vlan_id);
4259 	if (vdev && vdev->multipass_en) {
4260 		dp_peer_multipass_list_add(soc, peer_mac, vdev_id, vlan_id);
4261 		dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_TX_MULTIPASS);
4262 	}
4263 }
4264 #endif /* QCA_MULTIPASS_SUPPORT */
4265