svcrpc: don't hold sv_lock over svc_xprt_put()
[safe/jmp/linux-2.6] / net / mac80211 / status.c
index 800b677..56d5b9a 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright 2002-2005, Instant802 Networks, Inc.
  * Copyright 2005-2006, Devicescape Software, Inc.
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
- * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -53,6 +53,9 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
         * modified/encrypted again.
         */
        memset(&info->control, 0, sizeof(info->control));
+
+       info->control.jiffies = jiffies;
+       info->control.vif = &sta->sdata->vif;
        info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
                       IEEE80211_TX_INTFL_RETRANSMISSION;
 
@@ -185,6 +188,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
        rcu_read_lock();
 
        sband = local->hw.wiphy->bands[info->band];
+       fc = hdr->frame_control;
 
        for_each_sta_info(local, hdr->addr1, sta, tmp) {
                /* skip wrong virtual interface */
@@ -202,8 +206,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                        return;
                }
 
-               fc = hdr->frame_control;
-
                if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
                    (ieee80211_is_data_qos(fc))) {
                        u16 tid, ssn;
@@ -272,6 +274,25 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                        local->dot11FailedCount++;
        }
 
+       if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc) &&
+           (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
+           !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
+           local->ps_sdata && !(local->scanning)) {
+               if (info->flags & IEEE80211_TX_STAT_ACK) {
+                       local->ps_sdata->u.mgd.flags |=
+                                       IEEE80211_STA_NULLFUNC_ACKED;
+                       ieee80211_queue_work(&local->hw,
+                                       &local->dynamic_ps_enable_work);
+               } else
+                       mod_timer(&local->dynamic_ps_timer, jiffies +
+                                       msecs_to_jiffies(10));
+       }
+
+       if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX)
+               cfg80211_action_tx_status(
+                       skb->dev, (unsigned long) skb, skb->data, skb->len,
+                       !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
+
        /* this was a transmitted frame, but now we want to reuse it */
        skb_orphan(skb);