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