xref: /wlan-driver/qcacld-3.0/core/dp/txrx/ol_tx_classify.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  *
4*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
5*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
6*5113495bSYour Name  * above copyright notice and this permission notice appear in all
7*5113495bSYour Name  * copies.
8*5113495bSYour Name  *
9*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
17*5113495bSYour Name  */
18*5113495bSYour Name 
19*5113495bSYour Name #include <qdf_nbuf.h>         /* qdf_nbuf_t, etc. */
20*5113495bSYour Name #include <htt.h>              /* HTT_TX_EXT_TID_MGMT */
21*5113495bSYour Name #include <ol_htt_tx_api.h>    /* htt_tx_desc_tid */
22*5113495bSYour Name #include <ol_txrx_api.h>      /* ol_txrx_vdev_handle */
23*5113495bSYour Name #include <ol_txrx_ctrl_api.h> /* ol_txrx_sync */
24*5113495bSYour Name #include <ol_txrx.h>
25*5113495bSYour Name #include <ol_txrx_internal.h> /* TXRX_ASSERT1 */
26*5113495bSYour Name #include <ol_txrx_types.h>    /* pdev stats */
27*5113495bSYour Name #include <ol_tx_desc.h>       /* ol_tx_desc */
28*5113495bSYour Name #include <ol_tx_send.h>       /* ol_tx_send */
29*5113495bSYour Name #include <ol_txrx_peer_find.h>
30*5113495bSYour Name #include <ol_tx_classify.h>
31*5113495bSYour Name #include <ol_tx_queue.h>
32*5113495bSYour Name #include <ipv4.h>
33*5113495bSYour Name #include <ipv6_defs.h>
34*5113495bSYour Name #include <ip_prot.h>
35*5113495bSYour Name #include <enet.h>             /* ETHERTYPE_VLAN, etc. */
36*5113495bSYour Name #include <cds_ieee80211_common.h>        /* ieee80211_frame */
37*5113495bSYour Name #include <cdp_txrx_handle.h>
38*5113495bSYour Name /*
39*5113495bSYour Name  * In theory, this tx classify code could be used on the host or in the target.
40*5113495bSYour Name  * Thus, this code uses generic OS primitives, that can be aliased to either
41*5113495bSYour Name  * the host's OS primitives or the target's OS primitives.
42*5113495bSYour Name  * For now, the following #defines set up these host-specific or
43*5113495bSYour Name  * target-specific aliases.
44*5113495bSYour Name  */
45*5113495bSYour Name 
46*5113495bSYour Name #define OL_TX_CLASSIFY_EXTENSION(vdev, tx_desc, netbuf, msdu_info, txq)
47*5113495bSYour Name #define OL_TX_CLASSIFY_MGMT_EXTENSION(vdev, tx_desc, netbuf, msdu_info, txq)
48*5113495bSYour Name 
49*5113495bSYour Name #ifdef QCA_TX_HTT2_SUPPORT
50*5113495bSYour Name static void
ol_tx_classify_htt2_frm(struct ol_txrx_vdev_t * vdev,qdf_nbuf_t tx_nbuf,struct ol_txrx_msdu_info_t * tx_msdu_info)51*5113495bSYour Name ol_tx_classify_htt2_frm(
52*5113495bSYour Name 	struct ol_txrx_vdev_t *vdev,
53*5113495bSYour Name 	qdf_nbuf_t tx_nbuf,
54*5113495bSYour Name 	struct ol_txrx_msdu_info_t *tx_msdu_info)
55*5113495bSYour Name {
56*5113495bSYour Name 	struct htt_msdu_info_t *htt = &tx_msdu_info->htt;
57*5113495bSYour Name 	A_UINT8 candi_frm = 0;
58*5113495bSYour Name 
59*5113495bSYour Name 	/*
60*5113495bSYour Name 	 * Offload the frame re-order to L3 protocol and ONLY support
61*5113495bSYour Name 	 * TCP protocol now.
62*5113495bSYour Name 	 */
63*5113495bSYour Name 	if ((htt->info.l2_hdr_type == htt_pkt_type_ethernet) &&
64*5113495bSYour Name 	    (htt->info.frame_type == htt_frm_type_data) &&
65*5113495bSYour Name 	    htt->info.is_unicast &&
66*5113495bSYour Name 	    (htt->info.ethertype == ETHERTYPE_IPV4)) {
67*5113495bSYour Name 		struct ipv4_hdr_t *ipHdr;
68*5113495bSYour Name 
69*5113495bSYour Name 		ipHdr = (struct ipv4_hdr_t *)(qdf_nbuf_data(tx_nbuf) +
70*5113495bSYour Name 			htt->info.l3_hdr_offset);
71*5113495bSYour Name 		if (ipHdr->protocol == IP_PROTOCOL_TCP)
72*5113495bSYour Name 			candi_frm = 1;
73*5113495bSYour Name 	}
74*5113495bSYour Name 
75*5113495bSYour Name 	qdf_nbuf_set_tx_parallel_dnload_frm(tx_nbuf, candi_frm);
76*5113495bSYour Name }
77*5113495bSYour Name 
78*5113495bSYour Name #define OL_TX_CLASSIFY_HTT2_EXTENSION(vdev, netbuf, msdu_info)      \
79*5113495bSYour Name 	ol_tx_classify_htt2_frm(vdev, netbuf, msdu_info)
80*5113495bSYour Name #else
81*5113495bSYour Name #define OL_TX_CLASSIFY_HTT2_EXTENSION(vdev, netbuf, msdu_info)      /* no-op */
82*5113495bSYour Name #endif /* QCA_TX_HTT2_SUPPORT */
83*5113495bSYour Name /* DHCP go with voice priority; WMM_AC_VO_TID1();*/
84*5113495bSYour Name #define TX_DHCP_TID  6
85*5113495bSYour Name 
86*5113495bSYour Name #if defined(QCA_BAD_PEER_TX_FLOW_CL)
87*5113495bSYour Name static inline A_BOOL
ol_if_tx_bad_peer_txq_overflow(struct ol_txrx_pdev_t * pdev,struct ol_txrx_peer_t * peer,struct ol_tx_frms_queue_t * txq)88*5113495bSYour Name ol_if_tx_bad_peer_txq_overflow(
89*5113495bSYour Name 	struct ol_txrx_pdev_t *pdev,
90*5113495bSYour Name 	struct ol_txrx_peer_t *peer,
91*5113495bSYour Name 	struct ol_tx_frms_queue_t *txq)
92*5113495bSYour Name {
93*5113495bSYour Name 	if (peer && pdev && txq && (peer->tx_limit_flag) &&
94*5113495bSYour Name 	    (txq->frms >= pdev->tx_peer_bal.peer_bal_txq_limit))
95*5113495bSYour Name 		return true;
96*5113495bSYour Name 	else
97*5113495bSYour Name 		return false;
98*5113495bSYour Name }
99*5113495bSYour Name #else
ol_if_tx_bad_peer_txq_overflow(struct ol_txrx_pdev_t * pdev,struct ol_txrx_peer_t * peer,struct ol_tx_frms_queue_t * txq)100*5113495bSYour Name static inline A_BOOL ol_if_tx_bad_peer_txq_overflow(
101*5113495bSYour Name 	struct ol_txrx_pdev_t *pdev,
102*5113495bSYour Name 	struct ol_txrx_peer_t *peer,
103*5113495bSYour Name 	struct ol_tx_frms_queue_t *txq)
104*5113495bSYour Name {
105*5113495bSYour Name 	return false;
106*5113495bSYour Name }
107*5113495bSYour Name #endif
108*5113495bSYour Name 
109*5113495bSYour Name /* EAPOL go with voice priority: WMM_AC_TO_TID1(WMM_AC_VO);*/
110*5113495bSYour Name #define TX_EAPOL_TID  6
111*5113495bSYour Name 
112*5113495bSYour Name /* ARP go with voice priority: WMM_AC_TO_TID1(pdev->arp_ac_override)*/
113*5113495bSYour Name #define TX_ARP_TID  6
114*5113495bSYour Name 
115*5113495bSYour Name /* For non-IP case, use default TID */
116*5113495bSYour Name #define TX_DEFAULT_TID  0
117*5113495bSYour Name 
118*5113495bSYour Name /*
119*5113495bSYour Name  * Determine IP TOS priority
120*5113495bSYour Name  * IP Tos format :
121*5113495bSYour Name  *        (Refer Pg 57 WMM-test-plan-v1.2)
122*5113495bSYour Name  * IP-TOS - 8bits
123*5113495bSYour Name  *            : DSCP(6-bits) ECN(2-bits)
124*5113495bSYour Name  *            : DSCP - P2 P1 P0 X X X
125*5113495bSYour Name  *                where (P2 P1 P0) form 802.1D
126*5113495bSYour Name  */
127*5113495bSYour Name static inline A_UINT8
ol_tx_tid_by_ipv4(A_UINT8 * pkt)128*5113495bSYour Name ol_tx_tid_by_ipv4(A_UINT8 *pkt)
129*5113495bSYour Name {
130*5113495bSYour Name 	A_UINT8 ipPri, tid;
131*5113495bSYour Name 	struct ipv4_hdr_t *ipHdr = (struct ipv4_hdr_t *)pkt;
132*5113495bSYour Name 
133*5113495bSYour Name 	ipPri = ipHdr->tos >> 5;
134*5113495bSYour Name 	tid = ipPri & 0x7;
135*5113495bSYour Name 
136*5113495bSYour Name 	return tid;
137*5113495bSYour Name }
138*5113495bSYour Name 
139*5113495bSYour Name static inline A_UINT8
ol_tx_tid_by_ipv6(A_UINT8 * pkt)140*5113495bSYour Name ol_tx_tid_by_ipv6(A_UINT8 *pkt)
141*5113495bSYour Name {
142*5113495bSYour Name 	return (ipv6_traffic_class((struct ipv6_hdr_t *)pkt) >> 5) & 0x7;
143*5113495bSYour Name }
144*5113495bSYour Name 
145*5113495bSYour Name static inline void
ol_tx_set_ether_type(A_UINT8 * datap,struct ol_txrx_msdu_info_t * tx_msdu_info)146*5113495bSYour Name ol_tx_set_ether_type(
147*5113495bSYour Name 	A_UINT8 *datap,
148*5113495bSYour Name 	struct ol_txrx_msdu_info_t *tx_msdu_info)
149*5113495bSYour Name {
150*5113495bSYour Name 	A_UINT16 typeorlength;
151*5113495bSYour Name 	A_UINT8 *ptr;
152*5113495bSYour Name 	A_UINT8 *l3_data_ptr;
153*5113495bSYour Name 
154*5113495bSYour Name 	if (tx_msdu_info->htt.info.l2_hdr_type == htt_pkt_type_raw) {
155*5113495bSYour Name 		/* adjust hdr_ptr to RA */
156*5113495bSYour Name 		struct ieee80211_frame *wh = (struct ieee80211_frame *)datap;
157*5113495bSYour Name 
158*5113495bSYour Name 		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
159*5113495bSYour Name 					IEEE80211_FC0_TYPE_DATA) {
160*5113495bSYour Name 			struct llc_snap_hdr_t *llc;
161*5113495bSYour Name 			/* dot11 encapsulated frame */
162*5113495bSYour Name 			struct ieee80211_qosframe *whqos =
163*5113495bSYour Name 					(struct ieee80211_qosframe *)datap;
164*5113495bSYour Name 			if (whqos->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS) {
165*5113495bSYour Name 				tx_msdu_info->htt.info.l3_hdr_offset =
166*5113495bSYour Name 					sizeof(struct ieee80211_qosframe);
167*5113495bSYour Name 			} else {
168*5113495bSYour Name 				tx_msdu_info->htt.info.l3_hdr_offset =
169*5113495bSYour Name 					sizeof(struct ieee80211_frame);
170*5113495bSYour Name 			}
171*5113495bSYour Name 			llc = (struct llc_snap_hdr_t *)
172*5113495bSYour Name 				(datap + tx_msdu_info->htt.info.l3_hdr_offset);
173*5113495bSYour Name 			tx_msdu_info->htt.info.ethertype =
174*5113495bSYour Name 				(llc->ethertype[0] << 8) | llc->ethertype[1];
175*5113495bSYour Name 			/*
176*5113495bSYour Name 			 * l3_hdr_offset refers to the end of the 802.3 or
177*5113495bSYour Name 			 * 802.11 header, which may be a LLC/SNAP header rather
178*5113495bSYour Name 			 * than the IP header.
179*5113495bSYour Name 			 * Thus, don't increment l3_hdr_offset += sizeof(*llc);
180*5113495bSYour Name 			 * rather,leave it as is.
181*5113495bSYour Name 			 */
182*5113495bSYour Name 		} else {
183*5113495bSYour Name 			/*
184*5113495bSYour Name 			 * This function should only be applied to data frames.
185*5113495bSYour Name 			 * For management frames, we already know to use
186*5113495bSYour Name 			 * HTT_TX_EXT_TID_MGMT.
187*5113495bSYour Name 			 */
188*5113495bSYour Name 			TXRX_ASSERT2(0);
189*5113495bSYour Name 		}
190*5113495bSYour Name 	} else if (tx_msdu_info->htt.info.l2_hdr_type ==
191*5113495bSYour Name 					htt_pkt_type_ethernet) {
192*5113495bSYour Name 		ptr = (datap + QDF_MAC_ADDR_SIZE * 2);
193*5113495bSYour Name 		typeorlength = (ptr[0] << 8) | ptr[1];
194*5113495bSYour Name 		/*ETHERNET_HDR_LEN;*/
195*5113495bSYour Name 		l3_data_ptr = datap + sizeof(struct ethernet_hdr_t);
196*5113495bSYour Name 
197*5113495bSYour Name 		if (typeorlength == ETHERTYPE_VLAN) {
198*5113495bSYour Name 			ptr = (datap + QDF_MAC_ADDR_SIZE * 2
199*5113495bSYour Name 					+ ETHERTYPE_VLAN_LEN);
200*5113495bSYour Name 			typeorlength = (ptr[0] << 8) | ptr[1];
201*5113495bSYour Name 			l3_data_ptr += ETHERTYPE_VLAN_LEN;
202*5113495bSYour Name 		}
203*5113495bSYour Name 
204*5113495bSYour Name 		if (!IS_ETHERTYPE(typeorlength)) {
205*5113495bSYour Name 			/* 802.3 header*/
206*5113495bSYour Name 			struct llc_snap_hdr_t *llc_hdr =
207*5113495bSYour Name 				(struct llc_snap_hdr_t *)l3_data_ptr;
208*5113495bSYour Name 			typeorlength = (llc_hdr->ethertype[0] << 8) |
209*5113495bSYour Name 							llc_hdr->ethertype[1];
210*5113495bSYour Name 			l3_data_ptr += sizeof(struct llc_snap_hdr_t);
211*5113495bSYour Name 		}
212*5113495bSYour Name 
213*5113495bSYour Name 		tx_msdu_info->htt.info.l3_hdr_offset = (A_UINT8)(l3_data_ptr -
214*5113495bSYour Name 									datap);
215*5113495bSYour Name 		tx_msdu_info->htt.info.ethertype = typeorlength;
216*5113495bSYour Name 	}
217*5113495bSYour Name }
218*5113495bSYour Name 
219*5113495bSYour Name static inline A_UINT8
ol_tx_tid_by_ether_type(A_UINT8 * datap,struct ol_txrx_msdu_info_t * tx_msdu_info)220*5113495bSYour Name ol_tx_tid_by_ether_type(
221*5113495bSYour Name 	A_UINT8 *datap,
222*5113495bSYour Name 	struct ol_txrx_msdu_info_t *tx_msdu_info)
223*5113495bSYour Name {
224*5113495bSYour Name 	A_UINT8 tid;
225*5113495bSYour Name 	A_UINT8 *l3_data_ptr;
226*5113495bSYour Name 	A_UINT16 typeorlength;
227*5113495bSYour Name 
228*5113495bSYour Name 	l3_data_ptr = datap + tx_msdu_info->htt.info.l3_hdr_offset;
229*5113495bSYour Name 	typeorlength = tx_msdu_info->htt.info.ethertype;
230*5113495bSYour Name 
231*5113495bSYour Name 	/* IP packet, do packet inspection for TID */
232*5113495bSYour Name 	if (typeorlength == ETHERTYPE_IPV4) {
233*5113495bSYour Name 		tid = ol_tx_tid_by_ipv4(l3_data_ptr);
234*5113495bSYour Name 	} else if (typeorlength == ETHERTYPE_IPV6) {
235*5113495bSYour Name 		tid = ol_tx_tid_by_ipv6(l3_data_ptr);
236*5113495bSYour Name 	} else if (ETHERTYPE_IS_EAPOL_WAPI(typeorlength)) {
237*5113495bSYour Name 		/* EAPOL go with voice priority*/
238*5113495bSYour Name 		tid = TX_EAPOL_TID;
239*5113495bSYour Name 	} else if (typeorlength == ETHERTYPE_ARP) {
240*5113495bSYour Name 		tid = TX_ARP_TID;
241*5113495bSYour Name 	} else {
242*5113495bSYour Name 		/* For non-IP case, use default TID */
243*5113495bSYour Name 		tid = TX_DEFAULT_TID;
244*5113495bSYour Name 	}
245*5113495bSYour Name 	return tid;
246*5113495bSYour Name }
247*5113495bSYour Name 
248*5113495bSYour Name static inline A_UINT8
ol_tx_tid_by_raw_type(A_UINT8 * datap,struct ol_txrx_msdu_info_t * tx_msdu_info)249*5113495bSYour Name ol_tx_tid_by_raw_type(
250*5113495bSYour Name 	A_UINT8 *datap,
251*5113495bSYour Name 	struct ol_txrx_msdu_info_t *tx_msdu_info)
252*5113495bSYour Name {
253*5113495bSYour Name 	A_UINT8 tid = HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST;
254*5113495bSYour Name 
255*5113495bSYour Name 	/* adjust hdr_ptr to RA */
256*5113495bSYour Name 	struct ieee80211_frame *wh = (struct ieee80211_frame *)datap;
257*5113495bSYour Name 
258*5113495bSYour Name 	/* FIXME: This code does not handle 4 address formats. The QOS field
259*5113495bSYour Name 	 * is not at usual location.
260*5113495bSYour Name 	 */
261*5113495bSYour Name 	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
262*5113495bSYour Name 					IEEE80211_FC0_TYPE_DATA) {
263*5113495bSYour Name 		/* dot11 encapsulated frame */
264*5113495bSYour Name 		struct ieee80211_qosframe *whqos =
265*5113495bSYour Name 					(struct ieee80211_qosframe *)datap;
266*5113495bSYour Name 		if (whqos->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS)
267*5113495bSYour Name 			tid = whqos->i_qos[0] & IEEE80211_QOS_TID;
268*5113495bSYour Name 		else
269*5113495bSYour Name 			tid = HTT_NON_QOS_TID;
270*5113495bSYour Name 	} else {
271*5113495bSYour Name 		/*
272*5113495bSYour Name 		 * This function should only be applied to data frames.
273*5113495bSYour Name 		 * For management frames, we already know to use
274*5113495bSYour Name 		 * HTT_TX_EXT_TID_MGMT.
275*5113495bSYour Name 		 */
276*5113495bSYour Name 		qdf_assert(0);
277*5113495bSYour Name 	}
278*5113495bSYour Name 	return tid;
279*5113495bSYour Name }
280*5113495bSYour Name 
281*5113495bSYour Name static A_UINT8
ol_tx_tid(struct ol_txrx_pdev_t * pdev,qdf_nbuf_t tx_nbuf,struct ol_txrx_msdu_info_t * tx_msdu_info)282*5113495bSYour Name ol_tx_tid(
283*5113495bSYour Name 	struct ol_txrx_pdev_t *pdev,
284*5113495bSYour Name 	qdf_nbuf_t tx_nbuf,
285*5113495bSYour Name 	struct ol_txrx_msdu_info_t *tx_msdu_info)
286*5113495bSYour Name {
287*5113495bSYour Name 	A_UINT8 *datap = qdf_nbuf_data(tx_nbuf);
288*5113495bSYour Name 	A_UINT8 tid;
289*5113495bSYour Name 
290*5113495bSYour Name 	if (pdev->frame_format == wlan_frm_fmt_raw) {
291*5113495bSYour Name 		tx_msdu_info->htt.info.l2_hdr_type = htt_pkt_type_raw;
292*5113495bSYour Name 
293*5113495bSYour Name 		ol_tx_set_ether_type(datap, tx_msdu_info);
294*5113495bSYour Name 		tid = tx_msdu_info->htt.info.ext_tid ==
295*5113495bSYour Name 					QDF_NBUF_TX_EXT_TID_INVALID ?
296*5113495bSYour Name 			ol_tx_tid_by_raw_type(datap, tx_msdu_info) :
297*5113495bSYour Name 			tx_msdu_info->htt.info.ext_tid;
298*5113495bSYour Name 	} else if (pdev->frame_format == wlan_frm_fmt_802_3) {
299*5113495bSYour Name 		tx_msdu_info->htt.info.l2_hdr_type = htt_pkt_type_ethernet;
300*5113495bSYour Name 
301*5113495bSYour Name 		ol_tx_set_ether_type(datap, tx_msdu_info);
302*5113495bSYour Name 		tid =
303*5113495bSYour Name 			tx_msdu_info->htt.info.ext_tid ==
304*5113495bSYour Name 					QDF_NBUF_TX_EXT_TID_INVALID ?
305*5113495bSYour Name 				ol_tx_tid_by_ether_type(datap, tx_msdu_info) :
306*5113495bSYour Name 				tx_msdu_info->htt.info.ext_tid;
307*5113495bSYour Name 	} else if (pdev->frame_format == wlan_frm_fmt_native_wifi) {
308*5113495bSYour Name 		struct llc_snap_hdr_t *llc;
309*5113495bSYour Name 
310*5113495bSYour Name 		tx_msdu_info->htt.info.l2_hdr_type = htt_pkt_type_native_wifi;
311*5113495bSYour Name 		tx_msdu_info->htt.info.l3_hdr_offset =
312*5113495bSYour Name 						sizeof(struct ieee80211_frame);
313*5113495bSYour Name 		llc = (struct llc_snap_hdr_t *)
314*5113495bSYour Name 			(datap + tx_msdu_info->htt.info.l3_hdr_offset);
315*5113495bSYour Name 		tx_msdu_info->htt.info.ethertype =
316*5113495bSYour Name 			(llc->ethertype[0] << 8) | llc->ethertype[1];
317*5113495bSYour Name 		/*
318*5113495bSYour Name 		 * Native WiFi is a special case of "raw" 802.11 header format.
319*5113495bSYour Name 		 * However, we expect that for all cases that use native WiFi,
320*5113495bSYour Name 		 * the TID will be directly specified out of band.
321*5113495bSYour Name 		 */
322*5113495bSYour Name 		tid = tx_msdu_info->htt.info.ext_tid;
323*5113495bSYour Name 	} else {
324*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_FATAL,
325*5113495bSYour Name 			  "Invalid standard frame type: %d\n",
326*5113495bSYour Name 			  pdev->frame_format);
327*5113495bSYour Name 		qdf_assert(0);
328*5113495bSYour Name 		tid = HTT_TX_EXT_TID_INVALID;
329*5113495bSYour Name 	}
330*5113495bSYour Name 	return tid;
331*5113495bSYour Name }
332*5113495bSYour Name 
333*5113495bSYour Name #if defined(FEATURE_WLAN_TDLS)
334*5113495bSYour Name static inline
ol_tx_tdls_peer_find(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,uint8_t * dest_addr,uint8_t * peer_id)335*5113495bSYour Name struct ol_txrx_peer_t *ol_tx_tdls_peer_find(struct ol_txrx_pdev_t *pdev,
336*5113495bSYour Name 						struct ol_txrx_vdev_t *vdev,
337*5113495bSYour Name 						uint8_t *dest_addr,
338*5113495bSYour Name 						uint8_t *peer_id)
339*5113495bSYour Name {
340*5113495bSYour Name 	struct ol_txrx_peer_t *peer = NULL;
341*5113495bSYour Name 	uint8_t zero_mac_addr[QDF_MAC_ADDR_SIZE] = { 0, 0, 0, 0, 0, 0 };
342*5113495bSYour Name 	enum peer_debug_id_type id_type = PEER_DEBUG_ID_OL_INTERNAL;
343*5113495bSYour Name 
344*5113495bSYour Name 	struct ol_txrx_peer_t *(*find_peer)(struct ol_txrx_pdev_t *pdev,
345*5113495bSYour Name 					    uint8_t *peer_mac_addr,
346*5113495bSYour Name 					    int mac_addr_is_aligned,
347*5113495bSYour Name 					    u8 check_valid,
348*5113495bSYour Name 					    enum peer_debug_id_type dbg_id)
349*5113495bSYour Name 		= ol_txrx_peer_find_hash_find_get_ref;
350*5113495bSYour Name 
351*5113495bSYour Name 	if (vdev->hlTdlsFlag) {
352*5113495bSYour Name 		peer = find_peer(pdev, vdev->hl_tdls_ap_mac_addr.raw,
353*5113495bSYour Name 				 0, 1, id_type);
354*5113495bSYour Name 
355*5113495bSYour Name 		if (peer && (peer->peer_ids[0] == HTT_INVALID_PEER_ID)) {
356*5113495bSYour Name 			ol_txrx_peer_release_ref(peer, id_type);
357*5113495bSYour Name 			peer = NULL;
358*5113495bSYour Name 		} else {
359*5113495bSYour Name 			if (peer) {
360*5113495bSYour Name 				*peer_id = peer->local_id;
361*5113495bSYour Name 				return peer;
362*5113495bSYour Name 			}
363*5113495bSYour Name 		}
364*5113495bSYour Name 	}
365*5113495bSYour Name 
366*5113495bSYour Name 	/* Packets destined to TDLS Peer or AP with 'No TDLS Link'.
367*5113495bSYour Name 	 * Optimized to directly get the peer based on 'dest_addr'
368*5113495bSYour Name 	 */
369*5113495bSYour Name 	if (vdev->last_real_peer &&
370*5113495bSYour Name 	    !qdf_mem_cmp(vdev->last_real_peer->mac_addr.raw,
371*5113495bSYour Name 			 dest_addr, QDF_MAC_ADDR_SIZE)) {
372*5113495bSYour Name 		ol_txrx_peer_get_ref(vdev->last_real_peer, id_type);
373*5113495bSYour Name 		*peer_id = vdev->last_real_peer->local_id;
374*5113495bSYour Name 		peer = vdev->last_real_peer;
375*5113495bSYour Name 	} else {
376*5113495bSYour Name 		/* packets destined for other peers or AP with TDLS Link */
377*5113495bSYour Name 		if (vdev->last_real_peer &&
378*5113495bSYour Name 		    !qdf_mem_cmp(vdev->hl_tdls_ap_mac_addr.raw,
379*5113495bSYour Name 				 zero_mac_addr,
380*5113495bSYour Name 				 QDF_MAC_ADDR_SIZE)) {
381*5113495bSYour Name 		/* With No TDLS Link return last_real_peer for both AP
382*5113495bSYour Name 		 * and other bss peer
383*5113495bSYour Name 		 */
384*5113495bSYour Name 			ol_txrx_peer_get_ref(vdev->last_real_peer, id_type);
385*5113495bSYour Name 			*peer_id = vdev->last_real_peer->local_id;
386*5113495bSYour Name 			peer = vdev->last_real_peer;
387*5113495bSYour Name 		} else { /* packet destined for other peers and AP when
388*5113495bSYour Name 			  * STA has TDLS link
389*5113495bSYour Name 			  */
390*5113495bSYour Name 			peer = find_peer(pdev, vdev->hl_tdls_ap_mac_addr.raw,
391*5113495bSYour Name 					 0, 1, id_type);
392*5113495bSYour Name 
393*5113495bSYour Name 			if (peer &&
394*5113495bSYour Name 			    (peer->peer_ids[0] == HTT_INVALID_PEER_ID)) {
395*5113495bSYour Name 				ol_txrx_peer_release_ref(peer, id_type);
396*5113495bSYour Name 				peer = NULL;
397*5113495bSYour Name 			} else {
398*5113495bSYour Name 				if (peer)
399*5113495bSYour Name 					*peer_id = peer->local_id;
400*5113495bSYour Name 			}
401*5113495bSYour Name 		}
402*5113495bSYour Name 	}
403*5113495bSYour Name 	return peer;
404*5113495bSYour Name }
405*5113495bSYour Name 
406*5113495bSYour Name #else
ol_tx_tdls_peer_find(struct ol_txrx_pdev_t * pdev,struct ol_txrx_vdev_t * vdev,uint8_t * dest_addr,uint8_t * peer_id)407*5113495bSYour Name static struct ol_txrx_peer_t *ol_tx_tdls_peer_find(struct ol_txrx_pdev_t *pdev,
408*5113495bSYour Name 						struct ol_txrx_vdev_t *vdev,
409*5113495bSYour Name 						uint8_t *dest_addr,
410*5113495bSYour Name 						uint8_t *peer_id)
411*5113495bSYour Name {
412*5113495bSYour Name 	struct ol_txrx_peer_t *peer = NULL;
413*5113495bSYour Name 
414*5113495bSYour Name 	peer = ol_txrx_assoc_peer_find(vdev);
415*5113495bSYour Name 
416*5113495bSYour Name 	return peer;
417*5113495bSYour Name }
418*5113495bSYour Name #endif
419*5113495bSYour Name 
420*5113495bSYour Name struct ol_tx_frms_queue_t *
ol_tx_classify(struct ol_txrx_vdev_t * vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t tx_nbuf,struct ol_txrx_msdu_info_t * tx_msdu_info)421*5113495bSYour Name ol_tx_classify(
422*5113495bSYour Name 	struct ol_txrx_vdev_t *vdev,
423*5113495bSYour Name 	struct ol_tx_desc_t *tx_desc,
424*5113495bSYour Name 	qdf_nbuf_t tx_nbuf,
425*5113495bSYour Name 	struct ol_txrx_msdu_info_t *tx_msdu_info)
426*5113495bSYour Name {
427*5113495bSYour Name 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
428*5113495bSYour Name 	struct ol_txrx_peer_t *peer = NULL;
429*5113495bSYour Name 	struct ol_tx_frms_queue_t *txq = NULL;
430*5113495bSYour Name 	A_UINT8 *dest_addr;
431*5113495bSYour Name 	A_UINT8 tid;
432*5113495bSYour Name 	u_int8_t peer_id;
433*5113495bSYour Name 
434*5113495bSYour Name 	TX_SCHED_DEBUG_PRINT("Enter");
435*5113495bSYour Name 	dest_addr = ol_tx_dest_addr_find(pdev, tx_nbuf);
436*5113495bSYour Name 	if (unlikely(!dest_addr)) {
437*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_TXRX,
438*5113495bSYour Name 				QDF_TRACE_LEVEL_ERROR,
439*5113495bSYour Name 				"Error: dest_addr is NULL.\n");
440*5113495bSYour Name 		return NULL; /*error*/
441*5113495bSYour Name 	}
442*5113495bSYour Name 	if ((IEEE80211_IS_MULTICAST(dest_addr)) ||
443*5113495bSYour Name 	    (vdev->opmode == wlan_op_mode_ocb)) {
444*5113495bSYour Name 		txq = &vdev->txqs[OL_TX_VDEV_MCAST_BCAST];
445*5113495bSYour Name 		tx_msdu_info->htt.info.ext_tid =
446*5113495bSYour Name 					HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST;
447*5113495bSYour Name 		if (vdev->opmode == wlan_op_mode_sta) {
448*5113495bSYour Name 			/*
449*5113495bSYour Name 			 * The STA sends a frame with a broadcast
450*5113495bSYour Name 			 * dest addr (DA) as a
451*5113495bSYour Name 			 * unicast frame to the AP's receive addr (RA).
452*5113495bSYour Name 			 * Find the peer object that represents the AP
453*5113495bSYour Name 			 * that the STA is associated with.
454*5113495bSYour Name 			 */
455*5113495bSYour Name 			peer = ol_txrx_assoc_peer_find(vdev);
456*5113495bSYour Name 			if (!peer) {
457*5113495bSYour Name 				QDF_TRACE(QDF_MODULE_ID_TXRX,
458*5113495bSYour Name 					  QDF_TRACE_LEVEL_ERROR,
459*5113495bSYour Name 					  "Error: STA %pK ("QDF_MAC_ADDR_FMT") trying to send bcast DA tx data frame w/o association\n",
460*5113495bSYour Name 					  vdev,
461*5113495bSYour Name 					  QDF_MAC_ADDR_REF(vdev->mac_addr.raw));
462*5113495bSYour Name 				return NULL; /* error */
463*5113495bSYour Name 			} else if ((peer->security[
464*5113495bSYour Name 				OL_TXRX_PEER_SECURITY_MULTICAST].sec_type
465*5113495bSYour Name 						!= htt_sec_type_wapi) &&
466*5113495bSYour Name 				   (qdf_nbuf_is_ipv4_pkt(tx_nbuf) == true)) {
467*5113495bSYour Name 				if (QDF_NBUF_CB_PACKET_TYPE_DHCP ==
468*5113495bSYour Name 						QDF_NBUF_CB_GET_PACKET_TYPE(
469*5113495bSYour Name 								tx_nbuf)) {
470*5113495bSYour Name 					/* DHCP frame to go with
471*5113495bSYour Name 					 * voice priority
472*5113495bSYour Name 					 */
473*5113495bSYour Name 					txq = &peer->txqs[TX_DHCP_TID];
474*5113495bSYour Name 					tx_msdu_info->htt.info.ext_tid =
475*5113495bSYour Name 								TX_DHCP_TID;
476*5113495bSYour Name 				}
477*5113495bSYour Name 			}
478*5113495bSYour Name 			/*
479*5113495bSYour Name 			 * The following line assumes each peer object has a
480*5113495bSYour Name 			 * single ID. This is currently true, and is expected
481*5113495bSYour Name 			 * to remain true.
482*5113495bSYour Name 			 */
483*5113495bSYour Name 			tx_msdu_info->htt.info.peer_id = peer->peer_ids[0];
484*5113495bSYour Name 		} else if (vdev->opmode == wlan_op_mode_ocb) {
485*5113495bSYour Name 			tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID;
486*5113495bSYour Name 			/*
487*5113495bSYour Name 			 * In OCB mode, don't worry about the peer.
488*5113495bSYour Name 			 * We don't need it.
489*5113495bSYour Name 			 */
490*5113495bSYour Name 			peer = NULL;
491*5113495bSYour Name 		} else {
492*5113495bSYour Name 			tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID;
493*5113495bSYour Name 			/*
494*5113495bSYour Name 			 * Look up the vdev's BSS peer, so that the
495*5113495bSYour Name 			 * classify_extension function can check whether to
496*5113495bSYour Name 			 * encrypt multicast / broadcast frames.
497*5113495bSYour Name 			 */
498*5113495bSYour Name 			peer = ol_txrx_peer_find_hash_find_get_ref
499*5113495bSYour Name 						(pdev,
500*5113495bSYour Name 						 vdev->mac_addr.raw,
501*5113495bSYour Name 						 0, 1,
502*5113495bSYour Name 						 PEER_DEBUG_ID_OL_INTERNAL);
503*5113495bSYour Name 			if (!peer) {
504*5113495bSYour Name 				QDF_TRACE(QDF_MODULE_ID_TXRX,
505*5113495bSYour Name 					  QDF_TRACE_LEVEL_ERROR,
506*5113495bSYour Name 					  "Error: vdev %pK ("QDF_MAC_ADDR_FMT") trying to send bcast/mcast, but no self-peer found\n",
507*5113495bSYour Name 					  vdev,
508*5113495bSYour Name 					  QDF_MAC_ADDR_REF(vdev->mac_addr.raw));
509*5113495bSYour Name 				return NULL; /* error */
510*5113495bSYour Name 			}
511*5113495bSYour Name 		}
512*5113495bSYour Name 		tx_msdu_info->htt.info.is_unicast = false;
513*5113495bSYour Name 	} else {
514*5113495bSYour Name 		/* tid would be overwritten for non QoS case*/
515*5113495bSYour Name 		tid = ol_tx_tid(pdev, tx_nbuf, tx_msdu_info);
516*5113495bSYour Name 		if ((HTT_TX_EXT_TID_INVALID == tid) ||
517*5113495bSYour Name 		    (tid >= OL_TX_NUM_TIDS)) {
518*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_TXRX,
519*5113495bSYour Name 				  QDF_TRACE_LEVEL_ERROR,
520*5113495bSYour Name 				  "%s Error: could not classify packet into valid TID(%d).\n",
521*5113495bSYour Name 				  __func__, tid);
522*5113495bSYour Name 			return NULL;
523*5113495bSYour Name 		}
524*5113495bSYour Name #ifdef ATH_SUPPORT_WAPI
525*5113495bSYour Name 		/* Check to see if a frame is a WAI frame */
526*5113495bSYour Name 		if (tx_msdu_info->htt.info.ethertype == ETHERTYPE_WAI) {
527*5113495bSYour Name 			/* WAI frames should not be encrypted */
528*5113495bSYour Name 			tx_msdu_info->htt.action.do_encrypt = 0;
529*5113495bSYour Name 			QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
530*5113495bSYour Name 				  "Tx Frame is a WAI frame\n");
531*5113495bSYour Name 		}
532*5113495bSYour Name #endif /* ATH_SUPPORT_WAPI */
533*5113495bSYour Name 
534*5113495bSYour Name 		/*
535*5113495bSYour Name 		 * Find the peer and increment its reference count.
536*5113495bSYour Name 		 * If this vdev is an AP, use the dest addr (DA) to determine
537*5113495bSYour Name 		 * which peer STA this unicast data frame is for.
538*5113495bSYour Name 		 * If this vdev is a STA, the unicast data frame is for the
539*5113495bSYour Name 		 * AP the STA is associated with.
540*5113495bSYour Name 		 */
541*5113495bSYour Name 		if (vdev->opmode == wlan_op_mode_sta) {
542*5113495bSYour Name 			/*
543*5113495bSYour Name 			 * TO DO:
544*5113495bSYour Name 			 * To support TDLS, first check if there is a TDLS
545*5113495bSYour Name 			 * peer STA,
546*5113495bSYour Name 			 * and if so, check if the DA matches the TDLS peer
547*5113495bSYour Name 			 * STA's MAC address. If there is no peer TDLS STA,
548*5113495bSYour Name 			 * or if the DA is not the TDLS STA's address,
549*5113495bSYour Name 			 * then the frame is either for the AP itself, or is
550*5113495bSYour Name 			 * supposed to be sent to the AP for forwarding.
551*5113495bSYour Name 			 */
552*5113495bSYour Name 			peer = ol_tx_tdls_peer_find(pdev, vdev,
553*5113495bSYour Name 						    dest_addr,
554*5113495bSYour Name 						    &peer_id);
555*5113495bSYour Name 		} else {
556*5113495bSYour Name 			peer = ol_txrx_peer_find_hash_find_get_ref(pdev,
557*5113495bSYour Name 								   dest_addr,
558*5113495bSYour Name 								   0, 1,
559*5113495bSYour Name 						PEER_DEBUG_ID_OL_INTERNAL);
560*5113495bSYour Name 		}
561*5113495bSYour Name 		tx_msdu_info->htt.info.is_unicast = true;
562*5113495bSYour Name 		if (!peer) {
563*5113495bSYour Name 			/*
564*5113495bSYour Name 			 * Unicast data xfer can only happen to an
565*5113495bSYour Name 			 * associated peer. It is illegitimate to send unicast
566*5113495bSYour Name 			 * data if there is no peer to send it to.
567*5113495bSYour Name 			 */
568*5113495bSYour Name 			ol_txrx_err_rl("Error: vdev %pK (" QDF_MAC_ADDR_FMT ") trying to send unicast tx data frame to an unknown peer",
569*5113495bSYour Name 				       vdev,
570*5113495bSYour Name 				       QDF_MAC_ADDR_REF(vdev->mac_addr.raw));
571*5113495bSYour Name 			return NULL; /* error */
572*5113495bSYour Name 		}
573*5113495bSYour Name 		TX_SCHED_DEBUG_PRINT("Peer found");
574*5113495bSYour Name 		if (!peer->qos_capable) {
575*5113495bSYour Name 			tid = OL_TX_NON_QOS_TID;
576*5113495bSYour Name 		} else if ((peer->security[
577*5113495bSYour Name 				OL_TXRX_PEER_SECURITY_UNICAST].sec_type
578*5113495bSYour Name 					!= htt_sec_type_wapi) &&
579*5113495bSYour Name 			   (qdf_nbuf_is_ipv4_pkt(tx_nbuf) == true)) {
580*5113495bSYour Name 			if (QDF_NBUF_CB_PACKET_TYPE_DHCP ==
581*5113495bSYour Name 					QDF_NBUF_CB_GET_PACKET_TYPE(tx_nbuf))
582*5113495bSYour Name 				/* DHCP frame to go with voice priority */
583*5113495bSYour Name 				tid = TX_DHCP_TID;
584*5113495bSYour Name 		}
585*5113495bSYour Name 
586*5113495bSYour Name 		/* Only allow encryption when in authenticated state */
587*5113495bSYour Name 		if (OL_TXRX_PEER_STATE_AUTH != peer->state)
588*5113495bSYour Name 			tx_msdu_info->htt.action.do_encrypt = 0;
589*5113495bSYour Name 
590*5113495bSYour Name 		txq = &peer->txqs[tid];
591*5113495bSYour Name 		tx_msdu_info->htt.info.ext_tid = tid;
592*5113495bSYour Name 		/*
593*5113495bSYour Name 		 * The following line assumes each peer object has a single ID.
594*5113495bSYour Name 		 * This is currently true, and is expected to remain true.
595*5113495bSYour Name 		 */
596*5113495bSYour Name 		tx_msdu_info->htt.info.peer_id = peer->peer_ids[0];
597*5113495bSYour Name 		/*
598*5113495bSYour Name 		 * WORKAROUND - check that the peer ID is valid.
599*5113495bSYour Name 		 * If tx data is provided before ol_rx_peer_map_handler is
600*5113495bSYour Name 		 * called to record the peer ID specified by the target,
601*5113495bSYour Name 		 * then we could end up here with an invalid peer ID.
602*5113495bSYour Name 		 * TO DO: rather than dropping the tx frame, pause the txq it
603*5113495bSYour Name 		 * goes into, then fill in the peer ID for the entries in the
604*5113495bSYour Name 		 * txq when the peer_map event provides the peer ID, and then
605*5113495bSYour Name 		 * unpause the txq.
606*5113495bSYour Name 		 */
607*5113495bSYour Name 		if (tx_msdu_info->htt.info.peer_id == HTT_INVALID_PEER_ID) {
608*5113495bSYour Name 			if (peer) {
609*5113495bSYour Name 				ol_txrx_info("remove the peer for invalid peer_id %pK",
610*5113495bSYour Name 					     peer);
611*5113495bSYour Name 				/* remove the peer reference added above */
612*5113495bSYour Name 				ol_txrx_peer_release_ref
613*5113495bSYour Name 						(peer,
614*5113495bSYour Name 						 PEER_DEBUG_ID_OL_INTERNAL);
615*5113495bSYour Name 				tx_msdu_info->peer = NULL;
616*5113495bSYour Name 			}
617*5113495bSYour Name 			return NULL;
618*5113495bSYour Name 		}
619*5113495bSYour Name 	}
620*5113495bSYour Name 	tx_msdu_info->peer = peer;
621*5113495bSYour Name 	if (ol_if_tx_bad_peer_txq_overflow(pdev, peer, txq))
622*5113495bSYour Name 		return NULL;
623*5113495bSYour Name 	/*
624*5113495bSYour Name 	 * If relevant, do a deeper inspection to determine additional
625*5113495bSYour Name 	 * characteristics of the tx frame.
626*5113495bSYour Name 	 * If the frame is invalid, then the txq will be set to NULL to
627*5113495bSYour Name 	 * indicate an error.
628*5113495bSYour Name 	 */
629*5113495bSYour Name 	OL_TX_CLASSIFY_EXTENSION(vdev, tx_desc, tx_nbuf, tx_msdu_info, txq);
630*5113495bSYour Name 	if (IEEE80211_IS_MULTICAST(dest_addr) && vdev->opmode !=
631*5113495bSYour Name 				wlan_op_mode_sta && tx_msdu_info->peer !=
632*5113495bSYour Name 								NULL) {
633*5113495bSYour Name 		ol_txrx_dbg("remove the peer reference %pK", peer);
634*5113495bSYour Name 		/* remove the peer reference added above */
635*5113495bSYour Name 		ol_txrx_peer_release_ref(tx_msdu_info->peer,
636*5113495bSYour Name 					 PEER_DEBUG_ID_OL_INTERNAL);
637*5113495bSYour Name 		/* Making peer NULL in case if multicast non STA mode */
638*5113495bSYour Name 		tx_msdu_info->peer = NULL;
639*5113495bSYour Name 	}
640*5113495bSYour Name 
641*5113495bSYour Name 	/* Whether this frame can download though HTT2 data pipe or not. */
642*5113495bSYour Name 	OL_TX_CLASSIFY_HTT2_EXTENSION(vdev, tx_nbuf, tx_msdu_info);
643*5113495bSYour Name 
644*5113495bSYour Name 	/* Update Tx Queue info */
645*5113495bSYour Name 	tx_desc->txq = txq;
646*5113495bSYour Name 
647*5113495bSYour Name 	TX_SCHED_DEBUG_PRINT("Leave");
648*5113495bSYour Name 	return txq;
649*5113495bSYour Name }
650*5113495bSYour Name 
651*5113495bSYour Name struct ol_tx_frms_queue_t *
ol_tx_classify_mgmt(struct ol_txrx_vdev_t * vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t tx_nbuf,struct ol_txrx_msdu_info_t * tx_msdu_info)652*5113495bSYour Name ol_tx_classify_mgmt(
653*5113495bSYour Name 	struct ol_txrx_vdev_t *vdev,
654*5113495bSYour Name 	struct ol_tx_desc_t *tx_desc,
655*5113495bSYour Name 	qdf_nbuf_t tx_nbuf,
656*5113495bSYour Name 	struct ol_txrx_msdu_info_t *tx_msdu_info)
657*5113495bSYour Name {
658*5113495bSYour Name 	struct ol_txrx_pdev_t *pdev = vdev->pdev;
659*5113495bSYour Name 	struct ol_txrx_peer_t *peer = NULL;
660*5113495bSYour Name 	struct ol_tx_frms_queue_t *txq = NULL;
661*5113495bSYour Name 	A_UINT8 *dest_addr;
662*5113495bSYour Name 	union ol_txrx_align_mac_addr_t local_mac_addr_aligned, *mac_addr;
663*5113495bSYour Name 
664*5113495bSYour Name 	TX_SCHED_DEBUG_PRINT("Enter");
665*5113495bSYour Name 	dest_addr = ol_tx_dest_addr_find(pdev, tx_nbuf);
666*5113495bSYour Name 	if (unlikely(!dest_addr)) {
667*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_TXRX,
668*5113495bSYour Name 				QDF_TRACE_LEVEL_ERROR,
669*5113495bSYour Name 				"Error: dest_addr is NULL.\n");
670*5113495bSYour Name 		return NULL; /*error*/
671*5113495bSYour Name 	}
672*5113495bSYour Name 	if (IEEE80211_IS_MULTICAST(dest_addr)) {
673*5113495bSYour Name 		/*
674*5113495bSYour Name 		 * AP:  beacons are broadcast,
675*5113495bSYour Name 		 *      public action frames (e.g. extended channel
676*5113495bSYour Name 		 *      switch announce) may be broadcast
677*5113495bSYour Name 		 * STA: probe requests can be either broadcast or unicast
678*5113495bSYour Name 		 */
679*5113495bSYour Name 		txq = &vdev->txqs[OL_TX_VDEV_DEFAULT_MGMT];
680*5113495bSYour Name 		tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID;
681*5113495bSYour Name 		tx_msdu_info->peer = NULL;
682*5113495bSYour Name 		tx_msdu_info->htt.info.is_unicast = 0;
683*5113495bSYour Name 	} else {
684*5113495bSYour Name 		/*
685*5113495bSYour Name 		 * Find the peer and increment its reference count.
686*5113495bSYour Name 		 * If this vdev is an AP, use the receiver addr (RA) to
687*5113495bSYour Name 		 * determine which peer STA this unicast mgmt frame is for.
688*5113495bSYour Name 		 * If this vdev is a STA, the unicast mgmt frame is for the
689*5113495bSYour Name 		 * AP the STA is associated with.
690*5113495bSYour Name 		 * Probe request / response and Assoc request / response are
691*5113495bSYour Name 		 * sent before the peer exists - in this case, use the
692*5113495bSYour Name 		 * vdev's default tx queue.
693*5113495bSYour Name 		 */
694*5113495bSYour Name 		if (vdev->opmode == wlan_op_mode_sta) {
695*5113495bSYour Name 			/*
696*5113495bSYour Name 			 * TO DO:
697*5113495bSYour Name 			 * To support TDLS, first check if there is a TDLS
698*5113495bSYour Name 			 * peer STA, and if so, check if the DA matches
699*5113495bSYour Name 			 * the TDLS peer STA's MAC address.
700*5113495bSYour Name 			 */
701*5113495bSYour Name 			peer = ol_txrx_assoc_peer_find(vdev);
702*5113495bSYour Name 			/*
703*5113495bSYour Name 			 * Some special case(preauth for example) needs to send
704*5113495bSYour Name 			 * unicast mgmt frame to unassociated AP. In such case,
705*5113495bSYour Name 			 * we need to check if dest addr match the associated
706*5113495bSYour Name 			 * peer addr. If not, we set peer as NULL to queue this
707*5113495bSYour Name 			 * frame to vdev queue.
708*5113495bSYour Name 			 */
709*5113495bSYour Name 			if (peer) {
710*5113495bSYour Name 
711*5113495bSYour Name 				qdf_mem_copy(
712*5113495bSYour Name 					&local_mac_addr_aligned.raw[0],
713*5113495bSYour Name 					dest_addr, QDF_MAC_ADDR_SIZE);
714*5113495bSYour Name 				mac_addr = &local_mac_addr_aligned;
715*5113495bSYour Name 				if (ol_txrx_peer_find_mac_addr_cmp
716*5113495bSYour Name 						(mac_addr,
717*5113495bSYour Name 						 &peer->mac_addr) != 0) {
718*5113495bSYour Name 					ol_txrx_peer_release_ref
719*5113495bSYour Name 						(peer,
720*5113495bSYour Name 						 PEER_DEBUG_ID_OL_INTERNAL);
721*5113495bSYour Name 					peer = NULL;
722*5113495bSYour Name 				}
723*5113495bSYour Name 			}
724*5113495bSYour Name 		} else {
725*5113495bSYour Name 			/* find the peer and increment its reference count */
726*5113495bSYour Name 			peer = ol_txrx_peer_find_hash_find_get_ref(pdev,
727*5113495bSYour Name 								   dest_addr,
728*5113495bSYour Name 								   0, 1,
729*5113495bSYour Name 						PEER_DEBUG_ID_OL_INTERNAL);
730*5113495bSYour Name 		}
731*5113495bSYour Name 		tx_msdu_info->peer = peer;
732*5113495bSYour Name 		if (!peer) {
733*5113495bSYour Name 			txq = &vdev->txqs[OL_TX_VDEV_DEFAULT_MGMT];
734*5113495bSYour Name 			tx_msdu_info->htt.info.peer_id = HTT_INVALID_PEER_ID;
735*5113495bSYour Name 		} else {
736*5113495bSYour Name 			txq = &peer->txqs[HTT_TX_EXT_TID_MGMT];
737*5113495bSYour Name 			tx_msdu_info->htt.info.ext_tid = HTT_TX_EXT_TID_MGMT;
738*5113495bSYour Name 			/*
739*5113495bSYour Name 			 * The following line assumes each peer object has a
740*5113495bSYour Name 			 * single ID. This is currently true, and is expected
741*5113495bSYour Name 			 * to remain true.
742*5113495bSYour Name 			 */
743*5113495bSYour Name 			tx_msdu_info->htt.info.peer_id = peer->peer_ids[0];
744*5113495bSYour Name 		}
745*5113495bSYour Name 		tx_msdu_info->htt.info.is_unicast = 1;
746*5113495bSYour Name 	}
747*5113495bSYour Name 	/*
748*5113495bSYour Name 	 * If relevant, do a deeper inspection to determine additional
749*5113495bSYour Name 	 * characteristics of the tx frame.
750*5113495bSYour Name 	 * If the frame is invalid, then the txq will be set to NULL to
751*5113495bSYour Name 	 * indicate an error.
752*5113495bSYour Name 	 */
753*5113495bSYour Name 	OL_TX_CLASSIFY_MGMT_EXTENSION(vdev, tx_desc, tx_nbuf,
754*5113495bSYour Name 				      tx_msdu_info, txq);
755*5113495bSYour Name 
756*5113495bSYour Name 	/* Whether this frame can download though HTT2 data pipe or not. */
757*5113495bSYour Name 	OL_TX_CLASSIFY_HTT2_EXTENSION(vdev, tx_nbuf, tx_msdu_info);
758*5113495bSYour Name 
759*5113495bSYour Name 	/* Update Tx Queue info */
760*5113495bSYour Name 	tx_desc->txq = txq;
761*5113495bSYour Name 
762*5113495bSYour Name 	TX_SCHED_DEBUG_PRINT("Leave");
763*5113495bSYour Name 	return txq;
764*5113495bSYour Name }
765*5113495bSYour Name 
766*5113495bSYour Name #ifdef currently_unused
767*5113495bSYour Name QDF_STATUS
ol_tx_classify_extension(struct ol_txrx_vdev_t * vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t tx_msdu,struct ol_txrx_msdu_info_t * msdu_info)768*5113495bSYour Name ol_tx_classify_extension(
769*5113495bSYour Name 	struct ol_txrx_vdev_t *vdev,
770*5113495bSYour Name 	struct ol_tx_desc_t *tx_desc,
771*5113495bSYour Name 	qdf_nbuf_t tx_msdu,
772*5113495bSYour Name 	struct ol_txrx_msdu_info_t *msdu_info)
773*5113495bSYour Name {
774*5113495bSYour Name 	u8 *datap = qdf_nbuf_data(tx_msdu);
775*5113495bSYour Name 	struct ol_txrx_peer_t *peer;
776*5113495bSYour Name 	int which_key;
777*5113495bSYour Name 
778*5113495bSYour Name 	/*
779*5113495bSYour Name 	 * The following msdu_info fields were already filled in by the
780*5113495bSYour Name 	 * ol_tx entry function or the regular ol_tx_classify function:
781*5113495bSYour Name 	 *     htt.info.vdev_id            (ol_tx_hl or ol_tx_non_std_hl)
782*5113495bSYour Name 	 *     htt.info.ext_tid            (ol_tx_non_std_hl or ol_tx_classify)
783*5113495bSYour Name 	 *     htt.info.frame_type         (ol_tx_hl or ol_tx_non_std_hl)
784*5113495bSYour Name 	 *     htt.info.l2_hdr_type        (ol_tx_hl or ol_tx_non_std_hl)
785*5113495bSYour Name 	 *     htt.info.is_unicast         (ol_tx_classify)
786*5113495bSYour Name 	 *     htt.info.peer_id            (ol_tx_classify)
787*5113495bSYour Name 	 *     peer                        (ol_tx_classify)
788*5113495bSYour Name 	 *     if (is_unicast) {
789*5113495bSYour Name 	 *         htt.info.ethertype      (ol_tx_classify)
790*5113495bSYour Name 	 *         htt.info.l3_hdr_offset  (ol_tx_classify)
791*5113495bSYour Name 	 *     }
792*5113495bSYour Name 	 * The following fields need to be filled in by this function:
793*5113495bSYour Name 	 *     if (!is_unicast) {
794*5113495bSYour Name 	 *         htt.info.ethertype
795*5113495bSYour Name 	 *         htt.info.l3_hdr_offset
796*5113495bSYour Name 	 *     }
797*5113495bSYour Name 	 *     htt.action.band (NOT CURRENTLY USED)
798*5113495bSYour Name 	 *     htt.action.do_encrypt
799*5113495bSYour Name 	 *     htt.action.do_tx_complete
800*5113495bSYour Name 	 * The following fields are not needed for data frames, and can
801*5113495bSYour Name 	 * be left uninitialized:
802*5113495bSYour Name 	 *     htt.info.frame_subtype
803*5113495bSYour Name 	 */
804*5113495bSYour Name 
805*5113495bSYour Name 	if (!msdu_info->htt.info.is_unicast) {
806*5113495bSYour Name 		int l2_hdr_size;
807*5113495bSYour Name 		u16 ethertype;
808*5113495bSYour Name 
809*5113495bSYour Name 		if (msdu_info->htt.info.l2_hdr_type == htt_pkt_type_ethernet) {
810*5113495bSYour Name 			struct ethernet_hdr_t *eh;
811*5113495bSYour Name 
812*5113495bSYour Name 			eh = (struct ethernet_hdr_t *)datap;
813*5113495bSYour Name 			l2_hdr_size = sizeof(*eh);
814*5113495bSYour Name 			ethertype = (eh->ethertype[0] << 8) | eh->ethertype[1];
815*5113495bSYour Name 
816*5113495bSYour Name 			if (ethertype == ETHERTYPE_VLAN) {
817*5113495bSYour Name 				struct ethernet_vlan_hdr_t *evh;
818*5113495bSYour Name 
819*5113495bSYour Name 				evh = (struct ethernet_vlan_hdr_t *)datap;
820*5113495bSYour Name 				l2_hdr_size = sizeof(*evh);
821*5113495bSYour Name 				ethertype = (evh->ethertype[0] << 8) |
822*5113495bSYour Name 							evh->ethertype[1];
823*5113495bSYour Name 			}
824*5113495bSYour Name 
825*5113495bSYour Name 			if (!IS_ETHERTYPE(ethertype)) {
826*5113495bSYour Name 				/* 802.3 header*/
827*5113495bSYour Name 				struct llc_snap_hdr_t *llc =
828*5113495bSYour Name 					(struct llc_snap_hdr_t *)(datap +
829*5113495bSYour Name 							l2_hdr_size);
830*5113495bSYour Name 				ethertype = (llc->ethertype[0] << 8) |
831*5113495bSYour Name 							llc->ethertype[1];
832*5113495bSYour Name 				l2_hdr_size += sizeof(*llc);
833*5113495bSYour Name 			}
834*5113495bSYour Name 			msdu_info->htt.info.l3_hdr_offset = l2_hdr_size;
835*5113495bSYour Name 			msdu_info->htt.info.ethertype = ethertype;
836*5113495bSYour Name 		} else { /* 802.11 */
837*5113495bSYour Name 			struct llc_snap_hdr_t *llc;
838*5113495bSYour Name 
839*5113495bSYour Name 			l2_hdr_size = ol_txrx_ieee80211_hdrsize(datap);
840*5113495bSYour Name 			llc = (struct llc_snap_hdr_t *)(datap + l2_hdr_size);
841*5113495bSYour Name 			ethertype = (llc->ethertype[0] << 8) |
842*5113495bSYour Name 							llc->ethertype[1];
843*5113495bSYour Name 			/*
844*5113495bSYour Name 			 * Don't include the LLC/SNAP header in l2_hdr_size,
845*5113495bSYour Name 			 * because l3_hdr_offset is actually supposed to refer
846*5113495bSYour Name 			 * to the header after the 802.3 or 802.11 header,
847*5113495bSYour Name 			 * which could be a LLC/SNAP header rather
848*5113495bSYour Name 			 * than the L3 header.
849*5113495bSYour Name 			 */
850*5113495bSYour Name 		}
851*5113495bSYour Name 		msdu_info->htt.info.l3_hdr_offset = l2_hdr_size;
852*5113495bSYour Name 		msdu_info->htt.info.ethertype = ethertype;
853*5113495bSYour Name 		which_key = txrx_sec_mcast;
854*5113495bSYour Name 	} else {
855*5113495bSYour Name 		which_key = txrx_sec_ucast;
856*5113495bSYour Name 	}
857*5113495bSYour Name 	peer = msdu_info->peer;
858*5113495bSYour Name 	/*
859*5113495bSYour Name 	 * msdu_info->htt.action.do_encrypt is initially set in ol_tx_desc_hl.
860*5113495bSYour Name 	 * Add more check here.
861*5113495bSYour Name 	 */
862*5113495bSYour Name 	msdu_info->htt.action.do_encrypt = (!peer) ? 0 :
863*5113495bSYour Name 		(peer->security[which_key].sec_type == htt_sec_type_none) ? 0 :
864*5113495bSYour Name 		msdu_info->htt.action.do_encrypt;
865*5113495bSYour Name 	/*
866*5113495bSYour Name 	 * For systems that have a frame by frame spec for whether to receive
867*5113495bSYour Name 	 * a tx completion notification, use the tx completion notification
868*5113495bSYour Name 	 * only  for certain management frames, not for data frames.
869*5113495bSYour Name 	 * (In the future, this may be changed slightly, e.g. to request a
870*5113495bSYour Name 	 * tx completion notification for the final EAPOL message sent by a
871*5113495bSYour Name 	 * STA during the key delivery handshake.)
872*5113495bSYour Name 	 */
873*5113495bSYour Name 	msdu_info->htt.action.do_tx_complete = 0;
874*5113495bSYour Name 
875*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
876*5113495bSYour Name }
877*5113495bSYour Name 
878*5113495bSYour Name QDF_STATUS
ol_tx_classify_mgmt_extension(struct ol_txrx_vdev_t * vdev,struct ol_tx_desc_t * tx_desc,qdf_nbuf_t tx_msdu,struct ol_txrx_msdu_info_t * msdu_info)879*5113495bSYour Name ol_tx_classify_mgmt_extension(
880*5113495bSYour Name 		struct ol_txrx_vdev_t *vdev,
881*5113495bSYour Name 		struct ol_tx_desc_t *tx_desc,
882*5113495bSYour Name 		qdf_nbuf_t tx_msdu,
883*5113495bSYour Name 		struct ol_txrx_msdu_info_t *msdu_info)
884*5113495bSYour Name {
885*5113495bSYour Name 	struct ieee80211_frame *wh;
886*5113495bSYour Name 
887*5113495bSYour Name 	/*
888*5113495bSYour Name 	 * The following msdu_info fields were already filled in by the
889*5113495bSYour Name 	 * ol_tx entry function or the regular ol_tx_classify_mgmt function:
890*5113495bSYour Name 	 *     htt.info.vdev_id          (ol_txrx_mgmt_send)
891*5113495bSYour Name 	 *     htt.info.frame_type       (ol_txrx_mgmt_send)
892*5113495bSYour Name 	 *     htt.info.l2_hdr_type      (ol_txrx_mgmt_send)
893*5113495bSYour Name 	 *     htt.action.do_tx_complete (ol_txrx_mgmt_send)
894*5113495bSYour Name 	 *     htt.info.peer_id          (ol_tx_classify_mgmt)
895*5113495bSYour Name 	 *     htt.info.ext_tid          (ol_tx_classify_mgmt)
896*5113495bSYour Name 	 *     htt.info.is_unicast       (ol_tx_classify_mgmt)
897*5113495bSYour Name 	 *     peer                      (ol_tx_classify_mgmt)
898*5113495bSYour Name 	 * The following fields need to be filled in by this function:
899*5113495bSYour Name 	 *     htt.info.frame_subtype
900*5113495bSYour Name 	 *     htt.info.l3_hdr_offset
901*5113495bSYour Name 	 *     htt.action.band (NOT CURRENTLY USED)
902*5113495bSYour Name 	 * The following fields are not needed for mgmt frames, and can
903*5113495bSYour Name 	 * be left uninitialized:
904*5113495bSYour Name 	 *     htt.info.ethertype
905*5113495bSYour Name 	 *     htt.action.do_encrypt
906*5113495bSYour Name 	 *         (This will be filled in by other SW, which knows whether
907*5113495bSYour Name 	 *         the peer has robust-management-frames enabled.)
908*5113495bSYour Name 	 */
909*5113495bSYour Name 	wh = (struct ieee80211_frame *)qdf_nbuf_data(tx_msdu);
910*5113495bSYour Name 	msdu_info->htt.info.frame_subtype =
911*5113495bSYour Name 		(wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
912*5113495bSYour Name 		IEEE80211_FC0_SUBTYPE_SHIFT;
913*5113495bSYour Name 	msdu_info->htt.info.l3_hdr_offset = sizeof(struct ieee80211_frame);
914*5113495bSYour Name 
915*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
916*5113495bSYour Name }
917*5113495bSYour Name #endif
918