Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Wed, 30 Nov 2011 19:14:42 +0000 (14:14 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 30 Nov 2011 19:14:42 +0000 (14:14 -0500)
1  2 
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/rtlwifi/ps.c
net/mac80211/agg-tx.c

@@@ -16,7 -16,6 +16,7 @@@
  
  #include <linux/io.h>
  #include <linux/slab.h>
 +#include <linux/module.h>
  #include <asm/unaligned.h>
  
  #include "hw.h"
@@@ -1827,7 -1826,8 +1827,8 @@@ static void ath9k_set_power_sleep(struc
        }
  
        /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
-       REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
  }
  
  /*
@@@ -27,7 -27,6 +27,7 @@@
   *
   *****************************************************************************/
  
 +#include <linux/export.h>
  #include "wifi.h"
  #include "base.h"
  #include "ps.h"
@@@ -395,7 -394,7 +395,7 @@@ void rtl_lps_enter(struct ieee80211_hw 
        if (mac->link_state != MAC80211_LINKED)
                return;
  
-       spin_lock(&rtlpriv->locks.lps_lock);
+       spin_lock_irq(&rtlpriv->locks.lps_lock);
  
        /* Idle for a while if we connect to AP a while ago. */
        if (mac->cnt_after_linked >= 2) {
                }
        }
  
-       spin_unlock(&rtlpriv->locks.lps_lock);
+       spin_unlock_irq(&rtlpriv->locks.lps_lock);
  }
  
  /*Leave the leisure power save mode.*/
@@@ -416,8 -415,9 +416,9 @@@ void rtl_lps_leave(struct ieee80211_hw 
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       unsigned long flags;
  
-       spin_lock(&rtlpriv->locks.lps_lock);
+       spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags);
  
        if (ppsc->fwctrl_lps) {
                if (ppsc->dot11_psmode != EACTIVE) {
                        rtl_lps_set_psmode(hw, EACTIVE);
                }
        }
-       spin_unlock(&rtlpriv->locks.lps_lock);
+       spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags);
  }
  
  /* For sw LPS*/
@@@ -539,9 -539,9 +540,9 @@@ void rtl_swlps_rf_awake(struct ieee8021
                RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
        }
  
-       spin_lock(&rtlpriv->locks.lps_lock);
+       spin_lock_irq(&rtlpriv->locks.lps_lock);
        rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
-       spin_unlock(&rtlpriv->locks.lps_lock);
+       spin_unlock_irq(&rtlpriv->locks.lps_lock);
  }
  
  void rtl_swlps_rfon_wq_callback(void *data)
@@@ -574,9 -574,9 +575,9 @@@ void rtl_swlps_rf_sleep(struct ieee8021
        if (rtlpriv->link_info.busytraffic)
                return;
  
-       spin_lock(&rtlpriv->locks.lps_lock);
+       spin_lock_irq(&rtlpriv->locks.lps_lock);
        rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
-       spin_unlock(&rtlpriv->locks.lps_lock);
+       spin_unlock_irq(&rtlpriv->locks.lps_lock);
  
        if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
                !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
diff --combined net/mac80211/agg-tx.c
@@@ -15,7 -15,6 +15,7 @@@
  
  #include <linux/ieee80211.h>
  #include <linux/slab.h>
 +#include <linux/export.h>
  #include <net/mac80211.h>
  #include "ieee80211_i.h"
  #include "driver-ops.h"
@@@ -161,6 -160,12 +161,12 @@@ int ___ieee80211_stop_tx_ba_session(str
                return -ENOENT;
        }
  
+       /* if we're already stopping ignore any new requests to stop */
+       if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
+               spin_unlock_bh(&sta->lock);
+               return -EALREADY;
+       }
        if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
                /* not even started yet! */
                ieee80211_assign_tid_tx(sta, tid, NULL);
                return 0;
        }
  
+       set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
        spin_unlock_bh(&sta->lock);
  
  #ifdef CONFIG_MAC80211_HT_DEBUG
               sta->sta.addr, tid);
  #endif /* CONFIG_MAC80211_HT_DEBUG */
  
-       set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
        del_timer_sync(&tid_tx->addba_resp_timer);
  
        /*
         */
        clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
  
+       /*
+        * There might be a few packets being processed right now (on
+        * another CPU) that have already gotten past the aggregation
+        * check when it was still OPERATIONAL and consequently have
+        * IEEE80211_TX_CTL_AMPDU set. In that case, this code might
+        * call into the driver at the same time or even before the
+        * TX paths calls into it, which could confuse the driver.
+        *
+        * Wait for all currently running TX paths to finish before
+        * telling the driver. New packets will not go through since
+        * the aggregation session is no longer OPERATIONAL.
+        */
+       synchronize_net();
        tid_tx->stop_initiator = initiator;
        tid_tx->tx_stop = tx;
  
@@@ -757,11 -776,27 +777,27 @@@ void ieee80211_process_addba_resp(struc
                goto out;
        }
  
-       del_timer(&tid_tx->addba_resp_timer);
+       del_timer_sync(&tid_tx->addba_resp_timer);
  
  #ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid);
  #endif
+       /*
+        * addba_resp_timer may have fired before we got here, and
+        * caused WANT_STOP to be set. If the stop then was already
+        * processed further, STOPPING might be set.
+        */
+       if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) ||
+           test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
+ #ifdef CONFIG_MAC80211_HT_DEBUG
+               printk(KERN_DEBUG
+                      "got addBA resp for tid %d but we already gave up\n",
+                      tid);
+ #endif
+               goto out;
+       }
        /*
         * IEEE 802.11-2007 7.3.1.14:
         * In an ADDBA Response frame, when the Status Code field