1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright 2002-2005, Instant802 Networks, Inc.
4*4882a593Smuzhiyun * Copyright 2005-2006, Devicescape Software, Inc.
5*4882a593Smuzhiyun * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
6*4882a593Smuzhiyun * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net>
7*4882a593Smuzhiyun * Copyright 2013-2014 Intel Mobile Communications GmbH
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/export.h>
11*4882a593Smuzhiyun #include <linux/etherdevice.h>
12*4882a593Smuzhiyun #include <net/mac80211.h>
13*4882a593Smuzhiyun #include <asm/unaligned.h>
14*4882a593Smuzhiyun #include "ieee80211_i.h"
15*4882a593Smuzhiyun #include "rate.h"
16*4882a593Smuzhiyun #include "mesh.h"
17*4882a593Smuzhiyun #include "led.h"
18*4882a593Smuzhiyun #include "wme.h"
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun
ieee80211_tx_status_irqsafe(struct ieee80211_hw * hw,struct sk_buff * skb)21*4882a593Smuzhiyun void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
22*4882a593Smuzhiyun struct sk_buff *skb)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun struct ieee80211_local *local = hw_to_local(hw);
25*4882a593Smuzhiyun struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
26*4882a593Smuzhiyun int tmp;
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun skb->pkt_type = IEEE80211_TX_STATUS_MSG;
29*4882a593Smuzhiyun skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ?
30*4882a593Smuzhiyun &local->skb_queue : &local->skb_queue_unreliable, skb);
31*4882a593Smuzhiyun tmp = skb_queue_len(&local->skb_queue) +
32*4882a593Smuzhiyun skb_queue_len(&local->skb_queue_unreliable);
33*4882a593Smuzhiyun while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT &&
34*4882a593Smuzhiyun (skb = skb_dequeue(&local->skb_queue_unreliable))) {
35*4882a593Smuzhiyun ieee80211_free_txskb(hw, skb);
36*4882a593Smuzhiyun tmp--;
37*4882a593Smuzhiyun I802_DEBUG_INC(local->tx_status_drop);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun tasklet_schedule(&local->tasklet);
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun EXPORT_SYMBOL(ieee80211_tx_status_irqsafe);
42*4882a593Smuzhiyun
ieee80211_handle_filtered_frame(struct ieee80211_local * local,struct sta_info * sta,struct sk_buff * skb)43*4882a593Smuzhiyun static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
44*4882a593Smuzhiyun struct sta_info *sta,
45*4882a593Smuzhiyun struct sk_buff *skb)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
48*4882a593Smuzhiyun struct ieee80211_hdr *hdr = (void *)skb->data;
49*4882a593Smuzhiyun int ac;
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun if (info->flags & (IEEE80211_TX_CTL_NO_PS_BUFFER |
52*4882a593Smuzhiyun IEEE80211_TX_CTL_AMPDU |
53*4882a593Smuzhiyun IEEE80211_TX_CTL_HW_80211_ENCAP)) {
54*4882a593Smuzhiyun ieee80211_free_txskb(&local->hw, skb);
55*4882a593Smuzhiyun return;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /*
59*4882a593Smuzhiyun * This skb 'survived' a round-trip through the driver, and
60*4882a593Smuzhiyun * hopefully the driver didn't mangle it too badly. However,
61*4882a593Smuzhiyun * we can definitely not rely on the control information
62*4882a593Smuzhiyun * being correct. Clear it so we don't get junk there, and
63*4882a593Smuzhiyun * indicate that it needs new processing, but must not be
64*4882a593Smuzhiyun * modified/encrypted again.
65*4882a593Smuzhiyun */
66*4882a593Smuzhiyun memset(&info->control, 0, sizeof(info->control));
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun info->control.jiffies = jiffies;
69*4882a593Smuzhiyun info->control.vif = &sta->sdata->vif;
70*4882a593Smuzhiyun info->control.flags |= IEEE80211_TX_INTCFL_NEED_TXPROCESSING;
71*4882a593Smuzhiyun info->flags |= IEEE80211_TX_INTFL_RETRANSMISSION;
72*4882a593Smuzhiyun info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun sta->status_stats.filtered++;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /*
77*4882a593Smuzhiyun * Clear more-data bit on filtered frames, it might be set
78*4882a593Smuzhiyun * but later frames might time out so it might have to be
79*4882a593Smuzhiyun * clear again ... It's all rather unlikely (this frame
80*4882a593Smuzhiyun * should time out first, right?) but let's not confuse
81*4882a593Smuzhiyun * peers unnecessarily.
82*4882a593Smuzhiyun */
83*4882a593Smuzhiyun if (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREDATA))
84*4882a593Smuzhiyun hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun if (ieee80211_is_data_qos(hdr->frame_control)) {
87*4882a593Smuzhiyun u8 *p = ieee80211_get_qos_ctl(hdr);
88*4882a593Smuzhiyun int tid = *p & IEEE80211_QOS_CTL_TID_MASK;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /*
91*4882a593Smuzhiyun * Clear EOSP if set, this could happen e.g.
92*4882a593Smuzhiyun * if an absence period (us being a P2P GO)
93*4882a593Smuzhiyun * shortens the SP.
94*4882a593Smuzhiyun */
95*4882a593Smuzhiyun if (*p & IEEE80211_QOS_CTL_EOSP)
96*4882a593Smuzhiyun *p &= ~IEEE80211_QOS_CTL_EOSP;
97*4882a593Smuzhiyun ac = ieee80211_ac_from_tid(tid);
98*4882a593Smuzhiyun } else {
99*4882a593Smuzhiyun ac = IEEE80211_AC_BE;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun * Clear the TX filter mask for this STA when sending the next
104*4882a593Smuzhiyun * packet. If the STA went to power save mode, this will happen
105*4882a593Smuzhiyun * when it wakes up for the next time.
106*4882a593Smuzhiyun */
107*4882a593Smuzhiyun set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT);
108*4882a593Smuzhiyun ieee80211_clear_fast_xmit(sta);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /*
111*4882a593Smuzhiyun * This code races in the following way:
112*4882a593Smuzhiyun *
113*4882a593Smuzhiyun * (1) STA sends frame indicating it will go to sleep and does so
114*4882a593Smuzhiyun * (2) hardware/firmware adds STA to filter list, passes frame up
115*4882a593Smuzhiyun * (3) hardware/firmware processes TX fifo and suppresses a frame
116*4882a593Smuzhiyun * (4) we get TX status before having processed the frame and
117*4882a593Smuzhiyun * knowing that the STA has gone to sleep.
118*4882a593Smuzhiyun *
119*4882a593Smuzhiyun * This is actually quite unlikely even when both those events are
120*4882a593Smuzhiyun * processed from interrupts coming in quickly after one another or
121*4882a593Smuzhiyun * even at the same time because we queue both TX status events and
122*4882a593Smuzhiyun * RX frames to be processed by a tasklet and process them in the
123*4882a593Smuzhiyun * same order that they were received or TX status last. Hence, there
124*4882a593Smuzhiyun * is no race as long as the frame RX is processed before the next TX
125*4882a593Smuzhiyun * status, which drivers can ensure, see below.
126*4882a593Smuzhiyun *
127*4882a593Smuzhiyun * Note that this can only happen if the hardware or firmware can
128*4882a593Smuzhiyun * actually add STAs to the filter list, if this is done by the
129*4882a593Smuzhiyun * driver in response to set_tim() (which will only reduce the race
130*4882a593Smuzhiyun * this whole filtering tries to solve, not completely solve it)
131*4882a593Smuzhiyun * this situation cannot happen.
132*4882a593Smuzhiyun *
133*4882a593Smuzhiyun * To completely solve this race drivers need to make sure that they
134*4882a593Smuzhiyun * (a) don't mix the irq-safe/not irq-safe TX status/RX processing
135*4882a593Smuzhiyun * functions and
136*4882a593Smuzhiyun * (b) always process RX events before TX status events if ordering
137*4882a593Smuzhiyun * can be unknown, for example with different interrupt status
138*4882a593Smuzhiyun * bits.
139*4882a593Smuzhiyun * (c) if PS mode transitions are manual (i.e. the flag
140*4882a593Smuzhiyun * %IEEE80211_HW_AP_LINK_PS is set), always process PS state
141*4882a593Smuzhiyun * changes before calling TX status events if ordering can be
142*4882a593Smuzhiyun * unknown.
143*4882a593Smuzhiyun */
144*4882a593Smuzhiyun if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
145*4882a593Smuzhiyun skb_queue_len(&sta->tx_filtered[ac]) < STA_MAX_TX_BUFFER) {
146*4882a593Smuzhiyun skb_queue_tail(&sta->tx_filtered[ac], skb);
147*4882a593Smuzhiyun sta_info_recalc_tim(sta);
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun if (!timer_pending(&local->sta_cleanup))
150*4882a593Smuzhiyun mod_timer(&local->sta_cleanup,
151*4882a593Smuzhiyun round_jiffies(jiffies +
152*4882a593Smuzhiyun STA_INFO_CLEANUP_INTERVAL));
153*4882a593Smuzhiyun return;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
157*4882a593Smuzhiyun !(info->flags & IEEE80211_TX_INTFL_RETRIED)) {
158*4882a593Smuzhiyun /* Software retry the packet once */
159*4882a593Smuzhiyun info->flags |= IEEE80211_TX_INTFL_RETRIED;
160*4882a593Smuzhiyun ieee80211_add_pending_skb(local, skb);
161*4882a593Smuzhiyun return;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun ps_dbg_ratelimited(sta->sdata,
165*4882a593Smuzhiyun "dropped TX filtered frame, queue_len=%d PS=%d @%lu\n",
166*4882a593Smuzhiyun skb_queue_len(&sta->tx_filtered[ac]),
167*4882a593Smuzhiyun !!test_sta_flag(sta, WLAN_STA_PS_STA), jiffies);
168*4882a593Smuzhiyun ieee80211_free_txskb(&local->hw, skb);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
ieee80211_check_pending_bar(struct sta_info * sta,u8 * addr,u8 tid)171*4882a593Smuzhiyun static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun struct tid_ampdu_tx *tid_tx;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
176*4882a593Smuzhiyun if (!tid_tx || !tid_tx->bar_pending)
177*4882a593Smuzhiyun return;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun tid_tx->bar_pending = false;
180*4882a593Smuzhiyun ieee80211_send_bar(&sta->sdata->vif, addr, tid, tid_tx->failed_bar_ssn);
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
ieee80211_frame_acked(struct sta_info * sta,struct sk_buff * skb)183*4882a593Smuzhiyun static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun struct ieee80211_mgmt *mgmt = (void *) skb->data;
186*4882a593Smuzhiyun struct ieee80211_local *local = sta->local;
187*4882a593Smuzhiyun struct ieee80211_sub_if_data *sdata = sta->sdata;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (ieee80211_is_data_qos(mgmt->frame_control)) {
190*4882a593Smuzhiyun struct ieee80211_hdr *hdr = (void *) skb->data;
191*4882a593Smuzhiyun u8 *qc = ieee80211_get_qos_ctl(hdr);
192*4882a593Smuzhiyun u16 tid = qc[0] & 0xf;
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun ieee80211_check_pending_bar(sta, hdr->addr1, tid);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun if (ieee80211_is_action(mgmt->frame_control) &&
198*4882a593Smuzhiyun !ieee80211_has_protected(mgmt->frame_control) &&
199*4882a593Smuzhiyun mgmt->u.action.category == WLAN_CATEGORY_HT &&
200*4882a593Smuzhiyun mgmt->u.action.u.ht_smps.action == WLAN_HT_ACTION_SMPS &&
201*4882a593Smuzhiyun ieee80211_sdata_running(sdata)) {
202*4882a593Smuzhiyun enum ieee80211_smps_mode smps_mode;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun switch (mgmt->u.action.u.ht_smps.smps_control) {
205*4882a593Smuzhiyun case WLAN_HT_SMPS_CONTROL_DYNAMIC:
206*4882a593Smuzhiyun smps_mode = IEEE80211_SMPS_DYNAMIC;
207*4882a593Smuzhiyun break;
208*4882a593Smuzhiyun case WLAN_HT_SMPS_CONTROL_STATIC:
209*4882a593Smuzhiyun smps_mode = IEEE80211_SMPS_STATIC;
210*4882a593Smuzhiyun break;
211*4882a593Smuzhiyun case WLAN_HT_SMPS_CONTROL_DISABLED:
212*4882a593Smuzhiyun default: /* shouldn't happen since we don't send that */
213*4882a593Smuzhiyun smps_mode = IEEE80211_SMPS_OFF;
214*4882a593Smuzhiyun break;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun if (sdata->vif.type == NL80211_IFTYPE_STATION) {
218*4882a593Smuzhiyun /*
219*4882a593Smuzhiyun * This update looks racy, but isn't -- if we come
220*4882a593Smuzhiyun * here we've definitely got a station that we're
221*4882a593Smuzhiyun * talking to, and on a managed interface that can
222*4882a593Smuzhiyun * only be the AP. And the only other place updating
223*4882a593Smuzhiyun * this variable in managed mode is before association.
224*4882a593Smuzhiyun */
225*4882a593Smuzhiyun sdata->smps_mode = smps_mode;
226*4882a593Smuzhiyun ieee80211_queue_work(&local->hw, &sdata->recalc_smps);
227*4882a593Smuzhiyun } else if (sdata->vif.type == NL80211_IFTYPE_AP ||
228*4882a593Smuzhiyun sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
229*4882a593Smuzhiyun sta->known_smps_mode = smps_mode;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
ieee80211_set_bar_pending(struct sta_info * sta,u8 tid,u16 ssn)234*4882a593Smuzhiyun static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun struct tid_ampdu_tx *tid_tx;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
239*4882a593Smuzhiyun if (!tid_tx)
240*4882a593Smuzhiyun return;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun tid_tx->failed_bar_ssn = ssn;
243*4882a593Smuzhiyun tid_tx->bar_pending = true;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
ieee80211_tx_radiotap_len(struct ieee80211_tx_info * info,struct ieee80211_tx_status * status)246*4882a593Smuzhiyun static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info,
247*4882a593Smuzhiyun struct ieee80211_tx_status *status)
248*4882a593Smuzhiyun {
249*4882a593Smuzhiyun int len = sizeof(struct ieee80211_radiotap_header);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /* IEEE80211_RADIOTAP_RATE rate */
252*4882a593Smuzhiyun if (status && status->rate && !(status->rate->flags &
253*4882a593Smuzhiyun (RATE_INFO_FLAGS_MCS |
254*4882a593Smuzhiyun RATE_INFO_FLAGS_DMG |
255*4882a593Smuzhiyun RATE_INFO_FLAGS_EDMG |
256*4882a593Smuzhiyun RATE_INFO_FLAGS_VHT_MCS |
257*4882a593Smuzhiyun RATE_INFO_FLAGS_HE_MCS)))
258*4882a593Smuzhiyun len += 2;
259*4882a593Smuzhiyun else if (info->status.rates[0].idx >= 0 &&
260*4882a593Smuzhiyun !(info->status.rates[0].flags &
261*4882a593Smuzhiyun (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS)))
262*4882a593Smuzhiyun len += 2;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun /* IEEE80211_RADIOTAP_TX_FLAGS */
265*4882a593Smuzhiyun len += 2;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /* IEEE80211_RADIOTAP_DATA_RETRIES */
268*4882a593Smuzhiyun len += 1;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* IEEE80211_RADIOTAP_MCS
271*4882a593Smuzhiyun * IEEE80211_RADIOTAP_VHT */
272*4882a593Smuzhiyun if (status && status->rate) {
273*4882a593Smuzhiyun if (status->rate->flags & RATE_INFO_FLAGS_MCS)
274*4882a593Smuzhiyun len += 3;
275*4882a593Smuzhiyun else if (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS)
276*4882a593Smuzhiyun len = ALIGN(len, 2) + 12;
277*4882a593Smuzhiyun else if (status->rate->flags & RATE_INFO_FLAGS_HE_MCS)
278*4882a593Smuzhiyun len = ALIGN(len, 2) + 12;
279*4882a593Smuzhiyun } else if (info->status.rates[0].idx >= 0) {
280*4882a593Smuzhiyun if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS)
281*4882a593Smuzhiyun len += 3;
282*4882a593Smuzhiyun else if (info->status.rates[0].flags & IEEE80211_TX_RC_VHT_MCS)
283*4882a593Smuzhiyun len = ALIGN(len, 2) + 12;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun return len;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun static void
ieee80211_add_tx_radiotap_header(struct ieee80211_local * local,struct ieee80211_supported_band * sband,struct sk_buff * skb,int retry_count,int rtap_len,int shift,struct ieee80211_tx_status * status)290*4882a593Smuzhiyun ieee80211_add_tx_radiotap_header(struct ieee80211_local *local,
291*4882a593Smuzhiyun struct ieee80211_supported_band *sband,
292*4882a593Smuzhiyun struct sk_buff *skb, int retry_count,
293*4882a593Smuzhiyun int rtap_len, int shift,
294*4882a593Smuzhiyun struct ieee80211_tx_status *status)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
297*4882a593Smuzhiyun struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
298*4882a593Smuzhiyun struct ieee80211_radiotap_header *rthdr;
299*4882a593Smuzhiyun unsigned char *pos;
300*4882a593Smuzhiyun u16 legacy_rate = 0;
301*4882a593Smuzhiyun u16 txflags;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun rthdr = skb_push(skb, rtap_len);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun memset(rthdr, 0, rtap_len);
306*4882a593Smuzhiyun rthdr->it_len = cpu_to_le16(rtap_len);
307*4882a593Smuzhiyun rthdr->it_present =
308*4882a593Smuzhiyun cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) |
309*4882a593Smuzhiyun (1 << IEEE80211_RADIOTAP_DATA_RETRIES));
310*4882a593Smuzhiyun pos = (unsigned char *)(rthdr + 1);
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun /*
313*4882a593Smuzhiyun * XXX: Once radiotap gets the bitmap reset thing the vendor
314*4882a593Smuzhiyun * extensions proposal contains, we can actually report
315*4882a593Smuzhiyun * the whole set of tries we did.
316*4882a593Smuzhiyun */
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun /* IEEE80211_RADIOTAP_RATE */
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun if (status && status->rate) {
321*4882a593Smuzhiyun if (!(status->rate->flags & (RATE_INFO_FLAGS_MCS |
322*4882a593Smuzhiyun RATE_INFO_FLAGS_DMG |
323*4882a593Smuzhiyun RATE_INFO_FLAGS_EDMG |
324*4882a593Smuzhiyun RATE_INFO_FLAGS_VHT_MCS |
325*4882a593Smuzhiyun RATE_INFO_FLAGS_HE_MCS)))
326*4882a593Smuzhiyun legacy_rate = status->rate->legacy;
327*4882a593Smuzhiyun } else if (info->status.rates[0].idx >= 0 &&
328*4882a593Smuzhiyun !(info->status.rates[0].flags & (IEEE80211_TX_RC_MCS |
329*4882a593Smuzhiyun IEEE80211_TX_RC_VHT_MCS)))
330*4882a593Smuzhiyun legacy_rate =
331*4882a593Smuzhiyun sband->bitrates[info->status.rates[0].idx].bitrate;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun if (legacy_rate) {
334*4882a593Smuzhiyun rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
335*4882a593Smuzhiyun *pos = DIV_ROUND_UP(legacy_rate, 5 * (1 << shift));
336*4882a593Smuzhiyun /* padding for tx flags */
337*4882a593Smuzhiyun pos += 2;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun /* IEEE80211_RADIOTAP_TX_FLAGS */
341*4882a593Smuzhiyun txflags = 0;
342*4882a593Smuzhiyun if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
343*4882a593Smuzhiyun !is_multicast_ether_addr(hdr->addr1))
344*4882a593Smuzhiyun txflags |= IEEE80211_RADIOTAP_F_TX_FAIL;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
347*4882a593Smuzhiyun txflags |= IEEE80211_RADIOTAP_F_TX_CTS;
348*4882a593Smuzhiyun if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
349*4882a593Smuzhiyun txflags |= IEEE80211_RADIOTAP_F_TX_RTS;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun put_unaligned_le16(txflags, pos);
352*4882a593Smuzhiyun pos += 2;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun /* IEEE80211_RADIOTAP_DATA_RETRIES */
355*4882a593Smuzhiyun /* for now report the total retry_count */
356*4882a593Smuzhiyun *pos = retry_count;
357*4882a593Smuzhiyun pos++;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun if (status && status->rate &&
360*4882a593Smuzhiyun (status->rate->flags & RATE_INFO_FLAGS_MCS)) {
361*4882a593Smuzhiyun rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
362*4882a593Smuzhiyun pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
363*4882a593Smuzhiyun IEEE80211_RADIOTAP_MCS_HAVE_GI |
364*4882a593Smuzhiyun IEEE80211_RADIOTAP_MCS_HAVE_BW;
365*4882a593Smuzhiyun if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI)
366*4882a593Smuzhiyun pos[1] |= IEEE80211_RADIOTAP_MCS_SGI;
367*4882a593Smuzhiyun if (status->rate->bw == RATE_INFO_BW_40)
368*4882a593Smuzhiyun pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40;
369*4882a593Smuzhiyun pos[2] = status->rate->mcs;
370*4882a593Smuzhiyun pos += 3;
371*4882a593Smuzhiyun } else if (status && status->rate &&
372*4882a593Smuzhiyun (status->rate->flags & RATE_INFO_FLAGS_VHT_MCS)) {
373*4882a593Smuzhiyun u16 known = local->hw.radiotap_vht_details &
374*4882a593Smuzhiyun (IEEE80211_RADIOTAP_VHT_KNOWN_GI |
375*4882a593Smuzhiyun IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun /* required alignment from rthdr */
380*4882a593Smuzhiyun pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun /* u16 known - IEEE80211_RADIOTAP_VHT_KNOWN_* */
383*4882a593Smuzhiyun put_unaligned_le16(known, pos);
384*4882a593Smuzhiyun pos += 2;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun /* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */
387*4882a593Smuzhiyun if (status->rate->flags & RATE_INFO_FLAGS_SHORT_GI)
388*4882a593Smuzhiyun *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
389*4882a593Smuzhiyun pos++;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* u8 bandwidth */
392*4882a593Smuzhiyun switch (status->rate->bw) {
393*4882a593Smuzhiyun case RATE_INFO_BW_160:
394*4882a593Smuzhiyun *pos = 11;
395*4882a593Smuzhiyun break;
396*4882a593Smuzhiyun case RATE_INFO_BW_80:
397*4882a593Smuzhiyun *pos = 4;
398*4882a593Smuzhiyun break;
399*4882a593Smuzhiyun case RATE_INFO_BW_40:
400*4882a593Smuzhiyun *pos = 1;
401*4882a593Smuzhiyun break;
402*4882a593Smuzhiyun default:
403*4882a593Smuzhiyun *pos = 0;
404*4882a593Smuzhiyun break;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun pos++;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun /* u8 mcs_nss[4] */
409*4882a593Smuzhiyun *pos = (status->rate->mcs << 4) | status->rate->nss;
410*4882a593Smuzhiyun pos += 4;
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* u8 coding */
413*4882a593Smuzhiyun pos++;
414*4882a593Smuzhiyun /* u8 group_id */
415*4882a593Smuzhiyun pos++;
416*4882a593Smuzhiyun /* u16 partial_aid */
417*4882a593Smuzhiyun pos += 2;
418*4882a593Smuzhiyun } else if (status && status->rate &&
419*4882a593Smuzhiyun (status->rate->flags & RATE_INFO_FLAGS_HE_MCS)) {
420*4882a593Smuzhiyun struct ieee80211_radiotap_he *he;
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_HE);
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun /* required alignment from rthdr */
425*4882a593Smuzhiyun pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
426*4882a593Smuzhiyun he = (struct ieee80211_radiotap_he *)pos;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun he->data1 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA1_FORMAT_SU |
429*4882a593Smuzhiyun IEEE80211_RADIOTAP_HE_DATA1_DATA_MCS_KNOWN |
430*4882a593Smuzhiyun IEEE80211_RADIOTAP_HE_DATA1_DATA_DCM_KNOWN |
431*4882a593Smuzhiyun IEEE80211_RADIOTAP_HE_DATA1_BW_RU_ALLOC_KNOWN);
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun he->data2 = cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA2_GI_KNOWN);
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun #define HE_PREP(f, val) le16_encode_bits(val, IEEE80211_RADIOTAP_HE_##f)
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun he->data6 |= HE_PREP(DATA6_NSTS, status->rate->nss);
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun #define CHECK_GI(s) \
440*4882a593Smuzhiyun BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA5_GI_##s != \
441*4882a593Smuzhiyun (int)NL80211_RATE_INFO_HE_GI_##s)
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun CHECK_GI(0_8);
444*4882a593Smuzhiyun CHECK_GI(1_6);
445*4882a593Smuzhiyun CHECK_GI(3_2);
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun he->data3 |= HE_PREP(DATA3_DATA_MCS, status->rate->mcs);
448*4882a593Smuzhiyun he->data3 |= HE_PREP(DATA3_DATA_DCM, status->rate->he_dcm);
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun he->data5 |= HE_PREP(DATA5_GI, status->rate->he_gi);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun switch (status->rate->bw) {
453*4882a593Smuzhiyun case RATE_INFO_BW_20:
454*4882a593Smuzhiyun he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC,
455*4882a593Smuzhiyun IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_20MHZ);
456*4882a593Smuzhiyun break;
457*4882a593Smuzhiyun case RATE_INFO_BW_40:
458*4882a593Smuzhiyun he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC,
459*4882a593Smuzhiyun IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_40MHZ);
460*4882a593Smuzhiyun break;
461*4882a593Smuzhiyun case RATE_INFO_BW_80:
462*4882a593Smuzhiyun he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC,
463*4882a593Smuzhiyun IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_80MHZ);
464*4882a593Smuzhiyun break;
465*4882a593Smuzhiyun case RATE_INFO_BW_160:
466*4882a593Smuzhiyun he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC,
467*4882a593Smuzhiyun IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_160MHZ);
468*4882a593Smuzhiyun break;
469*4882a593Smuzhiyun case RATE_INFO_BW_HE_RU:
470*4882a593Smuzhiyun #define CHECK_RU_ALLOC(s) \
471*4882a593Smuzhiyun BUILD_BUG_ON(IEEE80211_RADIOTAP_HE_DATA5_DATA_BW_RU_ALLOC_##s##T != \
472*4882a593Smuzhiyun NL80211_RATE_INFO_HE_RU_ALLOC_##s + 4)
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun CHECK_RU_ALLOC(26);
475*4882a593Smuzhiyun CHECK_RU_ALLOC(52);
476*4882a593Smuzhiyun CHECK_RU_ALLOC(106);
477*4882a593Smuzhiyun CHECK_RU_ALLOC(242);
478*4882a593Smuzhiyun CHECK_RU_ALLOC(484);
479*4882a593Smuzhiyun CHECK_RU_ALLOC(996);
480*4882a593Smuzhiyun CHECK_RU_ALLOC(2x996);
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun he->data5 |= HE_PREP(DATA5_DATA_BW_RU_ALLOC,
483*4882a593Smuzhiyun status->rate->he_ru_alloc + 4);
484*4882a593Smuzhiyun break;
485*4882a593Smuzhiyun default:
486*4882a593Smuzhiyun WARN_ONCE(1, "Invalid SU BW %d\n", status->rate->bw);
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun pos += sizeof(struct ieee80211_radiotap_he);
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun if ((status && status->rate) || info->status.rates[0].idx < 0)
493*4882a593Smuzhiyun return;
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun /* IEEE80211_RADIOTAP_MCS
496*4882a593Smuzhiyun * IEEE80211_RADIOTAP_VHT */
497*4882a593Smuzhiyun if (info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
498*4882a593Smuzhiyun rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
499*4882a593Smuzhiyun pos[0] = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
500*4882a593Smuzhiyun IEEE80211_RADIOTAP_MCS_HAVE_GI |
501*4882a593Smuzhiyun IEEE80211_RADIOTAP_MCS_HAVE_BW;
502*4882a593Smuzhiyun if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
503*4882a593Smuzhiyun pos[1] |= IEEE80211_RADIOTAP_MCS_SGI;
504*4882a593Smuzhiyun if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
505*4882a593Smuzhiyun pos[1] |= IEEE80211_RADIOTAP_MCS_BW_40;
506*4882a593Smuzhiyun if (info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)
507*4882a593Smuzhiyun pos[1] |= IEEE80211_RADIOTAP_MCS_FMT_GF;
508*4882a593Smuzhiyun pos[2] = info->status.rates[0].idx;
509*4882a593Smuzhiyun pos += 3;
510*4882a593Smuzhiyun } else if (info->status.rates[0].flags & IEEE80211_TX_RC_VHT_MCS) {
511*4882a593Smuzhiyun u16 known = local->hw.radiotap_vht_details &
512*4882a593Smuzhiyun (IEEE80211_RADIOTAP_VHT_KNOWN_GI |
513*4882a593Smuzhiyun IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH);
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun /* required alignment from rthdr */
518*4882a593Smuzhiyun pos = (u8 *)rthdr + ALIGN(pos - (u8 *)rthdr, 2);
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun /* u16 known - IEEE80211_RADIOTAP_VHT_KNOWN_* */
521*4882a593Smuzhiyun put_unaligned_le16(known, pos);
522*4882a593Smuzhiyun pos += 2;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun /* u8 flags - IEEE80211_RADIOTAP_VHT_FLAG_* */
525*4882a593Smuzhiyun if (info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
526*4882a593Smuzhiyun *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
527*4882a593Smuzhiyun pos++;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /* u8 bandwidth */
530*4882a593Smuzhiyun if (info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
531*4882a593Smuzhiyun *pos = 1;
532*4882a593Smuzhiyun else if (info->status.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
533*4882a593Smuzhiyun *pos = 4;
534*4882a593Smuzhiyun else if (info->status.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
535*4882a593Smuzhiyun *pos = 11;
536*4882a593Smuzhiyun else /* IEEE80211_TX_RC_{20_MHZ_WIDTH,FIXME:DUP_DATA} */
537*4882a593Smuzhiyun *pos = 0;
538*4882a593Smuzhiyun pos++;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun /* u8 mcs_nss[4] */
541*4882a593Smuzhiyun *pos = (ieee80211_rate_get_vht_mcs(&info->status.rates[0]) << 4) |
542*4882a593Smuzhiyun ieee80211_rate_get_vht_nss(&info->status.rates[0]);
543*4882a593Smuzhiyun pos += 4;
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun /* u8 coding */
546*4882a593Smuzhiyun pos++;
547*4882a593Smuzhiyun /* u8 group_id */
548*4882a593Smuzhiyun pos++;
549*4882a593Smuzhiyun /* u16 partial_aid */
550*4882a593Smuzhiyun pos += 2;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /*
555*4882a593Smuzhiyun * Handles the tx for TDLS teardown frames.
556*4882a593Smuzhiyun * If the frame wasn't ACKed by the peer - it will be re-sent through the AP
557*4882a593Smuzhiyun */
ieee80211_tdls_td_tx_handle(struct ieee80211_local * local,struct ieee80211_sub_if_data * sdata,struct sk_buff * skb,u32 flags)558*4882a593Smuzhiyun static void ieee80211_tdls_td_tx_handle(struct ieee80211_local *local,
559*4882a593Smuzhiyun struct ieee80211_sub_if_data *sdata,
560*4882a593Smuzhiyun struct sk_buff *skb, u32 flags)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun struct sk_buff *teardown_skb;
563*4882a593Smuzhiyun struct sk_buff *orig_teardown_skb;
564*4882a593Smuzhiyun bool is_teardown = false;
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun /* Get the teardown data we need and free the lock */
567*4882a593Smuzhiyun spin_lock(&sdata->u.mgd.teardown_lock);
568*4882a593Smuzhiyun teardown_skb = sdata->u.mgd.teardown_skb;
569*4882a593Smuzhiyun orig_teardown_skb = sdata->u.mgd.orig_teardown_skb;
570*4882a593Smuzhiyun if ((skb == orig_teardown_skb) && teardown_skb) {
571*4882a593Smuzhiyun sdata->u.mgd.teardown_skb = NULL;
572*4882a593Smuzhiyun sdata->u.mgd.orig_teardown_skb = NULL;
573*4882a593Smuzhiyun is_teardown = true;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun spin_unlock(&sdata->u.mgd.teardown_lock);
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun if (is_teardown) {
578*4882a593Smuzhiyun /* This mechanism relies on being able to get ACKs */
579*4882a593Smuzhiyun WARN_ON(!ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS));
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun /* Check if peer has ACKed */
582*4882a593Smuzhiyun if (flags & IEEE80211_TX_STAT_ACK) {
583*4882a593Smuzhiyun dev_kfree_skb_any(teardown_skb);
584*4882a593Smuzhiyun } else {
585*4882a593Smuzhiyun tdls_dbg(sdata,
586*4882a593Smuzhiyun "TDLS Resending teardown through AP\n");
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun ieee80211_subif_start_xmit(teardown_skb, skb->dev);
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun }
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun static struct ieee80211_sub_if_data *
ieee80211_sdata_from_skb(struct ieee80211_local * local,struct sk_buff * skb)594*4882a593Smuzhiyun ieee80211_sdata_from_skb(struct ieee80211_local *local, struct sk_buff *skb)
595*4882a593Smuzhiyun {
596*4882a593Smuzhiyun struct ieee80211_sub_if_data *sdata;
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun if (skb->dev) {
599*4882a593Smuzhiyun list_for_each_entry_rcu(sdata, &local->interfaces, list) {
600*4882a593Smuzhiyun if (!sdata->dev)
601*4882a593Smuzhiyun continue;
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun if (skb->dev == sdata->dev)
604*4882a593Smuzhiyun return sdata;
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun return NULL;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun return rcu_dereference(local->p2p_sdata);
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun
ieee80211_report_ack_skb(struct ieee80211_local * local,struct ieee80211_tx_info * info,bool acked,bool dropped)613*4882a593Smuzhiyun static void ieee80211_report_ack_skb(struct ieee80211_local *local,
614*4882a593Smuzhiyun struct ieee80211_tx_info *info,
615*4882a593Smuzhiyun bool acked, bool dropped)
616*4882a593Smuzhiyun {
617*4882a593Smuzhiyun struct sk_buff *skb;
618*4882a593Smuzhiyun unsigned long flags;
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun spin_lock_irqsave(&local->ack_status_lock, flags);
621*4882a593Smuzhiyun skb = idr_remove(&local->ack_status_frames, info->ack_frame_id);
622*4882a593Smuzhiyun spin_unlock_irqrestore(&local->ack_status_lock, flags);
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun if (!skb)
625*4882a593Smuzhiyun return;
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
628*4882a593Smuzhiyun u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie;
629*4882a593Smuzhiyun struct ieee80211_sub_if_data *sdata;
630*4882a593Smuzhiyun struct ieee80211_hdr *hdr = (void *)skb->data;
631*4882a593Smuzhiyun __be16 ethertype = 0;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun if (skb->len >= ETH_HLEN && skb->protocol == cpu_to_be16(ETH_P_802_3))
634*4882a593Smuzhiyun skb_copy_bits(skb, 2 * ETH_ALEN, ðertype, ETH_TLEN);
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun rcu_read_lock();
637*4882a593Smuzhiyun sdata = ieee80211_sdata_from_skb(local, skb);
638*4882a593Smuzhiyun if (sdata) {
639*4882a593Smuzhiyun if (ethertype == sdata->control_port_protocol ||
640*4882a593Smuzhiyun ethertype == cpu_to_be16(ETH_P_PREAUTH))
641*4882a593Smuzhiyun cfg80211_control_port_tx_status(&sdata->wdev,
642*4882a593Smuzhiyun cookie,
643*4882a593Smuzhiyun skb->data,
644*4882a593Smuzhiyun skb->len,
645*4882a593Smuzhiyun acked,
646*4882a593Smuzhiyun GFP_ATOMIC);
647*4882a593Smuzhiyun else if (ieee80211_is_any_nullfunc(hdr->frame_control))
648*4882a593Smuzhiyun cfg80211_probe_status(sdata->dev, hdr->addr1,
649*4882a593Smuzhiyun cookie, acked,
650*4882a593Smuzhiyun info->status.ack_signal,
651*4882a593Smuzhiyun info->status.is_valid_ack_signal,
652*4882a593Smuzhiyun GFP_ATOMIC);
653*4882a593Smuzhiyun else if (ieee80211_is_mgmt(hdr->frame_control))
654*4882a593Smuzhiyun cfg80211_mgmt_tx_status(&sdata->wdev, cookie,
655*4882a593Smuzhiyun skb->data, skb->len,
656*4882a593Smuzhiyun acked, GFP_ATOMIC);
657*4882a593Smuzhiyun else
658*4882a593Smuzhiyun pr_warn("Unknown status report in ack skb\n");
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun rcu_read_unlock();
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun dev_kfree_skb_any(skb);
664*4882a593Smuzhiyun } else if (dropped) {
665*4882a593Smuzhiyun dev_kfree_skb_any(skb);
666*4882a593Smuzhiyun } else {
667*4882a593Smuzhiyun /* consumes skb */
668*4882a593Smuzhiyun skb_complete_wifi_ack(skb, acked);
669*4882a593Smuzhiyun }
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
ieee80211_report_used_skb(struct ieee80211_local * local,struct sk_buff * skb,bool dropped)672*4882a593Smuzhiyun static void ieee80211_report_used_skb(struct ieee80211_local *local,
673*4882a593Smuzhiyun struct sk_buff *skb, bool dropped)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
676*4882a593Smuzhiyun u16 tx_time_est = ieee80211_info_get_tx_time_est(info);
677*4882a593Smuzhiyun struct ieee80211_hdr *hdr = (void *)skb->data;
678*4882a593Smuzhiyun bool acked = info->flags & IEEE80211_TX_STAT_ACK;
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun if (dropped)
681*4882a593Smuzhiyun acked = false;
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun if (tx_time_est) {
684*4882a593Smuzhiyun struct sta_info *sta;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun rcu_read_lock();
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2);
689*4882a593Smuzhiyun ieee80211_sta_update_pending_airtime(local, sta,
690*4882a593Smuzhiyun skb_get_queue_mapping(skb),
691*4882a593Smuzhiyun tx_time_est,
692*4882a593Smuzhiyun true);
693*4882a593Smuzhiyun rcu_read_unlock();
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) {
697*4882a593Smuzhiyun struct ieee80211_sub_if_data *sdata;
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun rcu_read_lock();
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun sdata = ieee80211_sdata_from_skb(local, skb);
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun if (!sdata) {
704*4882a593Smuzhiyun skb->dev = NULL;
705*4882a593Smuzhiyun } else {
706*4882a593Smuzhiyun unsigned int hdr_size =
707*4882a593Smuzhiyun ieee80211_hdrlen(hdr->frame_control);
708*4882a593Smuzhiyun
709*4882a593Smuzhiyun /* Check to see if packet is a TDLS teardown packet */
710*4882a593Smuzhiyun if (ieee80211_is_data(hdr->frame_control) &&
711*4882a593Smuzhiyun (ieee80211_get_tdls_action(skb, hdr_size) ==
712*4882a593Smuzhiyun WLAN_TDLS_TEARDOWN))
713*4882a593Smuzhiyun ieee80211_tdls_td_tx_handle(local, sdata, skb,
714*4882a593Smuzhiyun info->flags);
715*4882a593Smuzhiyun else
716*4882a593Smuzhiyun ieee80211_mgd_conn_tx_status(sdata,
717*4882a593Smuzhiyun hdr->frame_control,
718*4882a593Smuzhiyun acked);
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun rcu_read_unlock();
722*4882a593Smuzhiyun } else if (info->ack_frame_id) {
723*4882a593Smuzhiyun ieee80211_report_ack_skb(local, info, acked, dropped);
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun if (!dropped && skb->destructor) {
727*4882a593Smuzhiyun skb->wifi_acked_valid = 1;
728*4882a593Smuzhiyun skb->wifi_acked = acked;
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun ieee80211_led_tx(local);
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun if (skb_has_frag_list(skb)) {
734*4882a593Smuzhiyun kfree_skb_list(skb_shinfo(skb)->frag_list);
735*4882a593Smuzhiyun skb_shinfo(skb)->frag_list = NULL;
736*4882a593Smuzhiyun }
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun /*
740*4882a593Smuzhiyun * Use a static threshold for now, best value to be determined
741*4882a593Smuzhiyun * by testing ...
742*4882a593Smuzhiyun * Should it depend on:
743*4882a593Smuzhiyun * - on # of retransmissions
744*4882a593Smuzhiyun * - current throughput (higher value for higher tpt)?
745*4882a593Smuzhiyun */
746*4882a593Smuzhiyun #define STA_LOST_PKT_THRESHOLD 50
747*4882a593Smuzhiyun #define STA_LOST_PKT_TIME HZ /* 1 sec since last ACK */
748*4882a593Smuzhiyun #define STA_LOST_TDLS_PKT_THRESHOLD 10
749*4882a593Smuzhiyun #define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */
750*4882a593Smuzhiyun
ieee80211_lost_packet(struct sta_info * sta,struct ieee80211_tx_info * info)751*4882a593Smuzhiyun static void ieee80211_lost_packet(struct sta_info *sta,
752*4882a593Smuzhiyun struct ieee80211_tx_info *info)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun unsigned long pkt_time = STA_LOST_PKT_TIME;
755*4882a593Smuzhiyun unsigned int pkt_thr = STA_LOST_PKT_THRESHOLD;
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun /* If driver relies on its own algorithm for station kickout, skip
758*4882a593Smuzhiyun * mac80211 packet loss mechanism.
759*4882a593Smuzhiyun */
760*4882a593Smuzhiyun if (ieee80211_hw_check(&sta->local->hw, REPORTS_LOW_ACK))
761*4882a593Smuzhiyun return;
762*4882a593Smuzhiyun
763*4882a593Smuzhiyun /* This packet was aggregated but doesn't carry status info */
764*4882a593Smuzhiyun if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
765*4882a593Smuzhiyun !(info->flags & IEEE80211_TX_STAT_AMPDU))
766*4882a593Smuzhiyun return;
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun sta->status_stats.lost_packets++;
769*4882a593Smuzhiyun if (sta->sta.tdls) {
770*4882a593Smuzhiyun pkt_time = STA_LOST_TDLS_PKT_TIME;
771*4882a593Smuzhiyun pkt_thr = STA_LOST_PKT_THRESHOLD;
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun /*
775*4882a593Smuzhiyun * If we're in TDLS mode, make sure that all STA_LOST_TDLS_PKT_THRESHOLD
776*4882a593Smuzhiyun * of the last packets were lost, and that no ACK was received in the
777*4882a593Smuzhiyun * last STA_LOST_TDLS_PKT_TIME ms, before triggering the CQM packet-loss
778*4882a593Smuzhiyun * mechanism.
779*4882a593Smuzhiyun * For non-TDLS, use STA_LOST_PKT_THRESHOLD and STA_LOST_PKT_TIME
780*4882a593Smuzhiyun */
781*4882a593Smuzhiyun if (sta->status_stats.lost_packets < pkt_thr ||
782*4882a593Smuzhiyun !time_after(jiffies, sta->status_stats.last_pkt_time + pkt_time))
783*4882a593Smuzhiyun return;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
786*4882a593Smuzhiyun sta->status_stats.lost_packets, GFP_ATOMIC);
787*4882a593Smuzhiyun sta->status_stats.lost_packets = 0;
788*4882a593Smuzhiyun }
789*4882a593Smuzhiyun
ieee80211_tx_get_rates(struct ieee80211_hw * hw,struct ieee80211_tx_info * info,int * retry_count)790*4882a593Smuzhiyun static int ieee80211_tx_get_rates(struct ieee80211_hw *hw,
791*4882a593Smuzhiyun struct ieee80211_tx_info *info,
792*4882a593Smuzhiyun int *retry_count)
793*4882a593Smuzhiyun {
794*4882a593Smuzhiyun int count = -1;
795*4882a593Smuzhiyun int i;
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
798*4882a593Smuzhiyun if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
799*4882a593Smuzhiyun !(info->flags & IEEE80211_TX_STAT_AMPDU)) {
800*4882a593Smuzhiyun /* just the first aggr frame carry status info */
801*4882a593Smuzhiyun info->status.rates[i].idx = -1;
802*4882a593Smuzhiyun info->status.rates[i].count = 0;
803*4882a593Smuzhiyun break;
804*4882a593Smuzhiyun } else if (info->status.rates[i].idx < 0) {
805*4882a593Smuzhiyun break;
806*4882a593Smuzhiyun } else if (i >= hw->max_report_rates) {
807*4882a593Smuzhiyun /* the HW cannot have attempted that rate */
808*4882a593Smuzhiyun info->status.rates[i].idx = -1;
809*4882a593Smuzhiyun info->status.rates[i].count = 0;
810*4882a593Smuzhiyun break;
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun count += info->status.rates[i].count;
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun
816*4882a593Smuzhiyun if (count < 0)
817*4882a593Smuzhiyun count = 0;
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun *retry_count = count;
820*4882a593Smuzhiyun return i - 1;
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun
ieee80211_tx_monitor(struct ieee80211_local * local,struct sk_buff * skb,struct ieee80211_supported_band * sband,int retry_count,int shift,bool send_to_cooked,struct ieee80211_tx_status * status)823*4882a593Smuzhiyun void ieee80211_tx_monitor(struct ieee80211_local *local, struct sk_buff *skb,
824*4882a593Smuzhiyun struct ieee80211_supported_band *sband,
825*4882a593Smuzhiyun int retry_count, int shift, bool send_to_cooked,
826*4882a593Smuzhiyun struct ieee80211_tx_status *status)
827*4882a593Smuzhiyun {
828*4882a593Smuzhiyun struct sk_buff *skb2;
829*4882a593Smuzhiyun struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
830*4882a593Smuzhiyun struct ieee80211_sub_if_data *sdata;
831*4882a593Smuzhiyun struct net_device *prev_dev = NULL;
832*4882a593Smuzhiyun int rtap_len;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun /* send frame to monitor interfaces now */
835*4882a593Smuzhiyun rtap_len = ieee80211_tx_radiotap_len(info, status);
836*4882a593Smuzhiyun if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
837*4882a593Smuzhiyun pr_err("ieee80211_tx_status: headroom too small\n");
838*4882a593Smuzhiyun dev_kfree_skb(skb);
839*4882a593Smuzhiyun return;
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun ieee80211_add_tx_radiotap_header(local, sband, skb, retry_count,
842*4882a593Smuzhiyun rtap_len, shift, status);
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun /* XXX: is this sufficient for BPF? */
845*4882a593Smuzhiyun skb_reset_mac_header(skb);
846*4882a593Smuzhiyun skb->ip_summed = CHECKSUM_UNNECESSARY;
847*4882a593Smuzhiyun skb->pkt_type = PACKET_OTHERHOST;
848*4882a593Smuzhiyun skb->protocol = htons(ETH_P_802_2);
849*4882a593Smuzhiyun memset(skb->cb, 0, sizeof(skb->cb));
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun rcu_read_lock();
852*4882a593Smuzhiyun list_for_each_entry_rcu(sdata, &local->interfaces, list) {
853*4882a593Smuzhiyun if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
854*4882a593Smuzhiyun if (!ieee80211_sdata_running(sdata))
855*4882a593Smuzhiyun continue;
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun if ((sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) &&
858*4882a593Smuzhiyun !send_to_cooked)
859*4882a593Smuzhiyun continue;
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun if (prev_dev) {
862*4882a593Smuzhiyun skb2 = skb_clone(skb, GFP_ATOMIC);
863*4882a593Smuzhiyun if (skb2) {
864*4882a593Smuzhiyun skb2->dev = prev_dev;
865*4882a593Smuzhiyun netif_rx(skb2);
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun }
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun prev_dev = sdata->dev;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun if (prev_dev) {
873*4882a593Smuzhiyun skb->dev = prev_dev;
874*4882a593Smuzhiyun netif_rx(skb);
875*4882a593Smuzhiyun skb = NULL;
876*4882a593Smuzhiyun }
877*4882a593Smuzhiyun rcu_read_unlock();
878*4882a593Smuzhiyun dev_kfree_skb(skb);
879*4882a593Smuzhiyun }
880*4882a593Smuzhiyun
__ieee80211_tx_status(struct ieee80211_hw * hw,struct ieee80211_tx_status * status,int rates_idx,int retry_count)881*4882a593Smuzhiyun static void __ieee80211_tx_status(struct ieee80211_hw *hw,
882*4882a593Smuzhiyun struct ieee80211_tx_status *status,
883*4882a593Smuzhiyun int rates_idx, int retry_count)
884*4882a593Smuzhiyun {
885*4882a593Smuzhiyun struct sk_buff *skb = status->skb;
886*4882a593Smuzhiyun struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
887*4882a593Smuzhiyun struct ieee80211_local *local = hw_to_local(hw);
888*4882a593Smuzhiyun struct ieee80211_tx_info *info = status->info;
889*4882a593Smuzhiyun struct sta_info *sta;
890*4882a593Smuzhiyun __le16 fc;
891*4882a593Smuzhiyun struct ieee80211_supported_band *sband;
892*4882a593Smuzhiyun bool send_to_cooked;
893*4882a593Smuzhiyun bool acked;
894*4882a593Smuzhiyun bool noack_success;
895*4882a593Smuzhiyun struct ieee80211_bar *bar;
896*4882a593Smuzhiyun int shift = 0;
897*4882a593Smuzhiyun int tid = IEEE80211_NUM_TIDS;
898*4882a593Smuzhiyun
899*4882a593Smuzhiyun sband = local->hw.wiphy->bands[info->band];
900*4882a593Smuzhiyun fc = hdr->frame_control;
901*4882a593Smuzhiyun
902*4882a593Smuzhiyun if (status->sta) {
903*4882a593Smuzhiyun sta = container_of(status->sta, struct sta_info, sta);
904*4882a593Smuzhiyun shift = ieee80211_vif_get_shift(&sta->sdata->vif);
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun if (info->flags & IEEE80211_TX_STATUS_EOSP)
907*4882a593Smuzhiyun clear_sta_flag(sta, WLAN_STA_SP);
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
910*4882a593Smuzhiyun noack_success = !!(info->flags &
911*4882a593Smuzhiyun IEEE80211_TX_STAT_NOACK_TRANSMITTED);
912*4882a593Smuzhiyun
913*4882a593Smuzhiyun /* mesh Peer Service Period support */
914*4882a593Smuzhiyun if (ieee80211_vif_is_mesh(&sta->sdata->vif) &&
915*4882a593Smuzhiyun ieee80211_is_data_qos(fc))
916*4882a593Smuzhiyun ieee80211_mpsp_trigger_process(
917*4882a593Smuzhiyun ieee80211_get_qos_ctl(hdr), sta, true, acked);
918*4882a593Smuzhiyun
919*4882a593Smuzhiyun if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL) &&
920*4882a593Smuzhiyun (ieee80211_is_data(hdr->frame_control)) &&
921*4882a593Smuzhiyun (rates_idx != -1))
922*4882a593Smuzhiyun sta->tx_stats.last_rate =
923*4882a593Smuzhiyun info->status.rates[rates_idx];
924*4882a593Smuzhiyun
925*4882a593Smuzhiyun if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
926*4882a593Smuzhiyun (ieee80211_is_data_qos(fc))) {
927*4882a593Smuzhiyun u16 ssn;
928*4882a593Smuzhiyun u8 *qc;
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun qc = ieee80211_get_qos_ctl(hdr);
931*4882a593Smuzhiyun tid = qc[0] & 0xf;
932*4882a593Smuzhiyun ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10)
933*4882a593Smuzhiyun & IEEE80211_SCTL_SEQ);
934*4882a593Smuzhiyun ieee80211_send_bar(&sta->sdata->vif, hdr->addr1,
935*4882a593Smuzhiyun tid, ssn);
936*4882a593Smuzhiyun } else if (ieee80211_is_data_qos(fc)) {
937*4882a593Smuzhiyun u8 *qc = ieee80211_get_qos_ctl(hdr);
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun tid = qc[0] & 0xf;
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun if (!acked && ieee80211_is_back_req(fc)) {
943*4882a593Smuzhiyun u16 control;
944*4882a593Smuzhiyun
945*4882a593Smuzhiyun /*
946*4882a593Smuzhiyun * BAR failed, store the last SSN and retry sending
947*4882a593Smuzhiyun * the BAR when the next unicast transmission on the
948*4882a593Smuzhiyun * same TID succeeds.
949*4882a593Smuzhiyun */
950*4882a593Smuzhiyun bar = (struct ieee80211_bar *) skb->data;
951*4882a593Smuzhiyun control = le16_to_cpu(bar->control);
952*4882a593Smuzhiyun if (!(control & IEEE80211_BAR_CTRL_MULTI_TID)) {
953*4882a593Smuzhiyun u16 ssn = le16_to_cpu(bar->start_seq_num);
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun tid = (control &
956*4882a593Smuzhiyun IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
957*4882a593Smuzhiyun IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun ieee80211_set_bar_pending(sta, tid, ssn);
960*4882a593Smuzhiyun }
961*4882a593Smuzhiyun }
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
964*4882a593Smuzhiyun ieee80211_handle_filtered_frame(local, sta, skb);
965*4882a593Smuzhiyun return;
966*4882a593Smuzhiyun } else if (ieee80211_is_data_present(fc)) {
967*4882a593Smuzhiyun if (!acked && !noack_success)
968*4882a593Smuzhiyun sta->status_stats.msdu_failed[tid]++;
969*4882a593Smuzhiyun
970*4882a593Smuzhiyun sta->status_stats.msdu_retries[tid] +=
971*4882a593Smuzhiyun retry_count;
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun if (!(info->flags & IEEE80211_TX_CTL_INJECTED) && acked)
975*4882a593Smuzhiyun ieee80211_frame_acked(sta, skb);
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun
979*4882a593Smuzhiyun /* SNMP counters
980*4882a593Smuzhiyun * Fragments are passed to low-level drivers as separate skbs, so these
981*4882a593Smuzhiyun * are actually fragments, not frames. Update frame counters only for
982*4882a593Smuzhiyun * the first fragment of the frame. */
983*4882a593Smuzhiyun if ((info->flags & IEEE80211_TX_STAT_ACK) ||
984*4882a593Smuzhiyun (info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED)) {
985*4882a593Smuzhiyun if (ieee80211_is_first_frag(hdr->seq_ctrl)) {
986*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11TransmittedFrameCount);
987*4882a593Smuzhiyun if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
988*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
989*4882a593Smuzhiyun if (retry_count > 0)
990*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11RetryCount);
991*4882a593Smuzhiyun if (retry_count > 1)
992*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11MultipleRetryCount);
993*4882a593Smuzhiyun }
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun /* This counter shall be incremented for an acknowledged MPDU
996*4882a593Smuzhiyun * with an individual address in the address 1 field or an MPDU
997*4882a593Smuzhiyun * with a multicast address in the address 1 field of type Data
998*4882a593Smuzhiyun * or Management. */
999*4882a593Smuzhiyun if (!is_multicast_ether_addr(hdr->addr1) ||
1000*4882a593Smuzhiyun ieee80211_is_data(fc) ||
1001*4882a593Smuzhiyun ieee80211_is_mgmt(fc))
1002*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11TransmittedFragmentCount);
1003*4882a593Smuzhiyun } else {
1004*4882a593Smuzhiyun if (ieee80211_is_first_frag(hdr->seq_ctrl))
1005*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11FailedCount);
1006*4882a593Smuzhiyun }
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun if (ieee80211_is_any_nullfunc(fc) &&
1009*4882a593Smuzhiyun ieee80211_has_pm(fc) &&
1010*4882a593Smuzhiyun ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS) &&
1011*4882a593Smuzhiyun !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
1012*4882a593Smuzhiyun local->ps_sdata && !(local->scanning)) {
1013*4882a593Smuzhiyun if (info->flags & IEEE80211_TX_STAT_ACK) {
1014*4882a593Smuzhiyun local->ps_sdata->u.mgd.flags |=
1015*4882a593Smuzhiyun IEEE80211_STA_NULLFUNC_ACKED;
1016*4882a593Smuzhiyun } else
1017*4882a593Smuzhiyun mod_timer(&local->dynamic_ps_timer, jiffies +
1018*4882a593Smuzhiyun msecs_to_jiffies(10));
1019*4882a593Smuzhiyun }
1020*4882a593Smuzhiyun
1021*4882a593Smuzhiyun ieee80211_report_used_skb(local, skb, false);
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun /* this was a transmitted frame, but now we want to reuse it */
1024*4882a593Smuzhiyun skb_orphan(skb);
1025*4882a593Smuzhiyun
1026*4882a593Smuzhiyun /* Need to make a copy before skb->cb gets cleared */
1027*4882a593Smuzhiyun send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) ||
1028*4882a593Smuzhiyun !(ieee80211_is_data(fc));
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun /*
1031*4882a593Smuzhiyun * This is a bit racy but we can avoid a lot of work
1032*4882a593Smuzhiyun * with this test...
1033*4882a593Smuzhiyun */
1034*4882a593Smuzhiyun if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) {
1035*4882a593Smuzhiyun if (status->free_list)
1036*4882a593Smuzhiyun list_add_tail(&skb->list, status->free_list);
1037*4882a593Smuzhiyun else
1038*4882a593Smuzhiyun dev_kfree_skb(skb);
1039*4882a593Smuzhiyun return;
1040*4882a593Smuzhiyun }
1041*4882a593Smuzhiyun
1042*4882a593Smuzhiyun /* send to monitor interfaces */
1043*4882a593Smuzhiyun ieee80211_tx_monitor(local, skb, sband, retry_count, shift,
1044*4882a593Smuzhiyun send_to_cooked, status);
1045*4882a593Smuzhiyun }
1046*4882a593Smuzhiyun
ieee80211_tx_status(struct ieee80211_hw * hw,struct sk_buff * skb)1047*4882a593Smuzhiyun void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
1048*4882a593Smuzhiyun {
1049*4882a593Smuzhiyun struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1050*4882a593Smuzhiyun struct ieee80211_local *local = hw_to_local(hw);
1051*4882a593Smuzhiyun struct ieee80211_tx_status status = {
1052*4882a593Smuzhiyun .skb = skb,
1053*4882a593Smuzhiyun .info = IEEE80211_SKB_CB(skb),
1054*4882a593Smuzhiyun };
1055*4882a593Smuzhiyun struct sta_info *sta;
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun rcu_read_lock();
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun sta = sta_info_get_by_addrs(local, hdr->addr1, hdr->addr2);
1060*4882a593Smuzhiyun if (sta)
1061*4882a593Smuzhiyun status.sta = &sta->sta;
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun ieee80211_tx_status_ext(hw, &status);
1064*4882a593Smuzhiyun rcu_read_unlock();
1065*4882a593Smuzhiyun }
1066*4882a593Smuzhiyun EXPORT_SYMBOL(ieee80211_tx_status);
1067*4882a593Smuzhiyun
ieee80211_tx_status_ext(struct ieee80211_hw * hw,struct ieee80211_tx_status * status)1068*4882a593Smuzhiyun void ieee80211_tx_status_ext(struct ieee80211_hw *hw,
1069*4882a593Smuzhiyun struct ieee80211_tx_status *status)
1070*4882a593Smuzhiyun {
1071*4882a593Smuzhiyun struct ieee80211_local *local = hw_to_local(hw);
1072*4882a593Smuzhiyun struct ieee80211_tx_info *info = status->info;
1073*4882a593Smuzhiyun struct ieee80211_sta *pubsta = status->sta;
1074*4882a593Smuzhiyun struct sk_buff *skb = status->skb;
1075*4882a593Smuzhiyun struct ieee80211_supported_band *sband;
1076*4882a593Smuzhiyun struct sta_info *sta = NULL;
1077*4882a593Smuzhiyun int rates_idx, retry_count;
1078*4882a593Smuzhiyun bool acked, noack_success;
1079*4882a593Smuzhiyun u16 tx_time_est;
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun if (pubsta) {
1082*4882a593Smuzhiyun sta = container_of(pubsta, struct sta_info, sta);
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun if (status->rate)
1085*4882a593Smuzhiyun sta->tx_stats.last_rate_info = *status->rate;
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun
1088*4882a593Smuzhiyun if (skb && (tx_time_est =
1089*4882a593Smuzhiyun ieee80211_info_get_tx_time_est(IEEE80211_SKB_CB(skb))) > 0) {
1090*4882a593Smuzhiyun /* Do this here to avoid the expensive lookup of the sta
1091*4882a593Smuzhiyun * in ieee80211_report_used_skb().
1092*4882a593Smuzhiyun */
1093*4882a593Smuzhiyun ieee80211_sta_update_pending_airtime(local, sta,
1094*4882a593Smuzhiyun skb_get_queue_mapping(skb),
1095*4882a593Smuzhiyun tx_time_est,
1096*4882a593Smuzhiyun true);
1097*4882a593Smuzhiyun ieee80211_info_set_tx_time_est(IEEE80211_SKB_CB(skb), 0);
1098*4882a593Smuzhiyun }
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun if (!status->info)
1101*4882a593Smuzhiyun goto free;
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
1104*4882a593Smuzhiyun
1105*4882a593Smuzhiyun sband = hw->wiphy->bands[info->band];
1106*4882a593Smuzhiyun
1107*4882a593Smuzhiyun acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
1108*4882a593Smuzhiyun noack_success = !!(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED);
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun if (pubsta) {
1111*4882a593Smuzhiyun struct ieee80211_sub_if_data *sdata = sta->sdata;
1112*4882a593Smuzhiyun
1113*4882a593Smuzhiyun if (!acked && !noack_success)
1114*4882a593Smuzhiyun sta->status_stats.retry_failed++;
1115*4882a593Smuzhiyun sta->status_stats.retry_count += retry_count;
1116*4882a593Smuzhiyun
1117*4882a593Smuzhiyun if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
1118*4882a593Smuzhiyun if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1119*4882a593Smuzhiyun skb && !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
1120*4882a593Smuzhiyun ieee80211_sta_tx_notify(sdata, (void *) skb->data,
1121*4882a593Smuzhiyun acked, info->status.tx_time);
1122*4882a593Smuzhiyun
1123*4882a593Smuzhiyun if (acked) {
1124*4882a593Smuzhiyun sta->status_stats.last_ack = jiffies;
1125*4882a593Smuzhiyun
1126*4882a593Smuzhiyun if (sta->status_stats.lost_packets)
1127*4882a593Smuzhiyun sta->status_stats.lost_packets = 0;
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun /* Track when last packet was ACKed */
1130*4882a593Smuzhiyun sta->status_stats.last_pkt_time = jiffies;
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyun /* Reset connection monitor */
1133*4882a593Smuzhiyun if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1134*4882a593Smuzhiyun unlikely(sdata->u.mgd.probe_send_count > 0))
1135*4882a593Smuzhiyun sdata->u.mgd.probe_send_count = 0;
1136*4882a593Smuzhiyun
1137*4882a593Smuzhiyun if (info->status.is_valid_ack_signal) {
1138*4882a593Smuzhiyun sta->status_stats.last_ack_signal =
1139*4882a593Smuzhiyun (s8)info->status.ack_signal;
1140*4882a593Smuzhiyun sta->status_stats.ack_signal_filled = true;
1141*4882a593Smuzhiyun ewma_avg_signal_add(&sta->status_stats.avg_ack_signal,
1142*4882a593Smuzhiyun -info->status.ack_signal);
1143*4882a593Smuzhiyun }
1144*4882a593Smuzhiyun } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
1145*4882a593Smuzhiyun /*
1146*4882a593Smuzhiyun * The STA is in power save mode, so assume
1147*4882a593Smuzhiyun * that this TX packet failed because of that.
1148*4882a593Smuzhiyun */
1149*4882a593Smuzhiyun if (skb)
1150*4882a593Smuzhiyun ieee80211_handle_filtered_frame(local, sta, skb);
1151*4882a593Smuzhiyun return;
1152*4882a593Smuzhiyun } else if (noack_success) {
1153*4882a593Smuzhiyun /* nothing to do here, do not account as lost */
1154*4882a593Smuzhiyun } else {
1155*4882a593Smuzhiyun ieee80211_lost_packet(sta, info);
1156*4882a593Smuzhiyun }
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun rate_control_tx_status(local, sband, status);
1160*4882a593Smuzhiyun if (ieee80211_vif_is_mesh(&sta->sdata->vif))
1161*4882a593Smuzhiyun ieee80211s_update_metric(local, sta, status);
1162*4882a593Smuzhiyun }
1163*4882a593Smuzhiyun
1164*4882a593Smuzhiyun if (skb && !(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP))
1165*4882a593Smuzhiyun return __ieee80211_tx_status(hw, status, rates_idx,
1166*4882a593Smuzhiyun retry_count);
1167*4882a593Smuzhiyun
1168*4882a593Smuzhiyun if (acked || noack_success) {
1169*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11TransmittedFrameCount);
1170*4882a593Smuzhiyun if (!pubsta)
1171*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount);
1172*4882a593Smuzhiyun if (retry_count > 0)
1173*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11RetryCount);
1174*4882a593Smuzhiyun if (retry_count > 1)
1175*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11MultipleRetryCount);
1176*4882a593Smuzhiyun } else {
1177*4882a593Smuzhiyun I802_DEBUG_INC(local->dot11FailedCount);
1178*4882a593Smuzhiyun }
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun free:
1181*4882a593Smuzhiyun if (!skb)
1182*4882a593Smuzhiyun return;
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun ieee80211_report_used_skb(local, skb, false);
1185*4882a593Smuzhiyun if (status->free_list)
1186*4882a593Smuzhiyun list_add_tail(&skb->list, status->free_list);
1187*4882a593Smuzhiyun else
1188*4882a593Smuzhiyun dev_kfree_skb(skb);
1189*4882a593Smuzhiyun }
1190*4882a593Smuzhiyun EXPORT_SYMBOL(ieee80211_tx_status_ext);
1191*4882a593Smuzhiyun
ieee80211_tx_rate_update(struct ieee80211_hw * hw,struct ieee80211_sta * pubsta,struct ieee80211_tx_info * info)1192*4882a593Smuzhiyun void ieee80211_tx_rate_update(struct ieee80211_hw *hw,
1193*4882a593Smuzhiyun struct ieee80211_sta *pubsta,
1194*4882a593Smuzhiyun struct ieee80211_tx_info *info)
1195*4882a593Smuzhiyun {
1196*4882a593Smuzhiyun struct ieee80211_local *local = hw_to_local(hw);
1197*4882a593Smuzhiyun struct ieee80211_supported_band *sband = hw->wiphy->bands[info->band];
1198*4882a593Smuzhiyun struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
1199*4882a593Smuzhiyun struct ieee80211_tx_status status = {
1200*4882a593Smuzhiyun .info = info,
1201*4882a593Smuzhiyun .sta = pubsta,
1202*4882a593Smuzhiyun };
1203*4882a593Smuzhiyun
1204*4882a593Smuzhiyun rate_control_tx_status(local, sband, &status);
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL))
1207*4882a593Smuzhiyun sta->tx_stats.last_rate = info->status.rates[0];
1208*4882a593Smuzhiyun }
1209*4882a593Smuzhiyun EXPORT_SYMBOL(ieee80211_tx_rate_update);
1210*4882a593Smuzhiyun
ieee80211_tx_status_8023(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct sk_buff * skb)1211*4882a593Smuzhiyun void ieee80211_tx_status_8023(struct ieee80211_hw *hw,
1212*4882a593Smuzhiyun struct ieee80211_vif *vif,
1213*4882a593Smuzhiyun struct sk_buff *skb)
1214*4882a593Smuzhiyun {
1215*4882a593Smuzhiyun struct ieee80211_sub_if_data *sdata;
1216*4882a593Smuzhiyun struct ieee80211_tx_status status = {
1217*4882a593Smuzhiyun .skb = skb,
1218*4882a593Smuzhiyun .info = IEEE80211_SKB_CB(skb),
1219*4882a593Smuzhiyun };
1220*4882a593Smuzhiyun struct sta_info *sta;
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun sdata = vif_to_sdata(vif);
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun rcu_read_lock();
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun if (!ieee80211_lookup_ra_sta(sdata, skb, &sta) && !IS_ERR(sta))
1227*4882a593Smuzhiyun status.sta = &sta->sta;
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun ieee80211_tx_status_ext(hw, &status);
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun rcu_read_unlock();
1232*4882a593Smuzhiyun }
1233*4882a593Smuzhiyun EXPORT_SYMBOL(ieee80211_tx_status_8023);
1234*4882a593Smuzhiyun
ieee80211_report_low_ack(struct ieee80211_sta * pubsta,u32 num_packets)1235*4882a593Smuzhiyun void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
1236*4882a593Smuzhiyun {
1237*4882a593Smuzhiyun struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
1238*4882a593Smuzhiyun cfg80211_cqm_pktloss_notify(sta->sdata->dev, sta->sta.addr,
1239*4882a593Smuzhiyun num_packets, GFP_ATOMIC);
1240*4882a593Smuzhiyun }
1241*4882a593Smuzhiyun EXPORT_SYMBOL(ieee80211_report_low_ack);
1242*4882a593Smuzhiyun
ieee80211_free_txskb(struct ieee80211_hw * hw,struct sk_buff * skb)1243*4882a593Smuzhiyun void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
1244*4882a593Smuzhiyun {
1245*4882a593Smuzhiyun struct ieee80211_local *local = hw_to_local(hw);
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun ieee80211_report_used_skb(local, skb, true);
1248*4882a593Smuzhiyun dev_kfree_skb_any(skb);
1249*4882a593Smuzhiyun }
1250*4882a593Smuzhiyun EXPORT_SYMBOL(ieee80211_free_txskb);
1251*4882a593Smuzhiyun
ieee80211_purge_tx_queue(struct ieee80211_hw * hw,struct sk_buff_head * skbs)1252*4882a593Smuzhiyun void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
1253*4882a593Smuzhiyun struct sk_buff_head *skbs)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun struct sk_buff *skb;
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun while ((skb = __skb_dequeue(skbs)))
1258*4882a593Smuzhiyun ieee80211_free_txskb(hw, skb);
1259*4882a593Smuzhiyun }
1260