diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-11-06 08:13:34 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-11-09 16:14:09 -0500 |
commit | a729cff8ad5120d0d5172ec28a3843d1cb458f79 (patch) | |
tree | 96e85c0805050ba03a2df2a4278640da8f0454c5 /net/mac80211/status.c | |
parent | 1f074bd8eb7a4a210a5119cd7220f89da6c7a2c3 (diff) |
mac80211: implement wifi TX status
Implement the socket wifi TX status error
queue reflection in mac80211.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/status.c')
-rw-r--r-- | net/mac80211/status.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 94702f103cfc..83b800d17a9a 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -548,6 +548,24 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
548 | } | 548 | } |
549 | } | 549 | } |
550 | 550 | ||
551 | if (unlikely(info->ack_frame_id)) { | ||
552 | struct sk_buff *ack_skb; | ||
553 | unsigned long flags; | ||
554 | |||
555 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
556 | ack_skb = idr_find(&local->ack_status_frames, | ||
557 | info->ack_frame_id); | ||
558 | if (ack_skb) | ||
559 | idr_remove(&local->ack_status_frames, | ||
560 | info->ack_frame_id); | ||
561 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
562 | |||
563 | /* consumes ack_skb */ | ||
564 | if (ack_skb) | ||
565 | skb_complete_wifi_ack(ack_skb, | ||
566 | info->flags & IEEE80211_TX_STAT_ACK); | ||
567 | } | ||
568 | |||
551 | /* this was a transmitted frame, but now we want to reuse it */ | 569 | /* this was a transmitted frame, but now we want to reuse it */ |
552 | skb_orphan(skb); | 570 | skb_orphan(skb); |
553 | 571 | ||
@@ -621,6 +639,26 @@ EXPORT_SYMBOL(ieee80211_report_low_ack); | |||
621 | 639 | ||
622 | void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) | 640 | void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) |
623 | { | 641 | { |
642 | struct ieee80211_local *local = hw_to_local(hw); | ||
643 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
644 | |||
645 | if (unlikely(info->ack_frame_id)) { | ||
646 | struct sk_buff *ack_skb; | ||
647 | unsigned long flags; | ||
648 | |||
649 | spin_lock_irqsave(&local->ack_status_lock, flags); | ||
650 | ack_skb = idr_find(&local->ack_status_frames, | ||
651 | info->ack_frame_id); | ||
652 | if (ack_skb) | ||
653 | idr_remove(&local->ack_status_frames, | ||
654 | info->ack_frame_id); | ||
655 | spin_unlock_irqrestore(&local->ack_status_lock, flags); | ||
656 | |||
657 | /* consumes ack_skb */ | ||
658 | if (ack_skb) | ||
659 | dev_kfree_skb_any(ack_skb); | ||
660 | } | ||
661 | |||
624 | dev_kfree_skb_any(skb); | 662 | dev_kfree_skb_any(skb); |
625 | } | 663 | } |
626 | EXPORT_SYMBOL(ieee80211_free_txskb); | 664 | EXPORT_SYMBOL(ieee80211_free_txskb); |