1 From: Felix Fietkau <nbd@openwrt.org>
2 Date: Sat, 15 Nov 2014 23:50:27 +0100
3 Subject: [PATCH] mac80211: add ieee80211_tx_status_noskb
5 This can be used by drivers that cannot reliably map tx status
6 information onto specific skbs.
8 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
11 --- a/include/net/mac80211.h
12 +++ b/include/net/mac80211.h
13 @@ -3517,6 +3517,28 @@ void ieee80211_tx_status(struct ieee8021
17 + * ieee80211_tx_status_noskb - transmit status callback without skb
19 + * This function can be used as a replacement for ieee80211_tx_status
20 + * in drivers that cannot reliably map tx status information back to
23 + * This function may not be called in IRQ context. Calls to this function
24 + * for a single hardware must be synchronized against each other. Calls
25 + * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
26 + * may not be mixed for a single hardware. Must not run concurrently with
27 + * ieee80211_rx() or ieee80211_rx_ni().
29 + * @hw: the hardware the frame was transmitted by
30 + * @sta: the receiver station to which this packet is sent
31 + * (NULL for multicast packets)
32 + * @info: tx status information
34 +void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
35 + struct ieee80211_sta *sta,
36 + struct ieee80211_tx_info *info);
39 * ieee80211_tx_status_ni - transmit status callback (in process context)
41 * Like ieee80211_tx_status() but can be called in process context.
42 --- a/net/mac80211/rate.h
43 +++ b/net/mac80211/rate.h
44 @@ -49,6 +49,23 @@ static inline void rate_control_tx_statu
49 +rate_control_tx_status_noskb(struct ieee80211_local *local,
50 + struct ieee80211_supported_band *sband,
51 + struct sta_info *sta,
52 + struct ieee80211_tx_info *info)
54 + struct rate_control_ref *ref = local->rate_ctrl;
55 + struct ieee80211_sta *ista = &sta->sta;
56 + void *priv_sta = sta->rate_ctrl_priv;
58 + if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
61 + ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
65 static inline void rate_control_rate_init(struct sta_info *sta)
67 struct ieee80211_local *local = sta->sdata->local;
68 --- a/net/mac80211/status.c
69 +++ b/net/mac80211/status.c
70 @@ -541,10 +541,9 @@ static void ieee80211_tx_latency_end_msr
71 #define STA_LOST_TDLS_PKT_THRESHOLD 10
72 #define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */
74 -static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
75 +static void ieee80211_lost_packet(struct sta_info *sta,
76 + struct ieee80211_tx_info *info)
78 - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
80 /* This packet was aggregated but doesn't carry status info */
81 if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
82 !(info->flags & IEEE80211_TX_STAT_AMPDU))
83 @@ -571,24 +570,13 @@ static void ieee80211_lost_packet(struct
84 sta->lost_packets = 0;
87 -void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
88 +static int ieee80211_tx_get_rates(struct ieee80211_hw *hw,
89 + struct ieee80211_tx_info *info,
92 - struct sk_buff *skb2;
93 - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
94 - struct ieee80211_local *local = hw_to_local(hw);
95 - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
97 - struct ieee80211_supported_band *sband;
98 - struct ieee80211_sub_if_data *sdata;
99 - struct net_device *prev_dev = NULL;
100 - struct sta_info *sta, *tmp;
101 - int retry_count = -1, i;
103 - bool send_to_cooked;
105 - struct ieee80211_bar *bar;
111 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
112 if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
113 @@ -606,12 +594,94 @@ void ieee80211_tx_status(struct ieee8021
117 - retry_count += info->status.rates[i].count;
118 + count += info->status.rates[i].count;
122 - if (retry_count < 0)
127 + *retry_count = count;
131 +void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
132 + struct ieee80211_sta *pubsta,
133 + struct ieee80211_tx_info *info)
135 + struct ieee80211_local *local = hw_to_local(hw);
136 + struct ieee80211_supported_band *sband;
141 + rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
143 + sband = hw->wiphy->bands[info->band];
145 + acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
147 + struct sta_info *sta;
149 + sta = container_of(pubsta, struct sta_info, sta);
151 + if (info->flags & IEEE80211_TX_STATUS_EOSP)
152 + clear_sta_flag(sta, WLAN_STA_SP);
155 + sta->tx_retry_failed++;
156 + sta->tx_retry_count += retry_count;
159 + sta->last_rx = jiffies;
161 + if (sta->lost_packets)
162 + sta->lost_packets = 0;
164 + /* Track when last TDLS packet was ACKed */
165 + if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
166 + sta->last_tdls_pkt_time = jiffies;
168 + ieee80211_lost_packet(sta, info);
171 + rate_control_tx_status_noskb(local, sband, sta, info);
175 + local->dot11TransmittedFrameCount++;
177 + local->dot11MulticastTransmittedFrameCount++;
178 + if (retry_count > 0)
179 + local->dot11RetryCount++;
180 + if (retry_count > 1)
181 + local->dot11MultipleRetryCount++;
183 + local->dot11FailedCount++;
186 +EXPORT_SYMBOL(ieee80211_tx_status_noskb);
188 +void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
190 + struct sk_buff *skb2;
191 + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
192 + struct ieee80211_local *local = hw_to_local(hw);
193 + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
195 + struct ieee80211_supported_band *sband;
196 + struct ieee80211_sub_if_data *sdata;
197 + struct net_device *prev_dev = NULL;
198 + struct sta_info *sta, *tmp;
201 + bool send_to_cooked;
203 + struct ieee80211_bar *bar;
207 + rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
211 @@ -716,7 +786,7 @@ void ieee80211_tx_status(struct ieee8021
212 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
213 sta->last_tdls_pkt_time = jiffies;
215 - ieee80211_lost_packet(sta, skb);
216 + ieee80211_lost_packet(sta, info);