aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/status.c145
1 files changed, 71 insertions, 74 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 21fa5c72ea14..2d931ad0e90a 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -325,6 +325,75 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
325 325
326} 326}
327 327
328static void ieee80211_report_used_skb(struct ieee80211_local *local,
329 struct sk_buff *skb, bool dropped)
330{
331 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
332 struct ieee80211_hdr *hdr = (void *)skb->data;
333 bool acked = info->flags & IEEE80211_TX_STAT_ACK;
334
335 if (dropped)
336 acked = false;
337
338 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
339 struct ieee80211_sub_if_data *sdata = NULL;
340 struct ieee80211_sub_if_data *iter_sdata;
341 u64 cookie = (unsigned long)skb;
342
343 rcu_read_lock();
344
345 if (skb->dev) {
346 list_for_each_entry_rcu(iter_sdata, &local->interfaces,
347 list) {
348 if (!iter_sdata->dev)
349 continue;
350
351 if (skb->dev == iter_sdata->dev) {
352 sdata = iter_sdata;
353 break;
354 }
355 }
356 } else {
357 sdata = rcu_dereference(local->p2p_sdata);
358 }
359
360 if (!sdata)
361 skb->dev = NULL;
362 else if (ieee80211_is_nullfunc(hdr->frame_control) ||
363 ieee80211_is_qos_nullfunc(hdr->frame_control)) {
364 cfg80211_probe_status(sdata->dev, hdr->addr1,
365 cookie, acked, GFP_ATOMIC);
366 } else {
367 cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data,
368 skb->len, acked, GFP_ATOMIC);
369 }
370
371 rcu_read_unlock();
372 }
373
374 if (unlikely(info->ack_frame_id)) {
375 struct sk_buff *ack_skb;
376 unsigned long flags;
377
378 spin_lock_irqsave(&local->ack_status_lock, flags);
379 ack_skb = idr_find(&local->ack_status_frames,
380 info->ack_frame_id);
381 if (ack_skb)
382 idr_remove(&local->ack_status_frames,
383 info->ack_frame_id);
384 spin_unlock_irqrestore(&local->ack_status_lock, flags);
385
386 if (ack_skb) {
387 if (!dropped) {
388 /* consumes ack_skb */
389 skb_complete_wifi_ack(ack_skb, acked);
390 } else {
391 dev_kfree_skb_any(ack_skb);
392 }
393 }
394 }
395}
396
328/* 397/*
329 * Use a static threshold for now, best value to be determined 398 * Use a static threshold for now, best value to be determined
330 * by testing ... 399 * by testing ...
@@ -516,62 +585,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
516 msecs_to_jiffies(10)); 585 msecs_to_jiffies(10));
517 } 586 }
518 587
519 if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { 588 ieee80211_report_used_skb(local, skb, false);
520 u64 cookie = (unsigned long)skb;
521 bool found = false;
522
523 acked = info->flags & IEEE80211_TX_STAT_ACK;
524
525 rcu_read_lock();
526
527 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
528 if (!sdata->dev)
529 continue;
530
531 if (skb->dev != sdata->dev)
532 continue;
533
534 found = true;
535 break;
536 }
537
538 if (!skb->dev) {
539 sdata = rcu_dereference(local->p2p_sdata);
540 if (sdata)
541 found = true;
542 }
543
544 if (!found)
545 skb->dev = NULL;
546 else if (ieee80211_is_nullfunc(hdr->frame_control) ||
547 ieee80211_is_qos_nullfunc(hdr->frame_control)) {
548 cfg80211_probe_status(sdata->dev, hdr->addr1,
549 cookie, acked, GFP_ATOMIC);
550 } else {
551 cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data,
552 skb->len, acked, GFP_ATOMIC);
553 }
554
555 rcu_read_unlock();
556 }
557
558 if (unlikely(info->ack_frame_id)) {
559 struct sk_buff *ack_skb;
560 unsigned long flags;
561
562 spin_lock_irqsave(&local->ack_status_lock, flags);
563 ack_skb = idr_find(&local->ack_status_frames,
564 info->ack_frame_id);
565 if (ack_skb)
566 idr_remove(&local->ack_status_frames,
567 info->ack_frame_id);
568 spin_unlock_irqrestore(&local->ack_status_lock, flags);
569
570 /* consumes ack_skb */
571 if (ack_skb)
572 skb_complete_wifi_ack(ack_skb,
573 info->flags & IEEE80211_TX_STAT_ACK);
574 }
575 589
576 /* this was a transmitted frame, but now we want to reuse it */ 590 /* this was a transmitted frame, but now we want to reuse it */
577 skb_orphan(skb); 591 skb_orphan(skb);
@@ -647,25 +661,8 @@ EXPORT_SYMBOL(ieee80211_report_low_ack);
647void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) 661void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
648{ 662{
649 struct ieee80211_local *local = hw_to_local(hw); 663 struct ieee80211_local *local = hw_to_local(hw);
650 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
651
652 if (unlikely(info->ack_frame_id)) {
653 struct sk_buff *ack_skb;
654 unsigned long flags;
655
656 spin_lock_irqsave(&local->ack_status_lock, flags);
657 ack_skb = idr_find(&local->ack_status_frames,
658 info->ack_frame_id);
659 if (ack_skb)
660 idr_remove(&local->ack_status_frames,
661 info->ack_frame_id);
662 spin_unlock_irqrestore(&local->ack_status_lock, flags);
663
664 /* consumes ack_skb */
665 if (ack_skb)
666 dev_kfree_skb_any(ack_skb);
667 }
668 664
665 ieee80211_report_used_skb(local, skb, true);
669 dev_kfree_skb_any(skb); 666 dev_kfree_skb_any(skb);
670} 667}
671EXPORT_SYMBOL(ieee80211_free_txskb); 668EXPORT_SYMBOL(ieee80211_free_txskb);