xref: /wlan-driver/qca-wifi-host-cmn/dp/wifi3.0/dp_txrx_wds.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 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 #include "htt.h"
20*5113495bSYour Name #include "dp_peer.h"
21*5113495bSYour Name #include "hal_rx.h"
22*5113495bSYour Name #include "hal_api.h"
23*5113495bSYour Name #include "qdf_nbuf.h"
24*5113495bSYour Name #include "dp_types.h"
25*5113495bSYour Name #include "dp_internal.h"
26*5113495bSYour Name #include "dp_tx.h"
27*5113495bSYour Name #include "enet.h"
28*5113495bSYour Name #ifdef WIFI_MONITOR_SUPPORT
29*5113495bSYour Name #include "dp_mon.h"
30*5113495bSYour Name #endif
31*5113495bSYour Name #include "dp_txrx_wds.h"
32*5113495bSYour Name 
33*5113495bSYour Name /* Generic AST entry aging timer value */
34*5113495bSYour Name #define DP_AST_AGING_TIMER_DEFAULT_MS	5000
35*5113495bSYour Name #define DP_INVALID_AST_IDX 0xffff
36*5113495bSYour Name #define DP_INVALID_FLOW_PRIORITY 0xff
37*5113495bSYour Name #define DP_PEER_AST0_FLOW_MASK 0x4
38*5113495bSYour Name #define DP_PEER_AST1_FLOW_MASK 0x8
39*5113495bSYour Name #define DP_PEER_AST2_FLOW_MASK 0x1
40*5113495bSYour Name #define DP_PEER_AST3_FLOW_MASK 0x2
41*5113495bSYour Name #define DP_MAX_AST_INDEX_PER_PEER 4
42*5113495bSYour Name 
43*5113495bSYour Name #ifdef WLAN_FEATURE_MULTI_AST_DEL
44*5113495bSYour Name 
dp_peer_free_peer_ase_list(struct dp_soc * soc,struct peer_del_multi_wds_entries * wds_list)45*5113495bSYour Name void dp_peer_free_peer_ase_list(struct dp_soc *soc,
46*5113495bSYour Name 				struct peer_del_multi_wds_entries *wds_list)
47*5113495bSYour Name {
48*5113495bSYour Name 	struct peer_wds_entry_list *wds_entry, *tmp_entry;
49*5113495bSYour Name 
50*5113495bSYour Name 	TAILQ_FOREACH_SAFE(wds_entry, &wds_list->ase_list,
51*5113495bSYour Name 			   ase_list_elem, tmp_entry) {
52*5113495bSYour Name 		dp_peer_debug("type: %d mac_addr: " QDF_MAC_ADDR_FMT,
53*5113495bSYour Name 			      wds_entry->type,
54*5113495bSYour Name 			      QDF_MAC_ADDR_REF(wds_entry->dest_addr));
55*5113495bSYour Name 		TAILQ_REMOVE(&wds_list->ase_list, wds_entry, ase_list_elem);
56*5113495bSYour Name 		wds_list->num_entries--;
57*5113495bSYour Name 		qdf_mem_free(wds_entry);
58*5113495bSYour Name 	}
59*5113495bSYour Name }
60*5113495bSYour Name 
61*5113495bSYour Name static void
dp_pdev_build_peer_ase_list(struct dp_soc * soc,struct dp_peer * peer,void * arg)62*5113495bSYour Name dp_pdev_build_peer_ase_list(struct dp_soc *soc, struct dp_peer *peer,
63*5113495bSYour Name 			    void *arg)
64*5113495bSYour Name {
65*5113495bSYour Name 	struct dp_ast_entry *ase, *temp_ase;
66*5113495bSYour Name 	struct peer_del_multi_wds_entries *list = arg;
67*5113495bSYour Name 	struct peer_wds_entry_list *wds_entry;
68*5113495bSYour Name 
69*5113495bSYour Name 	if (!soc || !peer || !arg) {
70*5113495bSYour Name 		dp_peer_err("Invalid input");
71*5113495bSYour Name 		return;
72*5113495bSYour Name 	}
73*5113495bSYour Name 
74*5113495bSYour Name 	list->vdev_id = peer->vdev->vdev_id;
75*5113495bSYour Name 	DP_PEER_ITERATE_ASE_LIST(peer, ase, temp_ase) {
76*5113495bSYour Name 		if (ase->type != CDP_TXRX_AST_TYPE_WDS &&
77*5113495bSYour Name 		    ase->type != CDP_TXRX_AST_TYPE_DA)
78*5113495bSYour Name 			continue;
79*5113495bSYour Name 
80*5113495bSYour Name 		if (ase->is_active) {
81*5113495bSYour Name 			ase->is_active = false;
82*5113495bSYour Name 			continue;
83*5113495bSYour Name 		}
84*5113495bSYour Name 
85*5113495bSYour Name 		if (ase->delete_in_progress) {
86*5113495bSYour Name 			dp_info_rl("Del set addr:" QDF_MAC_ADDR_FMT " type:%d",
87*5113495bSYour Name 				   QDF_MAC_ADDR_REF(ase->mac_addr.raw),
88*5113495bSYour Name 				   ase->type);
89*5113495bSYour Name 			continue;
90*5113495bSYour Name 		}
91*5113495bSYour Name 
92*5113495bSYour Name 		if (ase->is_mapped)
93*5113495bSYour Name 			soc->ast_table[ase->ast_idx] = NULL;
94*5113495bSYour Name 
95*5113495bSYour Name 		if (!ase->next_hop) {
96*5113495bSYour Name 			dp_peer_unlink_ast_entry(soc, ase, peer);
97*5113495bSYour Name 			continue;
98*5113495bSYour Name 		}
99*5113495bSYour Name 
100*5113495bSYour Name 		wds_entry = (struct peer_wds_entry_list *)
101*5113495bSYour Name 			    qdf_mem_malloc(sizeof(*wds_entry));
102*5113495bSYour Name 		if (!wds_entry) {
103*5113495bSYour Name 			dp_peer_err("%pK: fail to allocate wds_entry", soc);
104*5113495bSYour Name 			dp_peer_free_peer_ase_list(soc, list);
105*5113495bSYour Name 			return;
106*5113495bSYour Name 		}
107*5113495bSYour Name 
108*5113495bSYour Name 		DP_STATS_INC(soc, ast.aged_out, 1);
109*5113495bSYour Name 		ase->delete_in_progress = true;
110*5113495bSYour Name 		wds_entry->dest_addr = ase->mac_addr.raw;
111*5113495bSYour Name 		wds_entry->type = ase->type;
112*5113495bSYour Name 
113*5113495bSYour Name 		if (dp_peer_state_cmp(peer, DP_PEER_STATE_LOGICAL_DELETE))
114*5113495bSYour Name 			wds_entry->delete_in_fw = false;
115*5113495bSYour Name 		else
116*5113495bSYour Name 			wds_entry->delete_in_fw = true;
117*5113495bSYour Name 
118*5113495bSYour Name 		dp_peer_debug("ase->type: %d pdev: %u vdev: %u mac_addr: " QDF_MAC_ADDR_FMT " next_hop: %u peer: %u",
119*5113495bSYour Name 			      ase->type, ase->pdev_id, ase->vdev_id,
120*5113495bSYour Name 			      QDF_MAC_ADDR_REF(ase->mac_addr.raw),
121*5113495bSYour Name 			      ase->next_hop, ase->peer_id);
122*5113495bSYour Name 		TAILQ_INSERT_TAIL(&list->ase_list, wds_entry, ase_list_elem);
123*5113495bSYour Name 		list->num_entries++;
124*5113495bSYour Name 	}
125*5113495bSYour Name 	dp_peer_info("Total num of entries :%d", list->num_entries);
126*5113495bSYour Name }
127*5113495bSYour Name 
128*5113495bSYour Name static void
dp_peer_age_multi_ast_entries(struct dp_soc * soc,void * arg,enum dp_mod_id mod_id)129*5113495bSYour Name dp_peer_age_multi_ast_entries(struct dp_soc *soc, void *arg,
130*5113495bSYour Name 			      enum dp_mod_id mod_id)
131*5113495bSYour Name {
132*5113495bSYour Name 	uint8_t i;
133*5113495bSYour Name 	struct dp_pdev *pdev = NULL;
134*5113495bSYour Name 	struct peer_del_multi_wds_entries wds_list = {0};
135*5113495bSYour Name 
136*5113495bSYour Name 	TAILQ_INIT(&wds_list.ase_list);
137*5113495bSYour Name 	for (i = 0; i < MAX_PDEV_CNT && soc->pdev_list[i]; i++) {
138*5113495bSYour Name 		pdev = soc->pdev_list[i];
139*5113495bSYour Name 		dp_pdev_iterate_peer(pdev, dp_pdev_build_peer_ase_list,
140*5113495bSYour Name 				     &wds_list, mod_id);
141*5113495bSYour Name 		if (wds_list.num_entries > 0) {
142*5113495bSYour Name 			dp_peer_ast_send_multi_wds_del(soc, wds_list.vdev_id,
143*5113495bSYour Name 						       &wds_list);
144*5113495bSYour Name 			dp_peer_free_peer_ase_list(soc, &wds_list);
145*5113495bSYour Name 		} else {
146*5113495bSYour Name 			dp_peer_debug("No AST entries for pdev:%u",
147*5113495bSYour Name 				      pdev->pdev_id);
148*5113495bSYour Name 		}
149*5113495bSYour Name 	}
150*5113495bSYour Name }
151*5113495bSYour Name #endif /* WLAN_FEATURE_MULTI_AST_DEL */
152*5113495bSYour Name 
153*5113495bSYour Name static void
dp_peer_age_ast_entries(struct dp_soc * soc,struct dp_peer * peer,void * arg)154*5113495bSYour Name dp_peer_age_ast_entries(struct dp_soc *soc, struct dp_peer *peer, void *arg)
155*5113495bSYour Name {
156*5113495bSYour Name 	struct dp_ast_entry *ase, *temp_ase;
157*5113495bSYour Name 	struct ast_del_ctxt *del_ctxt = (struct ast_del_ctxt *)arg;
158*5113495bSYour Name 
159*5113495bSYour Name 	if ((del_ctxt->del_count >= soc->max_ast_ageout_count) &&
160*5113495bSYour Name 	    !del_ctxt->age) {
161*5113495bSYour Name 		return;
162*5113495bSYour Name 	}
163*5113495bSYour Name 
164*5113495bSYour Name 	DP_PEER_ITERATE_ASE_LIST(peer, ase, temp_ase) {
165*5113495bSYour Name 		/*
166*5113495bSYour Name 		 * Do not expire static ast entries and HM WDS entries
167*5113495bSYour Name 		 */
168*5113495bSYour Name 		if (ase->type != CDP_TXRX_AST_TYPE_WDS &&
169*5113495bSYour Name 		    ase->type != CDP_TXRX_AST_TYPE_DA)
170*5113495bSYour Name 			continue;
171*5113495bSYour Name 
172*5113495bSYour Name 		if (ase->is_active) {
173*5113495bSYour Name 			if (del_ctxt->age)
174*5113495bSYour Name 				ase->is_active = FALSE;
175*5113495bSYour Name 
176*5113495bSYour Name 			continue;
177*5113495bSYour Name 		}
178*5113495bSYour Name 
179*5113495bSYour Name 		if (del_ctxt->del_count < soc->max_ast_ageout_count) {
180*5113495bSYour Name 			DP_STATS_INC(soc, ast.aged_out, 1);
181*5113495bSYour Name 			dp_peer_del_ast(soc, ase);
182*5113495bSYour Name 			del_ctxt->del_count++;
183*5113495bSYour Name 		} else {
184*5113495bSYour Name 			soc->pending_ageout = true;
185*5113495bSYour Name 			if (!del_ctxt->age)
186*5113495bSYour Name 				break;
187*5113495bSYour Name 		}
188*5113495bSYour Name 	}
189*5113495bSYour Name }
190*5113495bSYour Name 
191*5113495bSYour Name static void
dp_peer_age_mec_entries(struct dp_soc * soc)192*5113495bSYour Name dp_peer_age_mec_entries(struct dp_soc *soc)
193*5113495bSYour Name {
194*5113495bSYour Name 	uint32_t index;
195*5113495bSYour Name 	struct dp_mec_entry *mecentry, *mecentry_next;
196*5113495bSYour Name 
197*5113495bSYour Name 	TAILQ_HEAD(, dp_mec_entry) free_list;
198*5113495bSYour Name 	TAILQ_INIT(&free_list);
199*5113495bSYour Name 
200*5113495bSYour Name 	for (index = 0; index <= soc->mec_hash.mask; index++) {
201*5113495bSYour Name 		qdf_spin_lock_bh(&soc->mec_lock);
202*5113495bSYour Name 		/*
203*5113495bSYour Name 		 * Expire MEC entry every n sec.
204*5113495bSYour Name 		 */
205*5113495bSYour Name 		if (!TAILQ_EMPTY(&soc->mec_hash.bins[index])) {
206*5113495bSYour Name 			TAILQ_FOREACH_SAFE(mecentry, &soc->mec_hash.bins[index],
207*5113495bSYour Name 					   hash_list_elem, mecentry_next) {
208*5113495bSYour Name 				if (mecentry->is_active) {
209*5113495bSYour Name 					mecentry->is_active = FALSE;
210*5113495bSYour Name 					continue;
211*5113495bSYour Name 				}
212*5113495bSYour Name 				dp_peer_mec_detach_entry(soc, mecentry,
213*5113495bSYour Name 							 &free_list);
214*5113495bSYour Name 			}
215*5113495bSYour Name 		}
216*5113495bSYour Name 		qdf_spin_unlock_bh(&soc->mec_lock);
217*5113495bSYour Name 	}
218*5113495bSYour Name 
219*5113495bSYour Name 	dp_peer_mec_free_list(soc, &free_list);
220*5113495bSYour Name }
221*5113495bSYour Name 
222*5113495bSYour Name #ifdef WLAN_FEATURE_MULTI_AST_DEL
dp_ast_aging_timer_fn(void * soc_hdl)223*5113495bSYour Name static void dp_ast_aging_timer_fn(void *soc_hdl)
224*5113495bSYour Name {
225*5113495bSYour Name 	struct dp_soc *soc = (struct dp_soc *)soc_hdl;
226*5113495bSYour Name 	struct ast_del_ctxt del_ctxt = {0};
227*5113495bSYour Name 
228*5113495bSYour Name 	if (soc->wds_ast_aging_timer_cnt++ >= DP_WDS_AST_AGING_TIMER_CNT) {
229*5113495bSYour Name 		del_ctxt.age = true;
230*5113495bSYour Name 		soc->wds_ast_aging_timer_cnt = 0;
231*5113495bSYour Name 	}
232*5113495bSYour Name 
233*5113495bSYour Name 	if (soc->pending_ageout || del_ctxt.age) {
234*5113495bSYour Name 		soc->pending_ageout = false;
235*5113495bSYour Name 
236*5113495bSYour Name 		/* AST list access lock */
237*5113495bSYour Name 		qdf_spin_lock_bh(&soc->ast_lock);
238*5113495bSYour Name 
239*5113495bSYour Name 		if (soc->multi_peer_grp_cmd_supported)
240*5113495bSYour Name 			dp_peer_age_multi_ast_entries(soc, NULL, DP_MOD_ID_AST);
241*5113495bSYour Name 		else
242*5113495bSYour Name 			dp_soc_iterate_peer(soc, dp_peer_age_ast_entries,
243*5113495bSYour Name 					    &del_ctxt, DP_MOD_ID_AST);
244*5113495bSYour Name 		qdf_spin_unlock_bh(&soc->ast_lock);
245*5113495bSYour Name 	}
246*5113495bSYour Name 
247*5113495bSYour Name 	/*
248*5113495bSYour Name 	 * If NSS offload is enabled, the MEC timeout
249*5113495bSYour Name 	 * will be managed by NSS.
250*5113495bSYour Name 	 */
251*5113495bSYour Name 	if (qdf_atomic_read(&soc->mec_cnt) &&
252*5113495bSYour Name 	    !wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx))
253*5113495bSYour Name 		dp_peer_age_mec_entries(soc);
254*5113495bSYour Name 
255*5113495bSYour Name 	if (qdf_atomic_read(&soc->cmn_init_done))
256*5113495bSYour Name 		qdf_timer_mod(&soc->ast_aging_timer,
257*5113495bSYour Name 			      DP_AST_AGING_TIMER_DEFAULT_MS);
258*5113495bSYour Name }
259*5113495bSYour Name #else
dp_ast_aging_timer_fn(void * soc_hdl)260*5113495bSYour Name static void dp_ast_aging_timer_fn(void *soc_hdl)
261*5113495bSYour Name {
262*5113495bSYour Name 	struct dp_soc *soc = (struct dp_soc *)soc_hdl;
263*5113495bSYour Name 	struct ast_del_ctxt del_ctxt = {0};
264*5113495bSYour Name 
265*5113495bSYour Name 	if (soc->wds_ast_aging_timer_cnt++ >= DP_WDS_AST_AGING_TIMER_CNT) {
266*5113495bSYour Name 		del_ctxt.age = true;
267*5113495bSYour Name 		soc->wds_ast_aging_timer_cnt = 0;
268*5113495bSYour Name 	}
269*5113495bSYour Name 
270*5113495bSYour Name 	if (soc->pending_ageout || del_ctxt.age) {
271*5113495bSYour Name 		soc->pending_ageout = false;
272*5113495bSYour Name 
273*5113495bSYour Name 		/* AST list access lock */
274*5113495bSYour Name 		qdf_spin_lock_bh(&soc->ast_lock);
275*5113495bSYour Name 		dp_soc_iterate_peer(soc, dp_peer_age_ast_entries,
276*5113495bSYour Name 				    &del_ctxt, DP_MOD_ID_AST);
277*5113495bSYour Name 		qdf_spin_unlock_bh(&soc->ast_lock);
278*5113495bSYour Name 	}
279*5113495bSYour Name 
280*5113495bSYour Name 	/*
281*5113495bSYour Name 	 * If NSS offload is enabled, the MEC timeout
282*5113495bSYour Name 	 * will be managed by NSS.
283*5113495bSYour Name 	 */
284*5113495bSYour Name 	if (qdf_atomic_read(&soc->mec_cnt) &&
285*5113495bSYour Name 	    !wlan_cfg_get_dp_soc_nss_cfg(soc->wlan_cfg_ctx))
286*5113495bSYour Name 		dp_peer_age_mec_entries(soc);
287*5113495bSYour Name 
288*5113495bSYour Name 	if (qdf_atomic_read(&soc->cmn_init_done))
289*5113495bSYour Name 		qdf_timer_mod(&soc->ast_aging_timer,
290*5113495bSYour Name 			      DP_AST_AGING_TIMER_DEFAULT_MS);
291*5113495bSYour Name }
292*5113495bSYour Name #endif /* WLAN_FEATURE_MULTI_AST_DEL */
293*5113495bSYour Name 
294*5113495bSYour Name #ifndef IPA_WDS_EASYMESH_FEATURE
dp_soc_wds_attach(struct dp_soc * soc)295*5113495bSYour Name void dp_soc_wds_attach(struct dp_soc *soc)
296*5113495bSYour Name {
297*5113495bSYour Name 	if (soc->ast_offload_support)
298*5113495bSYour Name 		return;
299*5113495bSYour Name 
300*5113495bSYour Name 	soc->wds_ast_aging_timer_cnt = 0;
301*5113495bSYour Name 	soc->pending_ageout = false;
302*5113495bSYour Name 	qdf_timer_init(soc->osdev, &soc->ast_aging_timer,
303*5113495bSYour Name 		       dp_ast_aging_timer_fn, (void *)soc,
304*5113495bSYour Name 		       QDF_TIMER_TYPE_WAKE_APPS);
305*5113495bSYour Name 
306*5113495bSYour Name 	qdf_timer_mod(&soc->ast_aging_timer, DP_AST_AGING_TIMER_DEFAULT_MS);
307*5113495bSYour Name }
308*5113495bSYour Name 
dp_soc_wds_detach(struct dp_soc * soc)309*5113495bSYour Name void dp_soc_wds_detach(struct dp_soc *soc)
310*5113495bSYour Name {
311*5113495bSYour Name 	qdf_timer_stop(&soc->ast_aging_timer);
312*5113495bSYour Name 	qdf_timer_free(&soc->ast_aging_timer);
313*5113495bSYour Name }
314*5113495bSYour Name #else
dp_soc_wds_attach(struct dp_soc * soc)315*5113495bSYour Name void dp_soc_wds_attach(struct dp_soc *soc)
316*5113495bSYour Name {
317*5113495bSYour Name }
318*5113495bSYour Name 
dp_soc_wds_detach(struct dp_soc * soc)319*5113495bSYour Name void dp_soc_wds_detach(struct dp_soc *soc)
320*5113495bSYour Name {
321*5113495bSYour Name }
322*5113495bSYour Name #endif
323*5113495bSYour Name 
dp_tx_mec_handler(struct dp_vdev * vdev,uint8_t * status)324*5113495bSYour Name void dp_tx_mec_handler(struct dp_vdev *vdev, uint8_t *status)
325*5113495bSYour Name {
326*5113495bSYour Name 	struct dp_soc *soc;
327*5113495bSYour Name 	QDF_STATUS add_mec_status;
328*5113495bSYour Name 	uint8_t mac_addr[QDF_MAC_ADDR_SIZE], i;
329*5113495bSYour Name 
330*5113495bSYour Name 	if (!vdev->mec_enabled)
331*5113495bSYour Name 		return;
332*5113495bSYour Name 
333*5113495bSYour Name 	/* MEC required only in STA mode */
334*5113495bSYour Name 	if (vdev->opmode != wlan_op_mode_sta)
335*5113495bSYour Name 		return;
336*5113495bSYour Name 
337*5113495bSYour Name 	soc = vdev->pdev->soc;
338*5113495bSYour Name 
339*5113495bSYour Name 	for (i = 0; i < QDF_MAC_ADDR_SIZE; i++)
340*5113495bSYour Name 		mac_addr[(QDF_MAC_ADDR_SIZE - 1) - i] =
341*5113495bSYour Name 					status[(QDF_MAC_ADDR_SIZE - 2) + i];
342*5113495bSYour Name 
343*5113495bSYour Name 	dp_peer_debug("%pK: MEC add for mac_addr "QDF_MAC_ADDR_FMT,
344*5113495bSYour Name 		      soc, QDF_MAC_ADDR_REF(mac_addr));
345*5113495bSYour Name 
346*5113495bSYour Name 	if (qdf_mem_cmp(mac_addr, vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE)) {
347*5113495bSYour Name 		add_mec_status = dp_peer_mec_add_entry(soc, vdev, mac_addr);
348*5113495bSYour Name 		dp_peer_debug("%pK: MEC add status %d", vdev, add_mec_status);
349*5113495bSYour Name 	}
350*5113495bSYour Name }
351*5113495bSYour Name 
352*5113495bSYour Name #ifndef QCA_HOST_MODE_WIFI_DISABLED
353*5113495bSYour Name 
354*5113495bSYour Name void
dp_rx_da_learn(struct dp_soc * soc,uint8_t * rx_tlv_hdr,struct dp_txrx_peer * ta_txrx_peer,qdf_nbuf_t nbuf)355*5113495bSYour Name dp_rx_da_learn(struct dp_soc *soc,
356*5113495bSYour Name 	       uint8_t *rx_tlv_hdr,
357*5113495bSYour Name 	       struct dp_txrx_peer *ta_txrx_peer,
358*5113495bSYour Name 	       qdf_nbuf_t nbuf)
359*5113495bSYour Name {
360*5113495bSYour Name 	struct dp_peer *base_peer;
361*5113495bSYour Name 	/* For HKv2 DA port learing is not needed */
362*5113495bSYour Name 	if (qdf_likely(soc->ast_override_support))
363*5113495bSYour Name 		return;
364*5113495bSYour Name 
365*5113495bSYour Name 	if (qdf_unlikely(!ta_txrx_peer))
366*5113495bSYour Name 		return;
367*5113495bSYour Name 
368*5113495bSYour Name 	if (qdf_unlikely(ta_txrx_peer->vdev->opmode != wlan_op_mode_ap))
369*5113495bSYour Name 		return;
370*5113495bSYour Name 
371*5113495bSYour Name 	if (!soc->da_war_enabled)
372*5113495bSYour Name 		return;
373*5113495bSYour Name 
374*5113495bSYour Name 	if (qdf_unlikely(!qdf_nbuf_is_da_valid(nbuf) &&
375*5113495bSYour Name 			 !qdf_nbuf_is_da_mcbc(nbuf))) {
376*5113495bSYour Name 		base_peer = dp_peer_get_ref_by_id(soc, ta_txrx_peer->peer_id,
377*5113495bSYour Name 						  DP_MOD_ID_AST);
378*5113495bSYour Name 
379*5113495bSYour Name 		if (base_peer) {
380*5113495bSYour Name 			dp_peer_add_ast(soc,
381*5113495bSYour Name 					base_peer,
382*5113495bSYour Name 					qdf_nbuf_data(nbuf),
383*5113495bSYour Name 					CDP_TXRX_AST_TYPE_DA,
384*5113495bSYour Name 					DP_AST_FLAGS_HM);
385*5113495bSYour Name 
386*5113495bSYour Name 			dp_peer_unref_delete(base_peer, DP_MOD_ID_AST);
387*5113495bSYour Name 		}
388*5113495bSYour Name 	}
389*5113495bSYour Name }
390*5113495bSYour Name 
391*5113495bSYour Name #ifdef WDS_VENDOR_EXTENSION
392*5113495bSYour Name QDF_STATUS
dp_txrx_set_wds_rx_policy(struct cdp_soc_t * soc_hdl,uint8_t vdev_id,u_int32_t val)393*5113495bSYour Name dp_txrx_set_wds_rx_policy(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
394*5113495bSYour Name 			  u_int32_t val)
395*5113495bSYour Name {
396*5113495bSYour Name 	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
397*5113495bSYour Name 	struct dp_peer *peer;
398*5113495bSYour Name 	struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id,
399*5113495bSYour Name 						     DP_MOD_ID_MISC);
400*5113495bSYour Name 	if (!vdev) {
401*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
402*5113495bSYour Name 			  FL("vdev is NULL for vdev_id %d"), vdev_id);
403*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
404*5113495bSYour Name 	}
405*5113495bSYour Name 
406*5113495bSYour Name 	peer = dp_vdev_bss_peer_ref_n_get(vdev, DP_MOD_ID_AST);
407*5113495bSYour Name 
408*5113495bSYour Name 	if (peer) {
409*5113495bSYour Name 		peer->txrx_peer->wds_ecm.wds_rx_filter = 1;
410*5113495bSYour Name 		peer->txrx_peer->wds_ecm.wds_rx_ucast_4addr =
411*5113495bSYour Name 			(val & WDS_POLICY_RX_UCAST_4ADDR) ? 1 : 0;
412*5113495bSYour Name 		peer->txrx_peer->wds_ecm.wds_rx_mcast_4addr =
413*5113495bSYour Name 			(val & WDS_POLICY_RX_MCAST_4ADDR) ? 1 : 0;
414*5113495bSYour Name 		dp_peer_unref_delete(peer, DP_MOD_ID_AST);
415*5113495bSYour Name 	}
416*5113495bSYour Name 
417*5113495bSYour Name 	dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_MISC);
418*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
419*5113495bSYour Name }
420*5113495bSYour Name 
421*5113495bSYour Name QDF_STATUS
dp_txrx_peer_wds_tx_policy_update(struct cdp_soc_t * soc,uint8_t vdev_id,uint8_t * peer_mac,int wds_tx_ucast,int wds_tx_mcast)422*5113495bSYour Name dp_txrx_peer_wds_tx_policy_update(struct cdp_soc_t *soc,  uint8_t vdev_id,
423*5113495bSYour Name 				  uint8_t *peer_mac, int wds_tx_ucast,
424*5113495bSYour Name 				  int wds_tx_mcast)
425*5113495bSYour Name {
426*5113495bSYour Name 	struct dp_peer *peer =
427*5113495bSYour Name 			dp_peer_get_tgt_peer_hash_find((struct dp_soc *)soc,
428*5113495bSYour Name 						       peer_mac, 0,
429*5113495bSYour Name 						       vdev_id,
430*5113495bSYour Name 						       DP_MOD_ID_AST);
431*5113495bSYour Name 	if (!peer) {
432*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
433*5113495bSYour Name 			  FL("peer is NULL for mac" QDF_MAC_ADDR_FMT
434*5113495bSYour Name 			     " vdev_id %d"), QDF_MAC_ADDR_REF(peer_mac),
435*5113495bSYour Name 			     vdev_id);
436*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
437*5113495bSYour Name 	}
438*5113495bSYour Name 
439*5113495bSYour Name 	if (!peer->txrx_peer) {
440*5113495bSYour Name 		dp_peer_unref_delete(peer, DP_MOD_ID_AST);
441*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
442*5113495bSYour Name 	}
443*5113495bSYour Name 
444*5113495bSYour Name 	if (wds_tx_ucast || wds_tx_mcast) {
445*5113495bSYour Name 		peer->txrx_peer->wds_enabled = 1;
446*5113495bSYour Name 		peer->txrx_peer->wds_ecm.wds_tx_ucast_4addr = wds_tx_ucast;
447*5113495bSYour Name 		peer->txrx_peer->wds_ecm.wds_tx_mcast_4addr = wds_tx_mcast;
448*5113495bSYour Name 	} else {
449*5113495bSYour Name 		peer->txrx_peer->wds_enabled = 0;
450*5113495bSYour Name 		peer->txrx_peer->wds_ecm.wds_tx_ucast_4addr = 0;
451*5113495bSYour Name 		peer->txrx_peer->wds_ecm.wds_tx_mcast_4addr = 0;
452*5113495bSYour Name 	}
453*5113495bSYour Name 
454*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
455*5113495bSYour Name 		  "Policy Update set to :\n");
456*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
457*5113495bSYour Name 		  "peer->wds_enabled %d\n", peer->wds_enabled);
458*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
459*5113495bSYour Name 		  "peer->wds_ecm.wds_tx_ucast_4addr %d\n",
460*5113495bSYour Name 		  peer->txrx_peer->wds_ecm.wds_tx_ucast_4addr);
461*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
462*5113495bSYour Name 		  "peer->wds_ecm.wds_tx_mcast_4addr %d\n",
463*5113495bSYour Name 		  peer->txrx_peer->wds_ecm.wds_tx_mcast_4addr);
464*5113495bSYour Name 
465*5113495bSYour Name 	dp_peer_unref_delete(peer, DP_MOD_ID_AST);
466*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
467*5113495bSYour Name }
468*5113495bSYour Name 
dp_wds_rx_policy_check(uint8_t * rx_tlv_hdr,struct dp_vdev * vdev,struct dp_txrx_peer * txrx_peer)469*5113495bSYour Name int dp_wds_rx_policy_check(uint8_t *rx_tlv_hdr,
470*5113495bSYour Name 			   struct dp_vdev *vdev,
471*5113495bSYour Name 			   struct dp_txrx_peer *txrx_peer)
472*5113495bSYour Name {
473*5113495bSYour Name 	struct dp_peer *bss_peer;
474*5113495bSYour Name 	int fr_ds, to_ds, rx_3addr, rx_4addr;
475*5113495bSYour Name 	int rx_policy_ucast, rx_policy_mcast;
476*5113495bSYour Name 	hal_soc_handle_t hal_soc = vdev->pdev->soc->hal_soc;
477*5113495bSYour Name 	int rx_mcast = hal_rx_msdu_end_da_is_mcbc_get(hal_soc, rx_tlv_hdr);
478*5113495bSYour Name 
479*5113495bSYour Name 	if (vdev->opmode == wlan_op_mode_ap) {
480*5113495bSYour Name 		bss_peer = dp_vdev_bss_peer_ref_n_get(vdev, DP_MOD_ID_AST);
481*5113495bSYour Name 		/* if wds policy check is not enabled on this vdev, accept all frames */
482*5113495bSYour Name 		if (bss_peer && !bss_peer->txrx_peer->wds_ecm.wds_rx_filter) {
483*5113495bSYour Name 			dp_peer_unref_delete(bss_peer, DP_MOD_ID_AST);
484*5113495bSYour Name 			return 1;
485*5113495bSYour Name 		}
486*5113495bSYour Name 		rx_policy_ucast = bss_peer->txrx_peerwds_ecm.wds_rx_ucast_4addr;
487*5113495bSYour Name 		rx_policy_mcast = bss_peer->txrx_peerwds_ecm.wds_rx_mcast_4addr;
488*5113495bSYour Name 		dp_peer_unref_delete(bss_peer, DP_MOD_ID_AST);
489*5113495bSYour Name 	} else {             /* sta mode */
490*5113495bSYour Name 		if (!txrx_peer->wds_ecm.wds_rx_filter)
491*5113495bSYour Name 			return 1;
492*5113495bSYour Name 
493*5113495bSYour Name 		rx_policy_ucast = txrx_peer->wds_ecm.wds_rx_ucast_4addr;
494*5113495bSYour Name 		rx_policy_mcast = txrx_peer->wds_ecm.wds_rx_mcast_4addr;
495*5113495bSYour Name 	}
496*5113495bSYour Name 
497*5113495bSYour Name 	/* ------------------------------------------------
498*5113495bSYour Name 	 *                       self
499*5113495bSYour Name 	 * peer-             rx  rx-
500*5113495bSYour Name 	 * wds  ucast mcast dir policy accept note
501*5113495bSYour Name 	 * ------------------------------------------------
502*5113495bSYour Name 	 * 1     1     0     11  x1     1      AP configured to accept ds-to-ds Rx ucast from wds peers, constraint met; so, accept
503*5113495bSYour Name 	 * 1     1     0     01  x1     0      AP configured to accept ds-to-ds Rx ucast from wds peers, constraint not met; so, drop
504*5113495bSYour Name 	 * 1     1     0     10  x1     0      AP configured to accept ds-to-ds Rx ucast from wds peers, constraint not met; so, drop
505*5113495bSYour Name 	 * 1     1     0     00  x1     0      bad frame, won't see it
506*5113495bSYour Name 	 * 1     0     1     11  1x     1      AP configured to accept ds-to-ds Rx mcast from wds peers, constraint met; so, accept
507*5113495bSYour Name 	 * 1     0     1     01  1x     0      AP configured to accept ds-to-ds Rx mcast from wds peers, constraint not met; so, drop
508*5113495bSYour Name 	 * 1     0     1     10  1x     0      AP configured to accept ds-to-ds Rx mcast from wds peers, constraint not met; so, drop
509*5113495bSYour Name 	 * 1     0     1     00  1x     0      bad frame, won't see it
510*5113495bSYour Name 	 * 1     1     0     11  x0     0      AP configured to accept from-ds Rx ucast from wds peers, constraint not met; so, drop
511*5113495bSYour Name 	 * 1     1     0     01  x0     0      AP configured to accept from-ds Rx ucast from wds peers, constraint not met; so, drop
512*5113495bSYour Name 	 * 1     1     0     10  x0     1      AP configured to accept from-ds Rx ucast from wds peers, constraint met; so, accept
513*5113495bSYour Name 	 * 1     1     0     00  x0     0      bad frame, won't see it
514*5113495bSYour Name 	 * 1     0     1     11  0x     0      AP configured to accept from-ds Rx mcast from wds peers, constraint not met; so, drop
515*5113495bSYour Name 	 * 1     0     1     01  0x     0      AP configured to accept from-ds Rx mcast from wds peers, constraint not met; so, drop
516*5113495bSYour Name 	 * 1     0     1     10  0x     1      AP configured to accept from-ds Rx mcast from wds peers, constraint met; so, accept
517*5113495bSYour Name 	 * 1     0     1     00  0x     0      bad frame, won't see it
518*5113495bSYour Name 	 *
519*5113495bSYour Name 	 * 0     x     x     11  xx     0      we only accept td-ds Rx frames from non-wds peers in mode.
520*5113495bSYour Name 	 * 0     x     x     01  xx     1
521*5113495bSYour Name 	 * 0     x     x     10  xx     0
522*5113495bSYour Name 	 * 0     x     x     00  xx     0      bad frame, won't see it
523*5113495bSYour Name 	 * ------------------------------------------------
524*5113495bSYour Name 	 */
525*5113495bSYour Name 
526*5113495bSYour Name 	fr_ds = hal_rx_mpdu_get_fr_ds(hal_soc, rx_tlv_hdr);
527*5113495bSYour Name 	to_ds = hal_rx_mpdu_get_to_ds(hal_soc, rx_tlv_hdr);
528*5113495bSYour Name 	rx_3addr = fr_ds ^ to_ds;
529*5113495bSYour Name 	rx_4addr = fr_ds & to_ds;
530*5113495bSYour Name 
531*5113495bSYour Name 	if (vdev->opmode == wlan_op_mode_ap) {
532*5113495bSYour Name 		if ((!txrx_peer->wds_enabled && rx_3addr && to_ds) ||
533*5113495bSYour Name 		    (txrx_peer->wds_enabled && !rx_mcast &&
534*5113495bSYour Name 		    (rx_4addr == rx_policy_ucast)) ||
535*5113495bSYour Name 		    (txrx_peer->wds_enabled && rx_mcast &&
536*5113495bSYour Name 		    (rx_4addr == rx_policy_mcast))) {
537*5113495bSYour Name 			return 1;
538*5113495bSYour Name 		}
539*5113495bSYour Name 	} else {           /* sta mode */
540*5113495bSYour Name 		if ((!rx_mcast && (rx_4addr == rx_policy_ucast)) ||
541*5113495bSYour Name 				(rx_mcast && (rx_4addr == rx_policy_mcast))) {
542*5113495bSYour Name 			return 1;
543*5113495bSYour Name 		}
544*5113495bSYour Name 	}
545*5113495bSYour Name 	return 0;
546*5113495bSYour Name }
547*5113495bSYour Name #endif
548*5113495bSYour Name 
549*5113495bSYour Name #endif /* QCA_HOST_MODE_WIFI_DISABLED */
550*5113495bSYour Name 
551*5113495bSYour Name #ifdef QCA_PEER_MULTIQ_SUPPORT
552*5113495bSYour Name 
dp_peer_reset_flowq_map(struct dp_peer * peer)553*5113495bSYour Name void dp_peer_reset_flowq_map(struct dp_peer *peer)
554*5113495bSYour Name {
555*5113495bSYour Name 	int i = 0;
556*5113495bSYour Name 
557*5113495bSYour Name 	if (!peer)
558*5113495bSYour Name 		return;
559*5113495bSYour Name 
560*5113495bSYour Name 	for (i = 0; i < DP_PEER_AST_FLOWQ_MAX; i++) {
561*5113495bSYour Name 		peer->peer_ast_flowq_idx[i].is_valid = false;
562*5113495bSYour Name 		peer->peer_ast_flowq_idx[i].valid_tid_mask = false;
563*5113495bSYour Name 		peer->peer_ast_flowq_idx[i].ast_idx = DP_INVALID_AST_IDX;
564*5113495bSYour Name 		peer->peer_ast_flowq_idx[i].flowQ = DP_INVALID_FLOW_PRIORITY;
565*5113495bSYour Name 	}
566*5113495bSYour Name }
567*5113495bSYour Name 
568*5113495bSYour Name /**
569*5113495bSYour Name  * dp_peer_get_flowid_from_flowmask() - get flow id from flow mask
570*5113495bSYour Name  * @peer: dp peer handle
571*5113495bSYour Name  * @mask: flow mask
572*5113495bSYour Name  *
573*5113495bSYour Name  * Return: flow id
574*5113495bSYour Name  */
dp_peer_get_flowid_from_flowmask(struct dp_peer * peer,uint8_t mask)575*5113495bSYour Name static int dp_peer_get_flowid_from_flowmask(struct dp_peer *peer,
576*5113495bSYour Name 		uint8_t mask)
577*5113495bSYour Name {
578*5113495bSYour Name 	if (!peer) {
579*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
580*5113495bSYour Name 				"%s: Invalid peer\n", __func__);
581*5113495bSYour Name 		return -1;
582*5113495bSYour Name 	}
583*5113495bSYour Name 
584*5113495bSYour Name 	if (mask & DP_PEER_AST0_FLOW_MASK)
585*5113495bSYour Name 		return DP_PEER_AST_FLOWQ_UDP;
586*5113495bSYour Name 	else if (mask & DP_PEER_AST1_FLOW_MASK)
587*5113495bSYour Name 		return DP_PEER_AST_FLOWQ_NON_UDP;
588*5113495bSYour Name 	else if (mask & DP_PEER_AST2_FLOW_MASK)
589*5113495bSYour Name 		return DP_PEER_AST_FLOWQ_HI_PRIO;
590*5113495bSYour Name 	else if (mask & DP_PEER_AST3_FLOW_MASK)
591*5113495bSYour Name 		return DP_PEER_AST_FLOWQ_LOW_PRIO;
592*5113495bSYour Name 
593*5113495bSYour Name 	return DP_PEER_AST_FLOWQ_MAX;
594*5113495bSYour Name }
595*5113495bSYour Name 
596*5113495bSYour Name /**
597*5113495bSYour Name  * dp_peer_get_ast_valid() - get ast index valid from mask
598*5113495bSYour Name  * @mask: mask for ast valid bits
599*5113495bSYour Name  * @index: index for an ast
600*5113495bSYour Name  *
601*5113495bSYour Name  * Return: 1 if ast index is valid from mask else 0
602*5113495bSYour Name  */
dp_peer_get_ast_valid(uint8_t mask,uint16_t index)603*5113495bSYour Name static inline bool dp_peer_get_ast_valid(uint8_t mask, uint16_t index)
604*5113495bSYour Name {
605*5113495bSYour Name 	if (index == 0)
606*5113495bSYour Name 		return 1;
607*5113495bSYour Name 	return ((mask) & (1 << ((index) - 1)));
608*5113495bSYour Name }
609*5113495bSYour Name 
dp_peer_ast_index_flow_queue_map_create(void * soc_hdl,bool is_wds,uint16_t peer_id,uint8_t * peer_mac_addr,struct dp_ast_flow_override_info * ast_info)610*5113495bSYour Name void dp_peer_ast_index_flow_queue_map_create(void *soc_hdl,
611*5113495bSYour Name 		bool is_wds, uint16_t peer_id, uint8_t *peer_mac_addr,
612*5113495bSYour Name 		struct dp_ast_flow_override_info *ast_info)
613*5113495bSYour Name {
614*5113495bSYour Name 	struct dp_soc *soc = (struct dp_soc *)soc_hdl;
615*5113495bSYour Name 	struct dp_peer *peer = NULL;
616*5113495bSYour Name 	uint8_t i;
617*5113495bSYour Name 
618*5113495bSYour Name 	/*
619*5113495bSYour Name 	 * Ast flow override feature is supported
620*5113495bSYour Name 	 * only for connected client
621*5113495bSYour Name 	 */
622*5113495bSYour Name 	if (is_wds)
623*5113495bSYour Name 		return;
624*5113495bSYour Name 
625*5113495bSYour Name 	peer = dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_AST);
626*5113495bSYour Name 	if (!peer) {
627*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
628*5113495bSYour Name 				"%s: Invalid peer\n", __func__);
629*5113495bSYour Name 		return;
630*5113495bSYour Name 	}
631*5113495bSYour Name 
632*5113495bSYour Name 	/* Valid only in AP mode */
633*5113495bSYour Name 	if (peer->vdev->opmode != wlan_op_mode_ap) {
634*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
635*5113495bSYour Name 				"%s: Peer ast flow map not in STA mode\n", __func__);
636*5113495bSYour Name 		goto end;
637*5113495bSYour Name 	}
638*5113495bSYour Name 
639*5113495bSYour Name 	/* Making sure the peer is for this mac address */
640*5113495bSYour Name 	if (!qdf_is_macaddr_equal((struct qdf_mac_addr *)peer_mac_addr,
641*5113495bSYour Name 				(struct qdf_mac_addr *)peer->mac_addr.raw)) {
642*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
643*5113495bSYour Name 				"%s: Peer mac address mismatch\n", __func__);
644*5113495bSYour Name 		goto end;
645*5113495bSYour Name 	}
646*5113495bSYour Name 
647*5113495bSYour Name 	/* Ast entry flow mapping not valid for self peer map */
648*5113495bSYour Name 	if (qdf_is_macaddr_equal((struct qdf_mac_addr *)peer_mac_addr,
649*5113495bSYour Name 				(struct qdf_mac_addr *)peer->vdev->mac_addr.raw)) {
650*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
651*5113495bSYour Name 				"%s: Ast flow mapping not valid for self peer \n", __func__);
652*5113495bSYour Name 		goto end;
653*5113495bSYour Name 	}
654*5113495bSYour Name 
655*5113495bSYour Name 	/* Fill up ast index <---> flow id mapping table for this peer */
656*5113495bSYour Name 	for (i = 0; i < DP_MAX_AST_INDEX_PER_PEER; i++) {
657*5113495bSYour Name 
658*5113495bSYour Name 		/* Check if this ast index is valid */
659*5113495bSYour Name 		peer->peer_ast_flowq_idx[i].is_valid =
660*5113495bSYour Name 			dp_peer_get_ast_valid(ast_info->ast_valid_mask, i);
661*5113495bSYour Name 		if (!peer->peer_ast_flowq_idx[i].is_valid)
662*5113495bSYour Name 			continue;
663*5113495bSYour Name 
664*5113495bSYour Name 		/* Get the flow queue id which is mapped to this ast index */
665*5113495bSYour Name 		peer->peer_ast_flowq_idx[i].flowQ =
666*5113495bSYour Name 			dp_peer_get_flowid_from_flowmask(peer,
667*5113495bSYour Name 					ast_info->ast_flow_mask[i]);
668*5113495bSYour Name 		/*
669*5113495bSYour Name 		 * Update tid valid mask only if flow id HIGH or
670*5113495bSYour Name 		 * Low priority
671*5113495bSYour Name 		 */
672*5113495bSYour Name 		if (peer->peer_ast_flowq_idx[i].flowQ ==
673*5113495bSYour Name 				DP_PEER_AST_FLOWQ_HI_PRIO) {
674*5113495bSYour Name 			peer->peer_ast_flowq_idx[i].valid_tid_mask =
675*5113495bSYour Name 				ast_info->tid_valid_hi_pri_mask;
676*5113495bSYour Name 		} else if (peer->peer_ast_flowq_idx[i].flowQ ==
677*5113495bSYour Name 				DP_PEER_AST_FLOWQ_LOW_PRIO) {
678*5113495bSYour Name 			peer->peer_ast_flowq_idx[i].valid_tid_mask =
679*5113495bSYour Name 				ast_info->tid_valid_low_pri_mask;
680*5113495bSYour Name 		}
681*5113495bSYour Name 
682*5113495bSYour Name 		/* Save the ast index for this entry */
683*5113495bSYour Name 		peer->peer_ast_flowq_idx[i].ast_idx = ast_info->ast_idx[i];
684*5113495bSYour Name 	}
685*5113495bSYour Name 
686*5113495bSYour Name 	if (soc->cdp_soc.ol_ops->peer_ast_flowid_map) {
687*5113495bSYour Name 		soc->cdp_soc.ol_ops->peer_ast_flowid_map(
688*5113495bSYour Name 				soc->ctrl_psoc, peer->peer_id,
689*5113495bSYour Name 				peer->vdev->vdev_id, peer_mac_addr);
690*5113495bSYour Name 	}
691*5113495bSYour Name 
692*5113495bSYour Name end:
693*5113495bSYour Name 	/* Release peer reference */
694*5113495bSYour Name 	dp_peer_unref_delete(peer, DP_MOD_ID_AST);
695*5113495bSYour Name }
696*5113495bSYour Name 
dp_peer_find_ast_index_by_flowq_id(struct cdp_soc_t * soc,uint16_t vdev_id,uint8_t * peer_mac_addr,uint8_t flow_id,uint8_t tid)697*5113495bSYour Name int dp_peer_find_ast_index_by_flowq_id(struct cdp_soc_t *soc,
698*5113495bSYour Name 		uint16_t vdev_id, uint8_t *peer_mac_addr,
699*5113495bSYour Name 		uint8_t flow_id, uint8_t tid)
700*5113495bSYour Name {
701*5113495bSYour Name 	struct dp_peer *peer = NULL;
702*5113495bSYour Name 	uint8_t i;
703*5113495bSYour Name 	uint16_t ast_index;
704*5113495bSYour Name 
705*5113495bSYour Name 	if (flow_id >= DP_PEER_AST_FLOWQ_MAX) {
706*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
707*5113495bSYour Name 				"Invalid Flow ID %d\n", flow_id);
708*5113495bSYour Name 		return -1;
709*5113495bSYour Name 	}
710*5113495bSYour Name 
711*5113495bSYour Name 	peer = dp_peer_find_hash_find((struct dp_soc *)soc,
712*5113495bSYour Name 				peer_mac_addr, 0, vdev_id,
713*5113495bSYour Name 				DP_MOD_ID_AST);
714*5113495bSYour Name 	if (!peer) {
715*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
716*5113495bSYour Name 				"%s: Invalid peer\n", __func__);
717*5113495bSYour Name 		return -1;
718*5113495bSYour Name 	}
719*5113495bSYour Name 
720*5113495bSYour Name 	 /*
721*5113495bSYour Name 	  * Loop over the ast entry <----> flow-id mapping to find
722*5113495bSYour Name 	  * which ast index entry has this flow queue id enabled.
723*5113495bSYour Name 	  */
724*5113495bSYour Name 	for (i = 0; i < DP_PEER_AST_FLOWQ_MAX; i++) {
725*5113495bSYour Name 		if (peer->peer_ast_flowq_idx[i].flowQ == flow_id)
726*5113495bSYour Name 			/*
727*5113495bSYour Name 			 * Found the matching index for this flow id
728*5113495bSYour Name 			 */
729*5113495bSYour Name 			break;
730*5113495bSYour Name 	}
731*5113495bSYour Name 
732*5113495bSYour Name 	/*
733*5113495bSYour Name 	 * No match found for this flow id
734*5113495bSYour Name 	 */
735*5113495bSYour Name 	if (i == DP_PEER_AST_FLOWQ_MAX) {
736*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
737*5113495bSYour Name 				"%s: ast index not found for flow %d\n", __func__, flow_id);
738*5113495bSYour Name 		dp_peer_unref_delete(peer, DP_MOD_ID_AST);
739*5113495bSYour Name 		return -1;
740*5113495bSYour Name 	}
741*5113495bSYour Name 
742*5113495bSYour Name 	/* Check whether this ast entry is valid */
743*5113495bSYour Name 	if (!peer->peer_ast_flowq_idx[i].is_valid) {
744*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
745*5113495bSYour Name 				"%s: ast index is invalid for flow %d\n", __func__, flow_id);
746*5113495bSYour Name 		dp_peer_unref_delete(peer, DP_MOD_ID_AST);
747*5113495bSYour Name 		return -1;
748*5113495bSYour Name 	}
749*5113495bSYour Name 
750*5113495bSYour Name 	if (flow_id == DP_PEER_AST_FLOWQ_HI_PRIO ||
751*5113495bSYour Name 			flow_id == DP_PEER_AST_FLOWQ_LOW_PRIO) {
752*5113495bSYour Name 		/*
753*5113495bSYour Name 		 * check if this tid is valid for Hi
754*5113495bSYour Name 		 * and Low priority flow id
755*5113495bSYour Name 		 */
756*5113495bSYour Name 		if ((peer->peer_ast_flowq_idx[i].valid_tid_mask
757*5113495bSYour Name 					& (1 << tid))) {
758*5113495bSYour Name 			/* Release peer reference */
759*5113495bSYour Name 			ast_index = peer->peer_ast_flowq_idx[i].ast_idx;
760*5113495bSYour Name 			dp_peer_unref_delete(peer, DP_MOD_ID_AST);
761*5113495bSYour Name 			return ast_index;
762*5113495bSYour Name 		} else {
763*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
764*5113495bSYour Name 					"%s: TID %d is not valid for flow %d\n",
765*5113495bSYour Name 					__func__, tid, flow_id);
766*5113495bSYour Name 			/*
767*5113495bSYour Name 			 * TID is not valid for this flow
768*5113495bSYour Name 			 * Return -1
769*5113495bSYour Name 			 */
770*5113495bSYour Name 			dp_peer_unref_delete(peer, DP_MOD_ID_AST);
771*5113495bSYour Name 			return -1;
772*5113495bSYour Name 		}
773*5113495bSYour Name 	}
774*5113495bSYour Name 
775*5113495bSYour Name 	/*
776*5113495bSYour Name 	 * TID valid check not required for
777*5113495bSYour Name 	 * UDP/NON UDP flow id
778*5113495bSYour Name 	 */
779*5113495bSYour Name 	ast_index = peer->peer_ast_flowq_idx[i].ast_idx;
780*5113495bSYour Name 	dp_peer_unref_delete(peer, DP_MOD_ID_AST);
781*5113495bSYour Name 	return ast_index;
782*5113495bSYour Name }
783*5113495bSYour Name #endif
784*5113495bSYour Name 
dp_hmwds_ast_add_notify(struct dp_peer * peer,uint8_t * mac_addr,enum cdp_txrx_ast_entry_type type,QDF_STATUS err,bool is_peer_map)785*5113495bSYour Name void dp_hmwds_ast_add_notify(struct dp_peer *peer,
786*5113495bSYour Name 			     uint8_t *mac_addr,
787*5113495bSYour Name 			     enum cdp_txrx_ast_entry_type type,
788*5113495bSYour Name 			     QDF_STATUS err,
789*5113495bSYour Name 			     bool is_peer_map)
790*5113495bSYour Name {
791*5113495bSYour Name 	struct dp_vdev *dp_vdev = peer->vdev;
792*5113495bSYour Name 	struct dp_pdev *dp_pdev = dp_vdev->pdev;
793*5113495bSYour Name 	struct cdp_peer_hmwds_ast_add_status add_status;
794*5113495bSYour Name 
795*5113495bSYour Name 	/* Ignore ast types other than HM */
796*5113495bSYour Name 	if ((type != CDP_TXRX_AST_TYPE_WDS_HM) &&
797*5113495bSYour Name 	    (type != CDP_TXRX_AST_TYPE_WDS_HM_SEC))
798*5113495bSYour Name 		return;
799*5113495bSYour Name 
800*5113495bSYour Name 	/* existing ast delete in progress, will be attempted
801*5113495bSYour Name 	 * to add again after delete is complete. Send status then.
802*5113495bSYour Name 	 */
803*5113495bSYour Name 	if (err == QDF_STATUS_E_AGAIN)
804*5113495bSYour Name 		return;
805*5113495bSYour Name 
806*5113495bSYour Name 	/* peer map pending, notify actual status
807*5113495bSYour Name 	 * when peer map is received.
808*5113495bSYour Name 	 */
809*5113495bSYour Name 	if (!is_peer_map && (err == QDF_STATUS_SUCCESS))
810*5113495bSYour Name 		return;
811*5113495bSYour Name 
812*5113495bSYour Name 	qdf_mem_zero(&add_status, sizeof(add_status));
813*5113495bSYour Name 	add_status.vdev_id = dp_vdev->vdev_id;
814*5113495bSYour Name 	/* For type CDP_TXRX_AST_TYPE_WDS_HM_SEC dp_peer_add_ast()
815*5113495bSYour Name 	 * returns QDF_STATUS_E_FAILURE as it is host only entry.
816*5113495bSYour Name 	 * In such cases set err as success. Also err code set to
817*5113495bSYour Name 	 * QDF_STATUS_E_ALREADY indicates entry already exist in
818*5113495bSYour Name 	 * such cases set err as success too. Any other error code
819*5113495bSYour Name 	 * is actual error.
820*5113495bSYour Name 	 */
821*5113495bSYour Name 	if (((type == CDP_TXRX_AST_TYPE_WDS_HM_SEC) &&
822*5113495bSYour Name 	     (err == QDF_STATUS_E_FAILURE)) ||
823*5113495bSYour Name 	    (err == QDF_STATUS_E_ALREADY)) {
824*5113495bSYour Name 		err = QDF_STATUS_SUCCESS;
825*5113495bSYour Name 	}
826*5113495bSYour Name 	add_status.status = err;
827*5113495bSYour Name 	qdf_mem_copy(add_status.peer_mac, peer->mac_addr.raw,
828*5113495bSYour Name 		     QDF_MAC_ADDR_SIZE);
829*5113495bSYour Name 	qdf_mem_copy(add_status.ast_mac, mac_addr,
830*5113495bSYour Name 		     QDF_MAC_ADDR_SIZE);
831*5113495bSYour Name #ifdef WDI_EVENT_ENABLE
832*5113495bSYour Name 	dp_wdi_event_handler(WDI_EVENT_HMWDS_AST_ADD_STATUS, dp_pdev->soc,
833*5113495bSYour Name 			     (void *)&add_status, 0,
834*5113495bSYour Name 			     WDI_NO_VAL, dp_pdev->pdev_id);
835*5113495bSYour Name #endif
836*5113495bSYour Name }
837*5113495bSYour Name 
838*5113495bSYour Name #if defined(QCA_SUPPORT_LATENCY_CAPTURE) || \
839*5113495bSYour Name 	defined(QCA_TX_CAPTURE_SUPPORT) || \
840*5113495bSYour Name 	defined(QCA_MCOPY_SUPPORT)
841*5113495bSYour Name #ifdef FEATURE_PERPKT_INFO
842*5113495bSYour Name QDF_STATUS
dp_get_completion_indication_for_stack(struct dp_soc * soc,struct dp_pdev * pdev,struct dp_txrx_peer * txrx_peer,struct hal_tx_completion_status * ts,qdf_nbuf_t netbuf,uint64_t time_latency)843*5113495bSYour Name dp_get_completion_indication_for_stack(struct dp_soc *soc,
844*5113495bSYour Name 				       struct dp_pdev *pdev,
845*5113495bSYour Name 				       struct dp_txrx_peer *txrx_peer,
846*5113495bSYour Name 				       struct hal_tx_completion_status *ts,
847*5113495bSYour Name 				       qdf_nbuf_t netbuf,
848*5113495bSYour Name 				       uint64_t time_latency)
849*5113495bSYour Name {
850*5113495bSYour Name 	struct tx_capture_hdr *ppdu_hdr;
851*5113495bSYour Name 	uint16_t peer_id = ts->peer_id;
852*5113495bSYour Name 	uint32_t ppdu_id = ts->ppdu_id;
853*5113495bSYour Name 	uint8_t first_msdu = ts->first_msdu;
854*5113495bSYour Name 	uint8_t last_msdu = ts->last_msdu;
855*5113495bSYour Name 	uint32_t txcap_hdr_size = sizeof(struct tx_capture_hdr);
856*5113495bSYour Name 	struct dp_peer *peer;
857*5113495bSYour Name 
858*5113495bSYour Name 	if (qdf_unlikely(!dp_monitor_is_enable_tx_sniffer(pdev) &&
859*5113495bSYour Name 			 !dp_monitor_is_enable_mcopy_mode(pdev) &&
860*5113495bSYour Name 			 !pdev->latency_capture_enable))
861*5113495bSYour Name 		return QDF_STATUS_E_NOSUPPORT;
862*5113495bSYour Name 
863*5113495bSYour Name 	if (!txrx_peer) {
864*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
865*5113495bSYour Name 			  FL("txrx_peer is NULL"));
866*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
867*5113495bSYour Name 	}
868*5113495bSYour Name 
869*5113495bSYour Name 	/* If mcopy is enabled and mcopy_mode is M_COPY deliver 1st MSDU
870*5113495bSYour Name 	 * per PPDU. If mcopy_mode is M_COPY_EXTENDED deliver 1st MSDU
871*5113495bSYour Name 	 * for each MPDU
872*5113495bSYour Name 	 */
873*5113495bSYour Name 	if (dp_monitor_mcopy_check_deliver(pdev,
874*5113495bSYour Name 					   peer_id,
875*5113495bSYour Name 					   ppdu_id,
876*5113495bSYour Name 					   first_msdu) != QDF_STATUS_SUCCESS)
877*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
878*5113495bSYour Name 
879*5113495bSYour Name 	if (qdf_unlikely(qdf_nbuf_headroom(netbuf) < txcap_hdr_size)) {
880*5113495bSYour Name 		netbuf = qdf_nbuf_realloc_headroom(netbuf, txcap_hdr_size);
881*5113495bSYour Name 		if (!netbuf) {
882*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
883*5113495bSYour Name 				  FL("No headroom"));
884*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
885*5113495bSYour Name 		}
886*5113495bSYour Name 	}
887*5113495bSYour Name 
888*5113495bSYour Name 	if (!qdf_nbuf_push_head(netbuf, txcap_hdr_size)) {
889*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
890*5113495bSYour Name 			  FL("No headroom"));
891*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
892*5113495bSYour Name 	}
893*5113495bSYour Name 
894*5113495bSYour Name 	ppdu_hdr = (struct tx_capture_hdr *)qdf_nbuf_data(netbuf);
895*5113495bSYour Name 	qdf_mem_copy(ppdu_hdr->ta, txrx_peer->vdev->mac_addr.raw,
896*5113495bSYour Name 		     QDF_MAC_ADDR_SIZE);
897*5113495bSYour Name 
898*5113495bSYour Name 	peer = dp_peer_get_ref_by_id(soc, peer_id, DP_MOD_ID_TX_COMP);
899*5113495bSYour Name 	if (peer) {
900*5113495bSYour Name 		qdf_mem_copy(ppdu_hdr->ra, peer->mac_addr.raw,
901*5113495bSYour Name 			     QDF_MAC_ADDR_SIZE);
902*5113495bSYour Name 		dp_peer_unref_delete(peer, DP_MOD_ID_TX_COMP);
903*5113495bSYour Name 	}
904*5113495bSYour Name 	ppdu_hdr->ppdu_id = ppdu_id;
905*5113495bSYour Name 	ppdu_hdr->peer_id = peer_id;
906*5113495bSYour Name 	ppdu_hdr->first_msdu = first_msdu;
907*5113495bSYour Name 	ppdu_hdr->last_msdu = last_msdu;
908*5113495bSYour Name 	if (qdf_unlikely(pdev->latency_capture_enable)) {
909*5113495bSYour Name 		ppdu_hdr->tsf = ts->tsf;
910*5113495bSYour Name 		ppdu_hdr->time_latency = (uint32_t)time_latency;
911*5113495bSYour Name 	}
912*5113495bSYour Name 
913*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
914*5113495bSYour Name }
915*5113495bSYour Name 
dp_send_completion_to_stack(struct dp_soc * soc,struct dp_pdev * pdev,uint16_t peer_id,uint32_t ppdu_id,qdf_nbuf_t netbuf)916*5113495bSYour Name void dp_send_completion_to_stack(struct dp_soc *soc,  struct dp_pdev *pdev,
917*5113495bSYour Name 				 uint16_t peer_id, uint32_t ppdu_id,
918*5113495bSYour Name 				 qdf_nbuf_t netbuf)
919*5113495bSYour Name {
920*5113495bSYour Name 	dp_wdi_event_handler(WDI_EVENT_TX_DATA, soc,
921*5113495bSYour Name 			     netbuf, peer_id,
922*5113495bSYour Name 			     WDI_NO_VAL, pdev->pdev_id);
923*5113495bSYour Name }
924*5113495bSYour Name #endif
925*5113495bSYour Name #endif
926