diff options
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r-- | net/mac80211/status.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 56d5b9a6ec5b..94613af009f3 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -171,13 +171,16 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
171 | struct net_device *prev_dev = NULL; | 171 | struct net_device *prev_dev = NULL; |
172 | struct sta_info *sta, *tmp; | 172 | struct sta_info *sta, *tmp; |
173 | int retry_count = -1, i; | 173 | int retry_count = -1, i; |
174 | bool injected; | 174 | int rates_idx = -1; |
175 | bool send_to_cooked; | ||
175 | 176 | ||
176 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 177 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
177 | /* the HW cannot have attempted that rate */ | 178 | /* the HW cannot have attempted that rate */ |
178 | if (i >= hw->max_rates) { | 179 | if (i >= hw->max_rates) { |
179 | info->status.rates[i].idx = -1; | 180 | info->status.rates[i].idx = -1; |
180 | info->status.rates[i].count = 0; | 181 | info->status.rates[i].count = 0; |
182 | } else if (info->status.rates[i].idx >= 0) { | ||
183 | rates_idx = i; | ||
181 | } | 184 | } |
182 | 185 | ||
183 | retry_count += info->status.rates[i].count; | 186 | retry_count += info->status.rates[i].count; |
@@ -206,6 +209,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
206 | return; | 209 | return; |
207 | } | 210 | } |
208 | 211 | ||
212 | if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && | ||
213 | (rates_idx != -1)) | ||
214 | sta->last_tx_rate = info->status.rates[rates_idx]; | ||
215 | |||
209 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | 216 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && |
210 | (ieee80211_is_data_qos(fc))) { | 217 | (ieee80211_is_data_qos(fc))) { |
211 | u16 tid, ssn; | 218 | u16 tid, ssn; |
@@ -296,11 +303,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
296 | /* this was a transmitted frame, but now we want to reuse it */ | 303 | /* this was a transmitted frame, but now we want to reuse it */ |
297 | skb_orphan(skb); | 304 | skb_orphan(skb); |
298 | 305 | ||
306 | /* Need to make a copy before skb->cb gets cleared */ | ||
307 | send_to_cooked = !!(info->flags & IEEE80211_TX_CTL_INJECTED) || | ||
308 | (type != IEEE80211_FTYPE_DATA); | ||
309 | |||
299 | /* | 310 | /* |
300 | * This is a bit racy but we can avoid a lot of work | 311 | * This is a bit racy but we can avoid a lot of work |
301 | * with this test... | 312 | * with this test... |
302 | */ | 313 | */ |
303 | if (!local->monitors && !local->cooked_mntrs) { | 314 | if (!local->monitors && (!send_to_cooked || !local->cooked_mntrs)) { |
304 | dev_kfree_skb(skb); | 315 | dev_kfree_skb(skb); |
305 | return; | 316 | return; |
306 | } | 317 | } |
@@ -345,9 +356,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
345 | /* for now report the total retry_count */ | 356 | /* for now report the total retry_count */ |
346 | rthdr->data_retries = retry_count; | 357 | rthdr->data_retries = retry_count; |
347 | 358 | ||
348 | /* Need to make a copy before skb->cb gets cleared */ | ||
349 | injected = !!(info->flags & IEEE80211_TX_CTL_INJECTED); | ||
350 | |||
351 | /* XXX: is this sufficient for BPF? */ | 359 | /* XXX: is this sufficient for BPF? */ |
352 | skb_set_mac_header(skb, 0); | 360 | skb_set_mac_header(skb, 0); |
353 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 361 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -362,8 +370,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
362 | continue; | 370 | continue; |
363 | 371 | ||
364 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && | 372 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && |
365 | !injected && | 373 | !send_to_cooked) |
366 | (type == IEEE80211_FTYPE_DATA)) | ||
367 | continue; | 374 | continue; |
368 | 375 | ||
369 | if (prev_dev) { | 376 | if (prev_dev) { |