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