mac80211: update to wireless-testing 2010-10-15, add a few ath9k fixes and performanc...
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 16 Oct 2010 02:30:30 +0000 (02:30 +0000)
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Sat, 16 Oct 2010 02:30:30 +0000 (02:30 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@23470 3c298f89-4303-0410-b956-a3cf2f4a3e73

35 files changed:
package/mac80211/Makefile
package/mac80211/patches/020-nl80211_fix.patch [deleted file]
package/mac80211/patches/300-ath5k_cc_lock_fix.patch [new file with mode: 0644]
package/mac80211/patches/300-mac80211_release_reorder_fix.patch [deleted file]
package/mac80211/patches/301-ath9k_cc_lock_fix.patch [new file with mode: 0644]
package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch
package/mac80211/patches/406-ath9k-set-AH_USE_EEPROM-only-if-no-platform-data-present.patch
package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch
package/mac80211/patches/408-ath9k_tweak_rx_intr_mitigation.patch
package/mac80211/patches/409-ath9k-add-wndr3700-antenna-initialization.patch
package/mac80211/patches/520-ath9k_common_clockrate.patch [deleted file]
package/mac80211/patches/520-ath9k_ps_survey_fix.patch [new file with mode: 0644]
package/mac80211/patches/521-ath5k_common_clockrate.patch [deleted file]
package/mac80211/patches/521-ath9k_ani_listen_time_fix.patch [new file with mode: 0644]
package/mac80211/patches/522-ath9k_ani_overflow_fix.patch [new file with mode: 0644]
package/mac80211/patches/522-ath_common_counters.patch [deleted file]
package/mac80211/patches/523-ath5k_use_common_counters.patch [deleted file]
package/mac80211/patches/523-ath9k_cycle_counter_lock_fix.patch [new file with mode: 0644]
package/mac80211/patches/524-mac80211_survey_channel_stats.patch [deleted file]
package/mac80211/patches/525-ath9k_channel_count_check.patch [deleted file]
package/mac80211/patches/526-ath9k_survey_channel_stats.patch [deleted file]
package/mac80211/patches/527-ath9k_ps_survey_fix.patch [deleted file]
package/mac80211/patches/528-ath9k_ani_listen_time_fix.patch [deleted file]
package/mac80211/patches/529-ath9k_ani_overflow_fix.patch [deleted file]
package/mac80211/patches/530-ath9k_cycle_counter_lock_fix.patch [deleted file]
package/mac80211/patches/540-ath9k_rc_debugfs.patch [new file with mode: 0644]
package/mac80211/patches/541-ath9k_rc_rate_table_cleanup.patch [new file with mode: 0644]
package/mac80211/patches/542-ath9k_no_mode_idx.patch [new file with mode: 0644]
package/mac80211/patches/550-ath9k_interrupt_mask_optimization.patch [new file with mode: 0644]
package/mac80211/patches/551-ath9k_isr_optimization.patch [new file with mode: 0644]
package/mac80211/patches/552-ath9k_txdesc_optimization.patch [new file with mode: 0644]
package/mac80211/patches/553-ath9k_no_node_rssi.patch [new file with mode: 0644]
package/mac80211/patches/554-ath9k_bt_timer_start.patch [new file with mode: 0644]
package/mac80211/patches/555-ath9k_hw_gettsf32_static.patch [new file with mode: 0644]
package/mac80211/patches/556-ath9k_desc_alignment.patch [new file with mode: 0644]

index 7a095bc..ef219d3 100644 (file)
@@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=mac80211
 
-PKG_VERSION:=2010-10-07
+PKG_VERSION:=2010-10-15
 PKG_RELEASE:=1
 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
 #      http://www.orbit-lab.org/kernel/compat-wireless-2.6/2010/11 \
 #      http://wireless.kernel.org/download/compat-wireless-2.6
-PKG_MD5SUM:=c46aada7c3ba92095dbac0a794538fe5
+PKG_MD5SUM:=3c1cfce9a4a14af671c69dad02b973a4
 
 PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
diff --git a/package/mac80211/patches/020-nl80211_fix.patch b/package/mac80211/patches/020-nl80211_fix.patch
deleted file mode 100644 (file)
index d7fb4df..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/compat/compat-2.6.37.c
-+++ b/compat/compat-2.6.37.c
-@@ -130,7 +130,8 @@ int compat_genl_register_family_with_ops
-               __copy(dumpit);
-               __copy(done);
- #undef __copy
--              ops[i].ops.doit = nl_doit_wrapper;
-+              if (ops[i].doit)
-+                      ops[i].ops.doit = nl_doit_wrapper;
-               ret = genl_register_ops(&family->family, &ops[i].ops);
-               if (ret < 0)
-                       goto error_ops;
diff --git a/package/mac80211/patches/300-ath5k_cc_lock_fix.patch b/package/mac80211/patches/300-ath5k_cc_lock_fix.patch
new file mode 100644 (file)
index 0000000..46f1202
--- /dev/null
@@ -0,0 +1,10 @@
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -3605,6 +3605,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
+       common->ah = sc->ah;
+       common->hw = hw;
+       common->cachelsz = csz << 2; /* convert to bytes */
++      spin_lock_init(&common->cc_lock);
+       /* Initialize device */
+       ret = ath5k_hw_attach(sc);
diff --git a/package/mac80211/patches/300-mac80211_release_reorder_fix.patch b/package/mac80211/patches/300-mac80211_release_reorder_fix.patch
deleted file mode 100644 (file)
index a42d7ec..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-[PATCH] mac80211: hoist sta->lock from reorder release timer
-
-The patch "mac80211: AMPDU rx reorder timeout timer" clashes
-with "mac80211: use netif_receive_skb in ieee80211_rx callpath"
-
-The timer itself is part of the station's private struct and
-it gets killed whenever the station is removed. Therefore
-the extra sta->lock protection (that can interferes with the
-tx path) is not necessary.
-
-Reported-by: Ming Lei <tom.leiming@gmail.com>
-Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
----
---- a/net/mac80211/agg-rx.c
-+++ b/net/mac80211/agg-rx.c
-@@ -129,9 +129,7 @@ static void sta_rx_agg_reorder_timer_exp
-                       timer_to_tid[0]);
-       rcu_read_lock();
--      spin_lock(&sta->lock);
-       ieee80211_release_reorder_timeout(sta, *ptid);
--      spin_unlock(&sta->lock);
-       rcu_read_unlock();
- }
diff --git a/package/mac80211/patches/301-ath9k_cc_lock_fix.patch b/package/mac80211/patches/301-ath9k_cc_lock_fix.patch
new file mode 100644 (file)
index 0000000..b9e82d1
--- /dev/null
@@ -0,0 +1,10 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -577,6 +577,7 @@ static int ath9k_init_softc(u16 devid, s
+       common->hw = sc->hw;
+       common->priv = sc;
+       common->debug_mask = ath9k_debug;
++      spin_lock_init(&common->cc_lock);
+       spin_lock_init(&sc->wiphy_lock);
+       spin_lock_init(&sc->sc_resetlock);
index 7dd3584..1f3712a 100644 (file)
@@ -8,7 +8,7 @@
  #include <asm/unaligned.h>
  
  #include "hw.h"
-@@ -446,8 +447,16 @@ static int ath9k_hw_init_macaddr(struct 
+@@ -449,8 +450,16 @@ static int ath9k_hw_init_macaddr(struct 
                common->macaddr[2 * i] = eeval >> 8;
                common->macaddr[2 * i + 1] = eeval & 0xff;
        }
index 1d90d6c..615bce5 100644 (file)
@@ -10,7 +10,7 @@
  
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -555,6 +555,7 @@ static int ath9k_init_softc(u16 devid, s
+@@ -559,6 +559,7 @@ static int ath9k_init_softc(u16 devid, s
  {
        struct ath_hw *ah = NULL;
        struct ath_common *common;
@@ -18,7 +18,7 @@
        int ret = 0, i;
        int csz = 0;
  
-@@ -566,6 +567,10 @@ static int ath9k_init_softc(u16 devid, s
+@@ -570,6 +571,10 @@ static int ath9k_init_softc(u16 devid, s
        ah->hw_version.subsysid = subsysid;
        sc->sc_ah = ah;
  
@@ -31,7 +31,7 @@
        common->bus_ops = bus_ops;
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -417,10 +417,6 @@ static void ath9k_hw_init_defaults(struc
+@@ -420,10 +420,6 @@ static void ath9k_hw_init_defaults(struc
        ah->hw_version.magic = AR5416_MAGIC;
        ah->hw_version.subvendorid = 0;
  
index 1a5ff02..315e799 100644 (file)
@@ -11,7 +11,7 @@
  #include "hw.h"
  #include "hw-ops.h"
  #include "rc.h"
-@@ -431,18 +433,23 @@ static void ath9k_hw_init_defaults(struc
+@@ -434,18 +436,23 @@ static void ath9k_hw_init_defaults(struc
  static int ath9k_hw_init_macaddr(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
index c2bf818..b9bf3e7 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1414,7 +1414,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1420,7 +1420,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
  
        if (ah->config.rx_intr_mitigation) {
                REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
index b79dd51..2007e4a 100644 (file)
@@ -8,7 +8,7 @@
  #include "ath9k.h"
  
  static char *dev_info = "ath9k";
-@@ -570,6 +571,8 @@ static int ath9k_init_softc(u16 devid, s
+@@ -574,6 +575,8 @@ static int ath9k_init_softc(u16 devid, s
        pdata = (struct ath9k_platform_data *) sc->dev->platform_data;
        if (!pdata)
                ah->ah_flags |= AH_USE_EEPROM;
@@ -17,7 +17,7 @@
  
        common = ath9k_hw_common(ah);
        common->ops = &ath9k_common_ops;
-@@ -699,6 +702,24 @@ void ath9k_set_hw_capab(struct ath_softc
+@@ -704,6 +707,24 @@ void ath9k_set_hw_capab(struct ath_softc
        SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
  }
  
@@ -42,7 +42,7 @@
  int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
                    const struct ath_bus_ops *bus_ops)
  {
-@@ -717,6 +738,9 @@ int ath9k_init_device(u16 devid, struct 
+@@ -722,6 +743,9 @@ int ath9k_init_device(u16 devid, struct 
        common = ath9k_hw_common(ah);
        ath9k_set_hw_capab(sc, hw);
  
@@ -54,7 +54,7 @@
                              ath9k_reg_notifier);
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -637,6 +637,8 @@ struct ath_softc {
+@@ -639,6 +639,8 @@ struct ath_softc {
  
        int beacon_interval;
  
diff --git a/package/mac80211/patches/520-ath9k_common_clockrate.patch b/package/mac80211/patches/520-ath9k_common_clockrate.patch
deleted file mode 100644 (file)
index 3266e0e..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
---- a/drivers/net/wireless/ath/ath.h
-+++ b/drivers/net/wireless/ath/ath.h
-@@ -145,6 +145,8 @@ struct ath_common {
-       DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX);
-       enum ath_crypt_caps crypt_caps;
-+      unsigned int clockrate;
-+
-       struct ath_regulatory regulatory;
-       const struct ath_ops *ops;
-       const struct ath_bus_ops *bus_ops;
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -91,29 +91,32 @@ static void ath9k_hw_ani_cache_ini_regs(
- /* Helper Functions */
- /********************/
--static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
-+static void ath9k_hw_set_clockrate(struct ath_hw *ah)
- {
-       struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-+      struct ath_common *common = ath9k_hw_common(ah);
-+      unsigned int clockrate;
-       if (!ah->curchan) /* should really check for CCK instead */
--              return usecs *ATH9K_CLOCK_RATE_CCK;
--      if (conf->channel->band == IEEE80211_BAND_2GHZ)
--              return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
--
--      if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
--              return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
-+              clockrate = ATH9K_CLOCK_RATE_CCK;
-+      else if (conf->channel->band == IEEE80211_BAND_2GHZ)
-+              clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
-+      else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
-+              clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
-       else
--              return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM;
-+              clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
-+
-+      if (conf_is_ht40(conf))
-+              clockrate *= 2;
-+
-+      common->clockrate = clockrate;
- }
- static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
- {
--      struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-+      struct ath_common *common = ath9k_hw_common(ah);
--      if (conf_is_ht40(conf))
--              return ath9k_hw_mac_clks(ah, usecs) * 2;
--      else
--              return ath9k_hw_mac_clks(ah, usecs);
-+      return usecs * common->clockrate;
- }
- bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
-@@ -1168,6 +1171,7 @@ static bool ath9k_hw_channel_change(stru
-                         "Failed to set channel\n");
-               return false;
-       }
-+      ath9k_hw_set_clockrate(ah);
-       ah->eep_ops->set_txpower(ah, chan,
-                            ath9k_regd_get_ctl(regulatory, chan),
-@@ -1380,6 +1384,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-       if (r)
-               return r;
-+      ath9k_hw_set_clockrate(ah);
-+
-       ENABLE_REGWRITE_BUFFER(ah);
-       for (i = 0; i < AR_NUM_DCU; i++)
---- a/drivers/net/wireless/ath/ath9k/ani.c
-+++ b/drivers/net/wireless/ath/ath9k/ani.c
-@@ -465,35 +465,13 @@ static void ath9k_hw_ani_lower_immunity(
-               ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
- }
--static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah)
--{
--      struct ath9k_channel *chan = ah->curchan;
--      struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
--      u8 clockrate; /* in MHz */
--
--      if (!ah->curchan) /* should really check for CCK instead */
--              clockrate = ATH9K_CLOCK_RATE_CCK;
--      else if (conf->channel->band == IEEE80211_BAND_2GHZ)
--              clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
--      else if (IS_CHAN_A_FAST_CLOCK(ah, chan))
--              clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
--      else
--              clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM;
--
--      if (conf_is_ht40(conf))
--              return clockrate * 2;
--
--      return clockrate;
--}
--
- static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
- {
-+      struct ath_common *common = ath9k_hw_common(ah);
-       int32_t listen_time;
--      int32_t clock_rate;
-       ath9k_hw_update_cycle_counters(ah);
--      clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;
--      listen_time = ah->listen_time / clock_rate;
-+      listen_time = ah->listen_time / (common->clockrate * 1000);
-       ah->listen_time = 0;
-       return listen_time;
diff --git a/package/mac80211/patches/520-ath9k_ps_survey_fix.patch b/package/mac80211/patches/520-ath9k_ps_survey_fix.patch
new file mode 100644 (file)
index 0000000..f130f41
--- /dev/null
@@ -0,0 +1,54 @@
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -122,6 +122,7 @@ bool ath9k_setpower(struct ath_softc *sc
+ void ath9k_ps_wakeup(struct ath_softc *sc)
+ {
++      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       unsigned long flags;
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+@@ -130,18 +131,33 @@ void ath9k_ps_wakeup(struct ath_softc *s
+       ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
++      /*
++       * While the hardware is asleep, the cycle counters contain no
++       * useful data. Better clear them now so that they don't mess up the
++       * ANI or survey data results.
++       */
++      spin_lock(&common->cc_lock);
++      ath_hw_cycle_counters_update(common);
++      memset(&common->cc_survey, 0, sizeof(common->cc_survey));
++      spin_unlock(&common->cc_lock);
++
+  unlock:
+       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ }
+ void ath9k_ps_restore(struct ath_softc *sc)
+ {
++      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       unsigned long flags;
+       spin_lock_irqsave(&sc->sc_pm_lock, flags);
+       if (--sc->ps_usecount != 0)
+               goto unlock;
++      spin_lock(&common->cc_lock);
++      ath_hw_cycle_counters_update(common);
++      spin_unlock(&common->cc_lock);
++
+       if (sc->ps_idle)
+               ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
+       else if (sc->ps_enabled &&
+@@ -197,7 +213,8 @@ static void ath_update_survey_stats(stru
+       struct ath_cycle_counters *cc = &common->cc_survey;
+       unsigned int div = common->clockrate * 1000;
+-      ath_hw_cycle_counters_update(common);
++      if (ah->power_mode == ATH9K_PM_AWAKE)
++              ath_hw_cycle_counters_update(common);
+       if (cc->cycles > 0) {
+               survey->filled |= SURVEY_INFO_CHANNEL_TIME |
diff --git a/package/mac80211/patches/521-ath5k_common_clockrate.patch b/package/mac80211/patches/521-ath5k_common_clockrate.patch
deleted file mode 100644 (file)
index 08c1834..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/pcu.c
-+++ b/drivers/net/wireless/ath/ath5k/pcu.c
-@@ -207,7 +207,8 @@ static int ath5k_hw_set_cts_timeout(stru
-  */
- unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
- {
--      return usec * ath5k_hw_get_clockrate(ah);
-+      struct ath_common *common = ath5k_hw_common(ah);
-+      return usec * common->clockrate;
- }
- /**
-@@ -216,17 +217,19 @@ unsigned int ath5k_hw_htoclock(struct at
-  */
- unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
- {
--      return clock / ath5k_hw_get_clockrate(ah);
-+      struct ath_common *common = ath5k_hw_common(ah);
-+      return clock / common->clockrate;
- }
- /**
-- * ath5k_hw_get_clockrate - Get the clock rate for current mode
-+ * ath5k_hw_set_clockrate - Set common->clockrate for the current channel
-  *
-  * @ah: The &struct ath5k_hw
-  */
--unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah)
-+void ath5k_hw_set_clockrate(struct ath5k_hw *ah)
- {
-       struct ieee80211_channel *channel = ah->ah_current_channel;
-+      struct ath_common *common = ath5k_hw_common(ah);
-       int clock;
-       if (channel->hw_value & CHANNEL_5GHZ)
-@@ -240,7 +243,7 @@ unsigned int ath5k_hw_get_clockrate(stru
-       if (channel->hw_value & CHANNEL_TURBO)
-               clock *= 2;
--      return clock;
-+      common->clockrate = clock;
- }
- /**
---- a/drivers/net/wireless/ath/ath5k/ath5k.h
-+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
-@@ -1201,7 +1201,7 @@ void ath5k_hw_set_ack_bitrate_high(struc
- /* Clock rate related functions */
- unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec);
- unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock);
--unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah);
-+void ath5k_hw_set_clockrate(struct ath5k_hw *ah);
- /* Queue Control Unit, DFS Control Unit Functions */
- int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
---- a/drivers/net/wireless/ath/ath5k/phy.c
-+++ b/drivers/net/wireless/ath/ath5k/phy.c
-@@ -1093,6 +1093,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah
-       ah->ah_current_channel = channel;
-       ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
-+      ath5k_hw_set_clockrate(ah);
-       return 0;
- }
diff --git a/package/mac80211/patches/521-ath9k_ani_listen_time_fix.patch b/package/mac80211/patches/521-ath9k_ani_listen_time_fix.patch
new file mode 100644 (file)
index 0000000..598286e
--- /dev/null
@@ -0,0 +1,52 @@
+--- a/drivers/net/wireless/ath/ath9k/ani.c
++++ b/drivers/net/wireless/ath/ath9k/ani.c
+@@ -633,7 +633,7 @@ void ath9k_ani_reset(struct ath_hw *ah, 
+       REGWRITE_BUFFER_FLUSH(ah);
+ }
+-static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
++static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
+ {
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ar5416AniState *aniState = &ah->curchan->ani;
+@@ -646,10 +646,10 @@ static void ath9k_hw_ani_read_counters(s
+       ath_hw_cycle_counters_update(common);
+       listenTime = ath_hw_get_listen_time(common);
+-      if (listenTime < 0) {
++      if (listenTime <= 0) {
+               ah->stats.ast_ani_lneg++;
+               ath9k_ani_restart(ah);
+-              return;
++              return false;
+       }
+       if (!use_new_ani(ah)) {
+@@ -683,7 +683,7 @@ static void ath9k_hw_ani_read_counters(s
+                       REG_WRITE(ah, AR_PHY_ERR_MASK_2,
+                                 AR_PHY_ERR_CCK_TIMING);
+               }
+-              return;
++              return false;
+       }
+       ofdmPhyErrCnt = phyCnt1 - ofdm_base;
+@@ -695,7 +695,7 @@ static void ath9k_hw_ani_read_counters(s
+       ah->stats.ast_ani_cckerrs +=
+               cckPhyErrCnt - aniState->cckPhyErrCount;
+       aniState->cckPhyErrCount = cckPhyErrCnt;
+-
++      return true;
+ }
+ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
+@@ -711,7 +711,8 @@ void ath9k_hw_ani_monitor(struct ath_hw 
+       if (WARN_ON(!aniState))
+               return;
+-      ath9k_hw_ani_read_counters(ah);
++      if (!ath9k_hw_ani_read_counters(ah))
++              return;
+       ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
+                        aniState->listenTime;
diff --git a/package/mac80211/patches/522-ath9k_ani_overflow_fix.patch b/package/mac80211/patches/522-ath9k_ani_overflow_fix.patch
new file mode 100644 (file)
index 0000000..45bb95d
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath9k/ani.c
++++ b/drivers/net/wireless/ath/ath9k/ani.c
+@@ -664,7 +664,7 @@ static bool ath9k_hw_ani_read_counters(s
+       phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+       phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+-      if (use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
++      if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
+               if (phyCnt1 < ofdm_base) {
+                       ath_print(common, ATH_DBG_ANI,
+                                 "phyCnt1 0x%x, resetting "
diff --git a/package/mac80211/patches/522-ath_common_counters.patch b/package/mac80211/patches/522-ath_common_counters.patch
deleted file mode 100644 (file)
index f719575..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
---- a/drivers/net/wireless/ath/ath.h
-+++ b/drivers/net/wireless/ath/ath.h
-@@ -19,6 +19,7 @@
- #include <linux/skbuff.h>
- #include <linux/if_ether.h>
-+#include <linux/spinlock.h>
- #include <net/mac80211.h>
- /*
-@@ -42,6 +43,13 @@ struct ath_ani {
-       struct timer_list timer;
- };
-+struct ath_cycle_counters {
-+      u32 cycles;
-+      u32 rx_busy;
-+      u32 rx_frame;
-+      u32 tx_frame;
-+};
-+
- enum ath_device_state {
-       ATH_HW_UNAVAILABLE,
-       ATH_HW_INITIALIZED,
-@@ -147,6 +155,10 @@ struct ath_common {
-       unsigned int clockrate;
-+      spinlock_t cc_lock;
-+      struct ath_cycle_counters cc_ani;
-+      struct ath_cycle_counters cc_survey;
-+
-       struct ath_regulatory regulatory;
-       const struct ath_ops *ops;
-       const struct ath_bus_ops *bus_ops;
-@@ -163,5 +175,7 @@ int ath_key_config(struct ath_common *co
-                         struct ieee80211_sta *sta,
-                         struct ieee80211_key_conf *key);
- bool ath_hw_keyreset(struct ath_common *common, u16 entry);
-+void ath_hw_cycle_counters_update(struct ath_common *common);
-+int32_t ath_hw_get_listen_time(struct ath_common *common);
- #endif /* ATH_H */
---- a/drivers/net/wireless/ath/ath9k/ani.c
-+++ b/drivers/net/wireless/ath/ath9k/ani.c
-@@ -465,18 +465,6 @@ static void ath9k_hw_ani_lower_immunity(
-               ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
- }
--static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
--{
--      struct ath_common *common = ath9k_hw_common(ah);
--      int32_t listen_time;
--
--      ath9k_hw_update_cycle_counters(ah);
--      listen_time = ah->listen_time / (common->clockrate * 1000);
--      ah->listen_time = 0;
--
--      return listen_time;
--}
--
- static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
- {
-       struct ar5416AniState *aniState;
-@@ -655,7 +643,9 @@ static void ath9k_hw_ani_read_counters(s
-       u32 phyCnt1, phyCnt2;
-       int32_t listenTime;
--      listenTime = ath9k_hw_ani_get_listen_time(ah);
-+      ath_hw_cycle_counters_update(common);
-+      listenTime = ath_hw_get_listen_time(common);
-+
-       if (listenTime < 0) {
-               ah->stats.ast_ani_lneg++;
-               ath9k_ani_restart(ah);
-@@ -796,54 +786,6 @@ void ath9k_hw_disable_mib_counters(struc
- }
- EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
--void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
--{
--      struct ath_cycle_counters cc;
--      bool clear;
--
--      memcpy(&cc, &ah->cc, sizeof(cc));
--
--      /* freeze counters */
--      REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
--
--      ah->cc.cycles = REG_READ(ah, AR_CCCNT);
--      if (ah->cc.cycles < cc.cycles) {
--              clear = true;
--              goto skip;
--      }
--
--      ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
--      ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
--      ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);
--
--      /* prevent wraparound */
--      if (ah->cc.cycles & BIT(31))
--              clear = true;
--
--#define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
--      CC_DELTA(cycles, AR_CCCNT);
--      CC_DELTA(rx_frame, AR_RFCNT);
--      CC_DELTA(rx_clear, AR_RCCNT);
--      CC_DELTA(tx_frame, AR_TFCNT);
--#undef CC_DELTA
--
--      ah->listen_time += (ah->cc.cycles - cc.cycles) -
--               ((ah->cc.rx_frame - cc.rx_frame) +
--                (ah->cc.tx_frame - cc.tx_frame));
--
--skip:
--      if (clear) {
--              REG_WRITE(ah, AR_CCCNT, 0);
--              REG_WRITE(ah, AR_RFCNT, 0);
--              REG_WRITE(ah, AR_RCCNT, 0);
--              REG_WRITE(ah, AR_TFCNT, 0);
--              memset(&ah->cc, 0, sizeof(ah->cc));
--      }
--
--      /* unfreeze counters */
--      REG_WRITE(ah, AR_MIBC, 0);
--}
--
- /*
-  * Process a MIB interrupt.  We may potentially be invoked because
-  * any of the MIB counters overflow/trigger so don't assume we're
---- a/drivers/net/wireless/ath/ath9k/ani.h
-+++ b/drivers/net/wireless/ath/ath9k/ani.h
-@@ -93,13 +93,6 @@ struct ath9k_mib_stats {
-       u32 beacons;
- };
--struct ath_cycle_counters {
--      u32 cycles;
--      u32 rx_frame;
--      u32 rx_clear;
--      u32 tx_frame;
--};
--
- /* INI default values for ANI registers */
- struct ath9k_ani_default {
-       u16 m1ThreshLow;
-@@ -164,7 +157,6 @@ struct ar5416Stats {
- void ath9k_enable_mib_counters(struct ath_hw *ah);
- void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
--void ath9k_hw_update_cycle_counters(struct ath_hw *ah);
- void ath9k_hw_ani_setup(struct ath_hw *ah);
- void ath9k_hw_ani_init(struct ath_hw *ah);
- int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -1254,13 +1254,12 @@ void ar9003_hw_bb_watchdog_dbg_info(stru
-                 "** BB mode: BB_gen_controls=0x%08x **\n",
-                 REG_READ(ah, AR_PHY_GEN_CTRL));
--      ath9k_hw_update_cycle_counters(ah);
--#define PCT(_field) (ah->cc_delta._field * 100 / ah->cc_delta.cycles)
--      if (ah->cc_delta.cycles)
-+#define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
-+      if (common->cc_survey.cycles)
-               ath_print(common, ATH_DBG_RESET,
-                         "** BB busy times: rx_clear=%d%%, "
-                         "rx_frame=%d%%, tx_frame=%d%% **\n",
--                        PCT(rx_clear), PCT(rx_frame), PCT(tx_frame));
-+                        PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));
-       ath_print(common, ATH_DBG_RESET,
-                 "==== BB update: done ====\n\n");
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -740,8 +740,6 @@ struct ath_hw {
-       int coarse_low[5];
-       int firpwr[5];
-       enum ath9k_ani_cmd ani_function;
--      struct ath_cycle_counters cc, cc_delta;
--      int32_t listen_time;
-       /* Bluetooth coexistance */
-       struct ath_btcoex_hw btcoex_hw;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -400,6 +400,7 @@ void ath_ani_calibrate(unsigned long dat
-       bool aniflag = false;
-       unsigned int timestamp = jiffies_to_msecs(jiffies);
-       u32 cal_interval, short_cal_interval, long_cal_interval;
-+      unsigned long flags;
-       if (ah->caldata && ah->caldata->nfcal_interference)
-               long_cal_interval = ATH_LONG_CALINTERVAL_INT;
-@@ -450,8 +451,11 @@ void ath_ani_calibrate(unsigned long dat
-       /* Skip all processing if there's nothing to do. */
-       if (longcal || shortcal || aniflag) {
-               /* Call ANI routine if necessary */
--              if (aniflag)
-+              if (aniflag) {
-+                      spin_lock_irqsave(&common->cc_lock, flags);
-                       ath9k_hw_ani_monitor(ah, ah->curchan);
-+                      spin_unlock_irqrestore(&common->cc_lock, flags);
-+              }
-               /* Perform calibration if necessary */
-               if (longcal || shortcal) {
-@@ -636,6 +640,7 @@ irqreturn_t ath_isr(int irq, void *dev)
-       struct ath_softc *sc = dev;
-       struct ath_hw *ah = sc->sc_ah;
-+      struct ath_common *common = ath9k_hw_common(ah);
-       enum ath9k_int status;
-       bool sched = false;
-@@ -685,7 +690,12 @@ irqreturn_t ath_isr(int irq, void *dev)
-       if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
-           (status & ATH9K_INT_BB_WATCHDOG)) {
-+
-+              spin_lock(&common->cc_lock);
-+              ath_hw_cycle_counters_update(common);
-               ar9003_hw_bb_watchdog_dbg_info(ah);
-+              spin_unlock(&common->cc_lock);
-+
-               goto chip_reset;
-       }
---- a/drivers/net/wireless/ath/ath9k/reg.h
-+++ b/drivers/net/wireless/ath/ath9k/reg.h
-@@ -107,12 +107,6 @@
- #define AR_RXCFG_DMASZ_256B  6
- #define AR_RXCFG_DMASZ_512B  7
--#define AR_MIBC              0x0040
--#define AR_MIBC_COW          0x00000001
--#define AR_MIBC_FMC          0x00000002
--#define AR_MIBC_CMC          0x00000004
--#define AR_MIBC_MCS          0x00000008
--
- #define AR_TOPS              0x0044
- #define AR_TOPS_MASK         0x0000FFFF
-@@ -1524,11 +1518,6 @@ enum {
- #define AR_TPC_CHIRP           0x003f0000
- #define AR_TPC_CHIRP_S         0x16
--#define AR_TFCNT           0x80ec
--#define AR_RFCNT           0x80f0
--#define AR_RCCNT           0x80f4
--#define AR_CCCNT           0x80f8
--
- #define AR_QUIET1          0x80fc
- #define AR_QUIET1_NEXT_QUIET_S         0
- #define AR_QUIET1_NEXT_QUIET_M         0x0000ffff
---- a/drivers/net/wireless/ath/hw.c
-+++ b/drivers/net/wireless/ath/hw.c
-@@ -124,3 +124,62 @@ void ath_hw_setbssidmask(struct ath_comm
-       REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
- }
- EXPORT_SYMBOL(ath_hw_setbssidmask);
-+
-+
-+/**
-+ * ath_hw_cycle_counters_update - common function to update cycle counters
-+ *
-+ * @common: the ath_common struct for the device.
-+ *
-+ * This function is used to update all cycle counters in one place.
-+ * It has to be called while holding common->cc_lock!
-+ */
-+void ath_hw_cycle_counters_update(struct ath_common *common)
-+{
-+      u32 cycles, busy, rx, tx;
-+      void *ah = common->ah;
-+
-+      /* freeze */
-+      REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
-+
-+      /* read */
-+      cycles = REG_READ(ah, AR_CCCNT);
-+      busy = REG_READ(ah, AR_RCCNT);
-+      rx = REG_READ(ah, AR_RFCNT);
-+      tx = REG_READ(ah, AR_TFCNT);
-+
-+      /* clear */
-+      REG_WRITE(ah, 0, AR_CCCNT);
-+      REG_WRITE(ah, 0, AR_RFCNT);
-+      REG_WRITE(ah, 0, AR_RCCNT);
-+      REG_WRITE(ah, 0, AR_TFCNT);
-+
-+      /* unfreeze */
-+      REG_WRITE(ah, 0, AR_MIBC);
-+
-+      /* update all cycle counters here */
-+      common->cc_ani.cycles += cycles;
-+      common->cc_ani.rx_busy += busy;
-+      common->cc_ani.rx_frame += rx;
-+      common->cc_ani.tx_frame += tx;
-+
-+      common->cc_survey.cycles += cycles;
-+      common->cc_survey.rx_busy += busy;
-+      common->cc_survey.rx_frame += rx;
-+      common->cc_survey.tx_frame += tx;
-+}
-+EXPORT_SYMBOL(ath_hw_cycle_counters_update);
-+
-+int32_t ath_hw_get_listen_time(struct ath_common *common)
-+{
-+      struct ath_cycle_counters *cc = &common->cc_ani;
-+      int32_t listen_time;
-+
-+      listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
-+                    (common->clockrate * 1000);
-+
-+      memset(cc, 0, sizeof(*cc));
-+
-+      return listen_time;
-+}
-+EXPORT_SYMBOL(ath_hw_get_listen_time);
---- a/drivers/net/wireless/ath/reg.h
-+++ b/drivers/net/wireless/ath/reg.h
-@@ -17,6 +17,12 @@
- #ifndef ATH_REGISTERS_H
- #define ATH_REGISTERS_H
-+#define AR_MIBC                       0x0040
-+#define AR_MIBC_COW           0x00000001
-+#define AR_MIBC_FMC           0x00000002
-+#define AR_MIBC_CMC           0x00000004
-+#define AR_MIBC_MCS           0x00000008
-+
- /*
-  * BSSID mask registers. See ath_hw_set_bssid_mask()
-  * for detailed documentation about these registers.
-@@ -24,6 +30,11 @@
- #define AR_BSSMSKL            0x80e0
- #define AR_BSSMSKU            0x80e4
-+#define AR_TFCNT              0x80ec
-+#define AR_RFCNT              0x80f0
-+#define AR_RCCNT              0x80f4
-+#define AR_CCCNT              0x80f8
-+
- #define AR_KEYTABLE_0           0x8800
- #define AR_KEYTABLE(_n)         (AR_KEYTABLE_0 + ((_n)*32))
- #define AR_KEY_CACHE_SIZE       128
diff --git a/package/mac80211/patches/523-ath5k_use_common_counters.patch b/package/mac80211/patches/523-ath5k_use_common_counters.patch
deleted file mode 100644 (file)
index 1899f8d..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/ani.c
-+++ b/drivers/net/wireless/ath/ath5k/ani.c
-@@ -355,41 +355,28 @@ ath5k_ani_lower_immunity(struct ath5k_hw
- /**
-- * ath5k_hw_ani_get_listen_time() - Calculate time spent listening
-+ * ath5k_hw_ani_get_listen_time() - Update counters and return listening time
-  *
-  * Return an approximation of the time spent "listening" in milliseconds (ms)
-- * since the last call of this function by deducting the cycles spent
-- * transmitting and receiving from the total cycle count.
-- * Save profile count values for debugging/statistics and because we might want
-- * to use them later.
-- *
-- * We assume no one else clears these registers!
-+ * since the last call of this function.
-+ * Save a snapshot of the counter values for debugging/statistics.
-  */
- static int
- ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as)
- {
-+      struct ath_common *common = ath5k_hw_common(ah);
-       int listen;
--      /* freeze */
--      ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC);
--      /* read */
--      as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE);
--      as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR);
--      as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX);
--      as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX);
--      /* clear */
--      ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
--      ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
--      ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
--      ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
--      /* un-freeze */
--      ath5k_hw_reg_write(ah, 0, AR5K_MIBC);
-+      spin_lock_bh(&common->cc_lock);
--      /* TODO: where does 44000 come from? (11g clock rate?) */
--      listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000;
-+      ath_hw_cycle_counters_update(common);
-+      memcpy(&as->last_cc, &common->cc_ani, sizeof(as->last_cc));
-+
-+      /* clears common->cc_ani */
-+      listen = ath_hw_get_listen_time(common);
-+
-+      spin_unlock_bh(&common->cc_lock);
--      if (as->pfc_cycles == 0 || listen < 0)
--              return 0;
-       return listen;
- }
---- a/drivers/net/wireless/ath/ath5k/ani.h
-+++ b/drivers/net/wireless/ath/ath5k/ani.h
-@@ -75,10 +75,7 @@ struct ath5k_ani_state {
-       unsigned int            cck_errors;
-       /* debug/statistics only: numbers from last ANI calibration */
--      unsigned int            pfc_tx;
--      unsigned int            pfc_rx;
--      unsigned int            pfc_busy;
--      unsigned int            pfc_cycles;
-+      struct ath_cycle_counters last_cc;
-       unsigned int            last_listen;
-       unsigned int            last_ofdm_errors;
-       unsigned int            last_cck_errors;
---- a/drivers/net/wireless/ath/ath5k/debug.c
-+++ b/drivers/net/wireless/ath/ath5k/debug.c
-@@ -715,20 +715,21 @@ static ssize_t read_file_ani(struct file
-       len += snprintf(buf+len, sizeof(buf)-len,
-                       "beacon RSSI average:\t%d\n",
-                       sc->ah->ah_beacon_rssi_avg.avg);
-+
-+#define CC_PRINT(_struct, _field) \
-+      _struct._field, \
-+      _struct.cycles > 0 ? \
-+      _struct._field*100/_struct.cycles : 0
-+
-       len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
--                      as->pfc_tx,
--                      as->pfc_cycles > 0 ?
--                      as->pfc_tx*100/as->pfc_cycles : 0);
-+                      CC_PRINT(as->last_cc, tx_frame));
-       len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
--                      as->pfc_rx,
--                      as->pfc_cycles > 0 ?
--                      as->pfc_rx*100/as->pfc_cycles : 0);
-+                      CC_PRINT(as->last_cc, rx_frame));
-       len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n",
--                      as->pfc_busy,
--                      as->pfc_cycles > 0 ?
--                      as->pfc_busy*100/as->pfc_cycles : 0);
-+                      CC_PRINT(as->last_cc, rx_busy));
-+#undef CC_PRINT
-       len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n",
--                      as->pfc_cycles);
-+                      as->last_cc.cycles);
-       len += snprintf(buf+len, sizeof(buf)-len,
-                       "listen time\t\t%d\tlast: %d\n",
-                       as->listen_time, as->last_listen);
diff --git a/package/mac80211/patches/523-ath9k_cycle_counter_lock_fix.patch b/package/mac80211/patches/523-ath9k_cycle_counter_lock_fix.patch
new file mode 100644 (file)
index 0000000..9f284df
--- /dev/null
@@ -0,0 +1,12 @@
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -780,7 +780,9 @@ irqreturn_t ath_isr(int irq, void *dev)
+                * it will clear whatever condition caused
+                * the interrupt.
+                */
++              spin_lock(&common->cc_lock);
+               ath9k_hw_proc_mib_event(ah);
++              spin_unlock(&common->cc_lock);
+               ath9k_hw_set_interrupts(ah, ah->imask);
+       }
diff --git a/package/mac80211/patches/524-mac80211_survey_channel_stats.patch b/package/mac80211/patches/524-mac80211_survey_channel_stats.patch
deleted file mode 100644 (file)
index af71234..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
---- a/include/linux/nl80211.h
-+++ b/include/linux/nl80211.h
-@@ -1413,6 +1413,16 @@ enum nl80211_reg_rule_flags {
-  * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
-  * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
-  * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used
-+ * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio
-+ *    spent on this channel
-+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary
-+ *    channel was sensed busy (either due to activity or energy detect)
-+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension
-+ *    channel was sensed busy
-+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent
-+ *    receiving data
-+ * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent
-+ *    transmitting data
-  * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number
-  *    currently defined
-  * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use
-@@ -1422,6 +1432,11 @@ enum nl80211_survey_info {
-       NL80211_SURVEY_INFO_FREQUENCY,
-       NL80211_SURVEY_INFO_NOISE,
-       NL80211_SURVEY_INFO_IN_USE,
-+      NL80211_SURVEY_INFO_CHANNEL_TIME,
-+      NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
-+      NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
-+      NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
-+      NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
-       /* keep last */
-       __NL80211_SURVEY_INFO_AFTER_LAST,
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -295,6 +295,11 @@ struct key_params {
-  *
-  * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
-  * @SURVEY_INFO_IN_USE: channel is currently being used
-+ * @SURVEY_INFO_CHANNEL_TIME: channel active time (in ms) was filled in
-+ * @SURVEY_INFO_CHANNEL_TIME_BUSY: channel busy time was filled in
-+ * @SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: extension channel busy time was filled in
-+ * @SURVEY_INFO_CHANNEL_TIME_RX: channel receive time was filled in
-+ * @SURVEY_INFO_CHANNEL_TIME_TX: channel transmit time was filled in
-  *
-  * Used by the driver to indicate which info in &struct survey_info
-  * it has filled in during the get_survey().
-@@ -302,6 +307,11 @@ struct key_params {
- enum survey_info_flags {
-       SURVEY_INFO_NOISE_DBM = 1<<0,
-       SURVEY_INFO_IN_USE = 1<<1,
-+      SURVEY_INFO_CHANNEL_TIME = 1<<2,
-+      SURVEY_INFO_CHANNEL_TIME_BUSY = 1<<3,
-+      SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 1<<4,
-+      SURVEY_INFO_CHANNEL_TIME_RX = 1<<5,
-+      SURVEY_INFO_CHANNEL_TIME_TX = 1<<6,
- };
- /**
-@@ -311,6 +321,11 @@ enum survey_info_flags {
-  * @filled: bitflag of flags from &enum survey_info_flags
-  * @noise: channel noise in dBm. This and all following fields are
-  *     optional
-+ * @channel_time: amount of time in ms the radio spent on the channel
-+ * @channel_time_busy: amount of time the primary channel was sensed busy
-+ * @channel_time_ext_busy: amount of time the extension channel was sensed busy
-+ * @channel_time_rx: amount of time the radio spent receiving data
-+ * @channel_time_tx: amount of time the radio spent transmitting data
-  *
-  * Used by dump_survey() to report back per-channel survey information.
-  *
-@@ -319,6 +334,11 @@ enum survey_info_flags {
-  */
- struct survey_info {
-       struct ieee80211_channel *channel;
-+      u64 channel_time;
-+      u64 channel_time_busy;
-+      u64 channel_time_ext_busy;
-+      u64 channel_time_rx;
-+      u64 channel_time_tx;
-       u32 filled;
-       s8 noise;
- };
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -3153,6 +3153,21 @@ static int nl80211_send_survey(struct sk
-                           survey->noise);
-       if (survey->filled & SURVEY_INFO_IN_USE)
-               NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE);
-+      if (survey->filled & SURVEY_INFO_CHANNEL_TIME)
-+              NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME,
-+                          survey->channel_time);
-+      if (survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY)
-+              NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
-+                          survey->channel_time_busy);
-+      if (survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY)
-+              NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
-+                          survey->channel_time_ext_busy);
-+      if (survey->filled & SURVEY_INFO_CHANNEL_TIME_RX)
-+              NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
-+                          survey->channel_time_rx);
-+      if (survey->filled & SURVEY_INFO_CHANNEL_TIME_TX)
-+              NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
-+                          survey->channel_time_tx);
-       nla_nest_end(msg, infoattr);
diff --git a/package/mac80211/patches/525-ath9k_channel_count_check.patch b/package/mac80211/patches/525-ath9k_channel_count_check.patch
deleted file mode 100644 (file)
index ae74393..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -61,6 +61,8 @@
- #define ATH9K_RSSI_BAD                        -128
-+#define ATH9K_NUM_CHANNELS    38
-+
- /* Register read/write primitives */
- #define REG_WRITE(_ah, _reg, _val) \
-       ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg))
-@@ -618,7 +620,7 @@ struct ath_hw {
-       struct ath9k_hw_version hw_version;
-       struct ath9k_ops_config config;
-       struct ath9k_hw_capabilities caps;
--      struct ath9k_channel channels[38];
-+      struct ath9k_channel channels[ATH9K_NUM_CHANNELS];
-       struct ath9k_channel *curchan;
-       union {
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -482,6 +482,10 @@ static int ath9k_init_channels_rates(str
- {
-       void *channels;
-+      BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) +
-+                   ARRAY_SIZE(ath9k_5ghz_chantable) !=
-+                   ATH9K_NUM_CHANNELS);
-+
-       if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
-               channels = kmemdup(ath9k_2ghz_chantable,
-                       sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
diff --git a/package/mac80211/patches/526-ath9k_survey_channel_stats.patch b/package/mac80211/patches/526-ath9k_survey_channel_stats.patch
deleted file mode 100644 (file)
index 57ba398..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -594,6 +594,8 @@ struct ath_softc {
-       struct delayed_work wiphy_work;
-       unsigned long wiphy_scheduler_int;
-       int wiphy_scheduler_index;
-+      struct survey_info *cur_survey;
-+      struct survey_info survey[ATH9K_NUM_CHANNELS];
-       struct tasklet_struct intr_tq;
-       struct tasklet_struct bcon_tasklet;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -176,6 +176,44 @@ static void ath_start_ani(struct ath_com
-                       msecs_to_jiffies((u32)ah->config.ani_poll_interval));
- }
-+static void ath_update_survey_nf(struct ath_softc *sc, int channel)
-+{
-+      struct ath_hw *ah = sc->sc_ah;
-+      struct ath9k_channel *chan = &ah->channels[channel];
-+      struct survey_info *survey = &sc->survey[channel];
-+
-+      if (chan->noisefloor) {
-+              survey->filled |= SURVEY_INFO_NOISE_DBM;
-+              survey->noise = chan->noisefloor;
-+      }
-+}
-+
-+static void ath_update_survey_stats(struct ath_softc *sc)
-+{
-+      struct ath_hw *ah = sc->sc_ah;
-+      struct ath_common *common = ath9k_hw_common(ah);
-+      int pos = ah->curchan - &ah->channels[0];
-+      struct survey_info *survey = &sc->survey[pos];
-+      struct ath_cycle_counters *cc = &common->cc_survey;
-+      unsigned int div = common->clockrate * 1000;
-+
-+      ath_hw_cycle_counters_update(common);
-+
-+      if (cc->cycles > 0) {
-+              survey->filled |= SURVEY_INFO_CHANNEL_TIME |
-+                      SURVEY_INFO_CHANNEL_TIME_BUSY |
-+                      SURVEY_INFO_CHANNEL_TIME_RX |
-+                      SURVEY_INFO_CHANNEL_TIME_TX;
-+              survey->channel_time += cc->cycles / div;
-+              survey->channel_time_busy += cc->rx_busy / div;
-+              survey->channel_time_rx += cc->rx_frame / div;
-+              survey->channel_time_tx += cc->tx_frame / div;
-+      }
-+      memset(cc, 0, sizeof(*cc));
-+
-+      ath_update_survey_nf(sc, pos);
-+}
-+
- /*
-  * Set/change channels.  If the channel is really being changed, it's done
-  * by reseting the chip.  To accomplish this we must first cleanup any pending
-@@ -454,6 +492,7 @@ void ath_ani_calibrate(unsigned long dat
-               if (aniflag) {
-                       spin_lock_irqsave(&common->cc_lock, flags);
-                       ath9k_hw_ani_monitor(ah, ah->curchan);
-+                      ath_update_survey_stats(sc);
-                       spin_unlock_irqrestore(&common->cc_lock, flags);
-               }
-@@ -1533,7 +1572,8 @@ static int ath9k_config(struct ieee80211
- {
-       struct ath_wiphy *aphy = hw->priv;
-       struct ath_softc *sc = aphy->sc;
--      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+      struct ath_hw *ah = sc->sc_ah;
-+      struct ath_common *common = ath9k_hw_common(ah);
-       struct ieee80211_conf *conf = &hw->conf;
-       bool disable_radio;
-@@ -1599,6 +1639,11 @@ static int ath9k_config(struct ieee80211
-       if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-               struct ieee80211_channel *curchan = hw->conf.channel;
-               int pos = curchan->hw_value;
-+              int old_pos = -1;
-+              unsigned long flags;
-+
-+              if (ah->curchan)
-+                      old_pos = ah->curchan - &ah->channels[0];
-               aphy->chan_idx = pos;
-               aphy->chan_is_ht = conf_is_ht(conf);
-@@ -1626,12 +1671,45 @@ static int ath9k_config(struct ieee80211
-               ath_update_chainmask(sc, conf_is_ht(conf));
-+              /* update survey stats for the old channel before switching */
-+              spin_lock_irqsave(&common->cc_lock, flags);
-+              ath_update_survey_stats(sc);
-+              spin_unlock_irqrestore(&common->cc_lock, flags);
-+
-+              /*
-+               * If the operating channel changes, change the survey in-use flags
-+               * along with it.
-+               * Reset the survey data for the new channel, unless we're switching
-+               * back to the operating channel from an off-channel operation.
-+               */
-+              if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) &&
-+                  sc->cur_survey != &sc->survey[pos]) {
-+
-+                      if (sc->cur_survey)
-+                              sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
-+
-+                      sc->cur_survey = &sc->survey[pos];
-+
-+                      memset(sc->cur_survey, 0, sizeof(struct survey_info));
-+                      sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
-+              } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
-+                      memset(&sc->survey[pos], 0, sizeof(struct survey_info));
-+              }
-+
-               if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
-                       ath_print(common, ATH_DBG_FATAL,
-                                 "Unable to set channel\n");
-                       mutex_unlock(&sc->mutex);
-                       return -EINVAL;
-               }
-+
-+              /*
-+               * The most recent snapshot of channel->noisefloor for the old
-+               * channel is only available after the hardware reset. Copy it to
-+               * the survey stats now.
-+               */
-+              if (old_pos >= 0)
-+                      ath_update_survey_nf(sc, old_pos);
-       }
- skip_chan_change:
-@@ -2001,9 +2079,15 @@ static int ath9k_get_survey(struct ieee8
- {
-       struct ath_wiphy *aphy = hw->priv;
-       struct ath_softc *sc = aphy->sc;
--      struct ath_hw *ah = sc->sc_ah;
-+      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ieee80211_supported_band *sband;
--      struct ath9k_channel *chan;
-+      struct ieee80211_channel *chan;
-+      unsigned long flags;
-+      int pos;
-+
-+      spin_lock_irqsave(&common->cc_lock, flags);
-+      if (idx == 0)
-+              ath_update_survey_stats(sc);
-       sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ];
-       if (sband && idx >= sband->n_channels) {
-@@ -2014,21 +2098,17 @@ static int ath9k_get_survey(struct ieee8
-       if (!sband)
-               sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ];
--      if (!sband || idx >= sband->n_channels)
--          return -ENOENT;
--
--      survey->channel = &sband->channels[idx];
--      chan = &ah->channels[survey->channel->hw_value];
--      survey->filled = 0;
--
--      if (chan == ah->curchan)
--              survey->filled |= SURVEY_INFO_IN_USE;
--
--      if (chan->noisefloor) {
--              survey->filled |= SURVEY_INFO_NOISE_DBM;
--              survey->noise = chan->noisefloor;
-+      if (!sband || idx >= sband->n_channels) {
-+              spin_unlock_irqrestore(&common->cc_lock, flags);
-+              return -ENOENT;
-       }
-+      chan = &sband->channels[idx];
-+      pos = chan->hw_value;
-+      memcpy(survey, &sc->survey[pos], sizeof(*survey));
-+      survey->channel = chan;
-+      spin_unlock_irqrestore(&common->cc_lock, flags);
-+
-       return 0;
- }
diff --git a/package/mac80211/patches/527-ath9k_ps_survey_fix.patch b/package/mac80211/patches/527-ath9k_ps_survey_fix.patch
deleted file mode 100644 (file)
index f130f41..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -122,6 +122,7 @@ bool ath9k_setpower(struct ath_softc *sc
- void ath9k_ps_wakeup(struct ath_softc *sc)
- {
-+      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       unsigned long flags;
-       spin_lock_irqsave(&sc->sc_pm_lock, flags);
-@@ -130,18 +131,33 @@ void ath9k_ps_wakeup(struct ath_softc *s
-       ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
-+      /*
-+       * While the hardware is asleep, the cycle counters contain no
-+       * useful data. Better clear them now so that they don't mess up the
-+       * ANI or survey data results.
-+       */
-+      spin_lock(&common->cc_lock);
-+      ath_hw_cycle_counters_update(common);
-+      memset(&common->cc_survey, 0, sizeof(common->cc_survey));
-+      spin_unlock(&common->cc_lock);
-+
-  unlock:
-       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
- }
- void ath9k_ps_restore(struct ath_softc *sc)
- {
-+      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       unsigned long flags;
-       spin_lock_irqsave(&sc->sc_pm_lock, flags);
-       if (--sc->ps_usecount != 0)
-               goto unlock;
-+      spin_lock(&common->cc_lock);
-+      ath_hw_cycle_counters_update(common);
-+      spin_unlock(&common->cc_lock);
-+
-       if (sc->ps_idle)
-               ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
-       else if (sc->ps_enabled &&
-@@ -197,7 +213,8 @@ static void ath_update_survey_stats(stru
-       struct ath_cycle_counters *cc = &common->cc_survey;
-       unsigned int div = common->clockrate * 1000;
--      ath_hw_cycle_counters_update(common);
-+      if (ah->power_mode == ATH9K_PM_AWAKE)
-+              ath_hw_cycle_counters_update(common);
-       if (cc->cycles > 0) {
-               survey->filled |= SURVEY_INFO_CHANNEL_TIME |
diff --git a/package/mac80211/patches/528-ath9k_ani_listen_time_fix.patch b/package/mac80211/patches/528-ath9k_ani_listen_time_fix.patch
deleted file mode 100644 (file)
index 598286e..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ani.c
-+++ b/drivers/net/wireless/ath/ath9k/ani.c
-@@ -633,7 +633,7 @@ void ath9k_ani_reset(struct ath_hw *ah, 
-       REGWRITE_BUFFER_FLUSH(ah);
- }
--static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
-+static bool ath9k_hw_ani_read_counters(struct ath_hw *ah)
- {
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ar5416AniState *aniState = &ah->curchan->ani;
-@@ -646,10 +646,10 @@ static void ath9k_hw_ani_read_counters(s
-       ath_hw_cycle_counters_update(common);
-       listenTime = ath_hw_get_listen_time(common);
--      if (listenTime < 0) {
-+      if (listenTime <= 0) {
-               ah->stats.ast_ani_lneg++;
-               ath9k_ani_restart(ah);
--              return;
-+              return false;
-       }
-       if (!use_new_ani(ah)) {
-@@ -683,7 +683,7 @@ static void ath9k_hw_ani_read_counters(s
-                       REG_WRITE(ah, AR_PHY_ERR_MASK_2,
-                                 AR_PHY_ERR_CCK_TIMING);
-               }
--              return;
-+              return false;
-       }
-       ofdmPhyErrCnt = phyCnt1 - ofdm_base;
-@@ -695,7 +695,7 @@ static void ath9k_hw_ani_read_counters(s
-       ah->stats.ast_ani_cckerrs +=
-               cckPhyErrCnt - aniState->cckPhyErrCount;
-       aniState->cckPhyErrCount = cckPhyErrCnt;
--
-+      return true;
- }
- void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
-@@ -711,7 +711,8 @@ void ath9k_hw_ani_monitor(struct ath_hw 
-       if (WARN_ON(!aniState))
-               return;
--      ath9k_hw_ani_read_counters(ah);
-+      if (!ath9k_hw_ani_read_counters(ah))
-+              return;
-       ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 /
-                        aniState->listenTime;
diff --git a/package/mac80211/patches/529-ath9k_ani_overflow_fix.patch b/package/mac80211/patches/529-ath9k_ani_overflow_fix.patch
deleted file mode 100644 (file)
index 45bb95d..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ani.c
-+++ b/drivers/net/wireless/ath/ath9k/ani.c
-@@ -664,7 +664,7 @@ static bool ath9k_hw_ani_read_counters(s
-       phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
-       phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
--      if (use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
-+      if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) {
-               if (phyCnt1 < ofdm_base) {
-                       ath_print(common, ATH_DBG_ANI,
-                                 "phyCnt1 0x%x, resetting "
diff --git a/package/mac80211/patches/530-ath9k_cycle_counter_lock_fix.patch b/package/mac80211/patches/530-ath9k_cycle_counter_lock_fix.patch
deleted file mode 100644 (file)
index 9f284df..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -780,7 +780,9 @@ irqreturn_t ath_isr(int irq, void *dev)
-                * it will clear whatever condition caused
-                * the interrupt.
-                */
-+              spin_lock(&common->cc_lock);
-               ath9k_hw_proc_mib_event(ah);
-+              spin_unlock(&common->cc_lock);
-               ath9k_hw_set_interrupts(ah, ah->imask);
-       }
diff --git a/package/mac80211/patches/540-ath9k_rc_debugfs.patch b/package/mac80211/patches/540-ath9k_rc_debugfs.patch
new file mode 100644 (file)
index 0000000..4e413f8
--- /dev/null
@@ -0,0 +1,363 @@
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -378,95 +378,6 @@ static const struct file_operations fops
+       .owner = THIS_MODULE
+ };
+-void ath_debug_stat_rc(struct ath_softc *sc, int final_rate)
+-{
+-      struct ath_rc_stats *stats;
+-
+-      stats = &sc->debug.stats.rcstats[final_rate];
+-      stats->success++;
+-}
+-
+-void ath_debug_stat_retries(struct ath_softc *sc, int rix,
+-                          int xretries, int retries, u8 per)
+-{
+-      struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix];
+-
+-      stats->xretries += xretries;
+-      stats->retries += retries;
+-      stats->per = per;
+-}
+-
+-static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
+-                              size_t count, loff_t *ppos)
+-{
+-      struct ath_softc *sc = file->private_data;
+-      char *buf;
+-      unsigned int len = 0, max;
+-      int i = 0;
+-      ssize_t retval;
+-
+-      if (sc->cur_rate_table == NULL)
+-              return 0;
+-
+-      max = 80 + sc->cur_rate_table->rate_cnt * 1024 + 1;
+-      buf = kmalloc(max, GFP_KERNEL);
+-      if (buf == NULL)
+-              return -ENOMEM;
+-
+-      len += sprintf(buf, "%6s %6s %6s "
+-                     "%10s %10s %10s %10s\n",
+-                     "HT", "MCS", "Rate",
+-                     "Success", "Retries", "XRetries", "PER");
+-
+-      for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) {
+-              u32 ratekbps = sc->cur_rate_table->info[i].ratekbps;
+-              struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i];
+-              char mcs[5];
+-              char htmode[5];
+-              int used_mcs = 0, used_htmode = 0;
+-
+-              if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) {
+-                      used_mcs = snprintf(mcs, 5, "%d",
+-                              sc->cur_rate_table->info[i].ratecode);
+-
+-                      if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy))
+-                              used_htmode = snprintf(htmode, 5, "HT40");
+-                      else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy))
+-                              used_htmode = snprintf(htmode, 5, "HT20");
+-                      else
+-                              used_htmode = snprintf(htmode, 5, "????");
+-              }
+-
+-              mcs[used_mcs] = '\0';
+-              htmode[used_htmode] = '\0';
+-
+-              len += snprintf(buf + len, max - len,
+-                      "%6s %6s %3u.%d: "
+-                      "%10u %10u %10u %10u\n",
+-                      htmode,
+-                      mcs,
+-                      ratekbps / 1000,
+-                      (ratekbps % 1000) / 100,
+-                      stats->success,
+-                      stats->retries,
+-                      stats->xretries,
+-                      stats->per);
+-      }
+-
+-      if (len > max)
+-              len = max;
+-
+-      retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+-      kfree(buf);
+-      return retval;
+-}
+-
+-static const struct file_operations fops_rcstat = {
+-      .read = read_file_rcstat,
+-      .open = ath9k_debugfs_open,
+-      .owner = THIS_MODULE
+-};
+-
+ static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
+ {
+       switch (state) {
+@@ -1024,10 +935,6 @@ int ath9k_init_debug(struct ath_hw *ah)
+                       sc, &fops_interrupt))
+               goto err;
+-      if (!debugfs_create_file("rcstat", S_IRUSR, sc->debug.debugfs_phy,
+-                      sc, &fops_rcstat))
+-              goto err;
+-
+       if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR,
+                       sc->debug.debugfs_phy, sc, &fops_wiphy))
+               goto err;
+--- a/drivers/net/wireless/ath/ath9k/debug.h
++++ b/drivers/net/wireless/ath/ath9k/debug.h
+@@ -80,13 +80,6 @@ struct ath_interrupt_stats {
+       u32 bb_watchdog;
+ };
+-struct ath_rc_stats {
+-      u32 success;
+-      u32 retries;
+-      u32 xretries;
+-      u8 per;
+-};
+-
+ /**
+  * struct ath_tx_stats - Statistics about TX
+  * @tx_pkts_all:  No. of total frames transmitted, including ones that
+@@ -160,7 +153,6 @@ struct ath_rx_stats {
+ struct ath_stats {
+       struct ath_interrupt_stats istats;
+-      struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
+       struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
+       struct ath_rx_stats rxstats;
+ };
+@@ -177,12 +169,9 @@ void ath9k_exit_debug(struct ath_hw *ah)
+ int ath9k_debug_create_root(void);
+ void ath9k_debug_remove_root(void);
+ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
+-void ath_debug_stat_rc(struct ath_softc *sc, int final_rate);
+ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
+                      struct ath_buf *bf, struct ath_tx_status *ts);
+ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
+-void ath_debug_stat_retries(struct ath_softc *sc, int rix,
+-                          int xretries, int retries, u8 per);
+ #else
+@@ -209,11 +198,6 @@ static inline void ath_debug_stat_interr
+ {
+ }
+-static inline void ath_debug_stat_rc(struct ath_softc *sc,
+-                                   int final_rate)
+-{
+-}
+-
+ static inline void ath_debug_stat_tx(struct ath_softc *sc,
+                                    struct ath_txq *txq,
+                                    struct ath_buf *bf,
+@@ -226,11 +210,6 @@ static inline void ath_debug_stat_rx(str
+ {
+ }
+-static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
+-                                        int xretries, int retries, u8 per)
+-{
+-}
+-
+ #endif /* CONFIG_ATH9K_DEBUGFS */
+ #endif /* DEBUG_H */
+--- a/drivers/net/wireless/ath/ath9k/rc.c
++++ b/drivers/net/wireless/ath/ath9k/rc.c
+@@ -1026,6 +1026,16 @@ static bool ath_rc_update_per(struct ath
+       return state_change;
+ }
++static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix,
++                                 int xretries, int retries, u8 per)
++{
++      struct ath_rc_stats *stats = &rc->rcstats[rix];
++
++      stats->xretries += xretries;
++      stats->retries += retries;
++      stats->per = per;
++}
++
+ /* Update PER, RSSI and whatever else that the code thinks it is doing.
+    If you can make sense of all this, you really need to go out more. */
+@@ -1098,7 +1108,7 @@ static void ath_rc_update_ht(struct ath_
+               ath_rc_priv->per_down_time = now_msec;
+       }
+-      ath_debug_stat_retries(sc, tx_rate, xretries, retries,
++      ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries,
+                              ath_rc_priv->per[tx_rate]);
+ }
+@@ -1294,6 +1304,7 @@ static void ath_rc_init(struct ath_softc
+       ath_rc_sort_validrates(rate_table, ath_rc_priv);
+       ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
+       sc->cur_rate_table = rate_table;
++      ath_rc_priv->rate_table = rate_table;
+       ath_print(common, ATH_DBG_CONFIG,
+                 "RC Initialized with capabilities: 0x%x\n",
+@@ -1340,6 +1351,15 @@ static bool ath_tx_aggr_check(struct ath
+ /* mac80211 Rate Control callbacks */
+ /***********************************/
++static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate)
++{
++      struct ath_rc_stats *stats;
++
++      stats = &rc->rcstats[final_rate];
++      stats->success++;
++}
++
++
+ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
+                         struct ieee80211_sta *sta, void *priv_sta,
+                         struct sk_buff *skb)
+@@ -1419,7 +1439,7 @@ static void ath_tx_status(void *priv, st
+               }
+       }
+-      ath_debug_stat_rc(sc, ath_rc_get_rateindex(sc->cur_rate_table,
++      ath_debug_stat_rc(ath_rc_priv, ath_rc_get_rateindex(sc->cur_rate_table,
+               &tx_info->status.rates[final_ts_idx]));
+ }
+@@ -1521,6 +1541,94 @@ static void ath_rate_update(void *priv, 
+       }
+ }
++#ifdef CONFIG_ATH9K_DEBUGFS
++
++static int ath9k_debugfs_open(struct inode *inode, struct file *file)
++{
++      file->private_data = inode->i_private;
++      return 0;
++}
++
++static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
++                              size_t count, loff_t *ppos)
++{
++      struct ath_rate_priv *rc = file->private_data;
++      char *buf;
++      unsigned int len = 0, max;
++      int i = 0;
++      ssize_t retval;
++
++      if (rc->rate_table == NULL)
++              return 0;
++
++      max = 80 + rc->rate_table->rate_cnt * 1024 + 1;
++      buf = kmalloc(max, GFP_KERNEL);
++      if (buf == NULL)
++              return -ENOMEM;
++
++      len += sprintf(buf, "%6s %6s %6s "
++                     "%10s %10s %10s %10s\n",
++                     "HT", "MCS", "Rate",
++                     "Success", "Retries", "XRetries", "PER");
++
++      for (i = 0; i < rc->rate_table->rate_cnt; i++) {
++              u32 ratekbps = rc->rate_table->info[i].ratekbps;
++              struct ath_rc_stats *stats = &rc->rcstats[i];
++              char mcs[5];
++              char htmode[5];
++              int used_mcs = 0, used_htmode = 0;
++
++              if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) {
++                      used_mcs = snprintf(mcs, 5, "%d",
++                              rc->rate_table->info[i].ratecode);
++
++                      if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy))
++                              used_htmode = snprintf(htmode, 5, "HT40");
++                      else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy))
++                              used_htmode = snprintf(htmode, 5, "HT20");
++                      else
++                              used_htmode = snprintf(htmode, 5, "????");
++              }
++
++              mcs[used_mcs] = '\0';
++              htmode[used_htmode] = '\0';
++
++              len += snprintf(buf + len, max - len,
++                      "%6s %6s %3u.%d: "
++                      "%10u %10u %10u %10u\n",
++                      htmode,
++                      mcs,
++                      ratekbps / 1000,
++                      (ratekbps % 1000) / 100,
++                      stats->success,
++                      stats->retries,
++                      stats->xretries,
++                      stats->per);
++      }
++
++      if (len > max)
++              len = max;
++
++      retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
++      kfree(buf);
++      return retval;
++}
++
++static const struct file_operations fops_rcstat = {
++      .read = read_file_rcstat,
++      .open = ath9k_debugfs_open,
++      .owner = THIS_MODULE
++};
++
++static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
++                                   struct dentry *dir)
++{
++      struct ath_rate_priv *rc = priv_sta;
++      debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat);
++}
++
++#endif /* CONFIG_ATH9K_DEBUGFS */
++
+ static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+ {
+       struct ath_wiphy *aphy = hw->priv;
+@@ -1567,6 +1675,9 @@ static struct rate_control_ops ath_rate_
+       .free = ath_rate_free,
+       .alloc_sta = ath_rate_alloc_sta,
+       .free_sta = ath_rate_free_sta,
++#ifdef CONFIG_ATH9K_DEBUGFS
++      .add_sta_debugfs = ath_rate_add_sta_debugfs,
++#endif
+ };
+ int ath_rate_control_register(void)
+--- a/drivers/net/wireless/ath/ath9k/rc.h
++++ b/drivers/net/wireless/ath/ath9k/rc.h
+@@ -176,6 +176,13 @@ struct ath_rateset {
+       u8 rs_rates[ATH_RATE_MAX];
+ };
++struct ath_rc_stats {
++      u32 success;
++      u32 retries;
++      u32 xretries;
++      u8 per;
++};
++
+ /**
+  * struct ath_rate_priv - Rate Control priv data
+  * @state: RC state
+@@ -212,6 +219,10 @@ struct ath_rate_priv {
+       struct ath_rateset neg_rates;
+       struct ath_rateset neg_ht_rates;
+       struct ath_rate_softc *asc;
++      const struct ath_rate_table *rate_table;
++
++      struct dentry *debugfs_rcstats;
++      struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
+ };
+ #define ATH_TX_INFO_FRAME_TYPE_INTERNAL       (1 << 0)
diff --git a/package/mac80211/patches/541-ath9k_rc_rate_table_cleanup.patch b/package/mac80211/patches/541-ath9k_rc_rate_table_cleanup.patch
new file mode 100644 (file)
index 0000000..b3c0413
--- /dev/null
@@ -0,0 +1,158 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -624,8 +624,6 @@ struct ath_softc {
+       struct ath_rx rx;
+       struct ath_tx tx;
+       struct ath_beacon beacon;
+-      const struct ath_rate_table *cur_rate_table;
+-      enum wireless_mode cur_rate_mode;
+       struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+       struct ath_led radio_led;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -19,36 +19,6 @@
+ #include "ath9k.h"
+ #include "btcoex.h"
+-static void ath_cache_conf_rate(struct ath_softc *sc,
+-                              struct ieee80211_conf *conf)
+-{
+-      switch (conf->channel->band) {
+-      case IEEE80211_BAND_2GHZ:
+-              if (conf_is_ht20(conf))
+-                      sc->cur_rate_mode = ATH9K_MODE_11NG_HT20;
+-              else if (conf_is_ht40_minus(conf))
+-                      sc->cur_rate_mode = ATH9K_MODE_11NG_HT40MINUS;
+-              else if (conf_is_ht40_plus(conf))
+-                      sc->cur_rate_mode = ATH9K_MODE_11NG_HT40PLUS;
+-              else
+-                      sc->cur_rate_mode = ATH9K_MODE_11G;
+-              break;
+-      case IEEE80211_BAND_5GHZ:
+-              if (conf_is_ht20(conf))
+-                      sc->cur_rate_mode = ATH9K_MODE_11NA_HT20;
+-              else if (conf_is_ht40_minus(conf))
+-                      sc->cur_rate_mode = ATH9K_MODE_11NA_HT40MINUS;
+-              else if (conf_is_ht40_plus(conf))
+-                      sc->cur_rate_mode = ATH9K_MODE_11NA_HT40PLUS;
+-              else
+-                      sc->cur_rate_mode = ATH9K_MODE_11A;
+-              break;
+-      default:
+-              BUG_ON(1);
+-              break;
+-      }
+-}
+-
+ static void ath_update_txpow(struct ath_softc *sc)
+ {
+       struct ath_hw *ah = sc->sc_ah;
+@@ -307,7 +277,6 @@ int ath_set_channel(struct ath_softc *sc
+               goto ps_restore;
+       }
+-      ath_cache_conf_rate(sc, &hw->conf);
+       ath_update_txpow(sc);
+       ath9k_hw_set_interrupts(ah, ah->imask);
+@@ -1014,8 +983,6 @@ int ath_reset(struct ath_softc *sc, bool
+        * that changes the channel so update any state that
+        * might change as a result.
+        */
+-      ath_cache_conf_rate(sc, &hw->conf);
+-
+       ath_update_txpow(sc);
+       if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
+@@ -1222,8 +1189,6 @@ static int ath9k_start(struct ieee80211_
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_HT)
+               ah->imask |= ATH9K_INT_CST;
+-      ath_cache_conf_rate(sc, &hw->conf);
+-
+       sc->sc_flags &= ~SC_OP_INVALID;
+       /* Disable BMISS interrupt when we're not associated */
+--- a/drivers/net/wireless/ath/ath9k/rc.c
++++ b/drivers/net/wireless/ath/ath9k/rc.c
+@@ -791,7 +791,7 @@ static void ath_get_rate(void *priv, str
+        */
+       try_per_rate = 4;
+-      rate_table = sc->cur_rate_table;
++      rate_table = ath_rc_priv->rate_table;
+       rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
+       /*
+@@ -1048,7 +1048,7 @@ static void ath_rc_update_ht(struct ath_
+       int rate;
+       u8 last_per;
+       bool state_change = false;
+-      const struct ath_rate_table *rate_table = sc->cur_rate_table;
++      const struct ath_rate_table *rate_table = ath_rc_priv->rate_table;
+       int size = ath_rc_priv->rate_table_size;
+       if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
+@@ -1150,7 +1150,7 @@ static void ath_rc_tx_status(struct ath_
+       u8 flags;
+       u32 i = 0, rix;
+-      rate_table = sc->cur_rate_table;
++      rate_table = ath_rc_priv->rate_table;
+       /*
+        * If the first rate is not the final index, there
+@@ -1231,7 +1231,6 @@ struct ath_rate_table *ath_choose_rate_t
+       ath_print(common, ATH_DBG_CONFIG,
+                 "Choosing rate table for mode: %d\n", mode);
+-      sc->cur_rate_mode = mode;
+       return hw_rate_table[mode];
+ }
+@@ -1303,7 +1302,6 @@ static void ath_rc_init(struct ath_softc
+       ath_rc_priv->max_valid_rate = k;
+       ath_rc_sort_validrates(rate_table, ath_rc_priv);
+       ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
+-      sc->cur_rate_table = rate_table;
+       ath_rc_priv->rate_table = rate_table;
+       ath_print(common, ATH_DBG_CONFIG,
+@@ -1439,8 +1437,9 @@ static void ath_tx_status(void *priv, st
+               }
+       }
+-      ath_debug_stat_rc(ath_rc_priv, ath_rc_get_rateindex(sc->cur_rate_table,
+-              &tx_info->status.rates[final_ts_idx]));
++      ath_debug_stat_rc(ath_rc_priv,
++              ath_rc_get_rateindex(ath_rc_priv->rate_table,
++                      &tx_info->status.rates[final_ts_idx]));
+ }
+ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
+@@ -1480,14 +1479,8 @@ static void ath_rate_init(void *priv, st
+       /* Choose rate table first */
+-      if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) ||
+-          (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
+-          (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
+-              rate_table = ath_choose_rate_table(sc, sband->band,
+-                                    sta->ht_cap.ht_supported, is_cw40);
+-      } else {
+-              rate_table = hw_rate_table[sc->cur_rate_mode];
+-      }
++      rate_table = ath_choose_rate_table(sc, sband->band,
++                            sta->ht_cap.ht_supported, is_cw40);
+       ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi);
+       ath_rc_init(sc, priv_sta, sband, sta, rate_table);
+@@ -1536,7 +1529,6 @@ static void ath_rate_update(void *priv, 
+                       ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
+                                 "Operating HT Bandwidth changed to: %d\n",
+                                 sc->hw->conf.channel_type);
+-                      sc->cur_rate_table = hw_rate_table[sc->cur_rate_mode];
+               }
+       }
+ }
diff --git a/package/mac80211/patches/542-ath9k_no_mode_idx.patch b/package/mac80211/patches/542-ath9k_no_mode_idx.patch
new file mode 100644 (file)
index 0000000..ae68546
--- /dev/null
@@ -0,0 +1,247 @@
+--- a/drivers/net/wireless/ath/ath9k/rc.c
++++ b/drivers/net/wireless/ath/ath9k/rc.c
+@@ -378,17 +378,6 @@ static const struct ath_rate_table ar541
+       0,   /* Phy rates allowed initially */
+ };
+-static const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX] = {
+-      [ATH9K_MODE_11A] = &ar5416_11a_ratetable,
+-      [ATH9K_MODE_11G] = &ar5416_11g_ratetable,
+-      [ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable,
+-      [ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable,
+-      [ATH9K_MODE_11NA_HT40PLUS] = &ar5416_11na_ratetable,
+-      [ATH9K_MODE_11NA_HT40MINUS] = &ar5416_11na_ratetable,
+-      [ATH9K_MODE_11NG_HT40PLUS] = &ar5416_11ng_ratetable,
+-      [ATH9K_MODE_11NG_HT40MINUS] = &ar5416_11ng_ratetable,
+-};
+-
+ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
+                               struct ieee80211_tx_rate *rate);
+@@ -1200,38 +1189,23 @@ static void ath_rc_tx_status(struct ath_
+ static const
+ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
+                                            enum ieee80211_band band,
+-                                           bool is_ht,
+-                                           bool is_cw_40)
++                                           bool is_ht)
+ {
+-      int mode = 0;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       switch(band) {
+       case IEEE80211_BAND_2GHZ:
+-              mode = ATH9K_MODE_11G;
+               if (is_ht)
+-                      mode = ATH9K_MODE_11NG_HT20;
+-              if (is_cw_40)
+-                      mode = ATH9K_MODE_11NG_HT40PLUS;
+-              break;
++                      return &ar5416_11ng_ratetable;
++              return &ar5416_11g_ratetable;
+       case IEEE80211_BAND_5GHZ:
+-              mode = ATH9K_MODE_11A;
+               if (is_ht)
+-                      mode = ATH9K_MODE_11NA_HT20;
+-              if (is_cw_40)
+-                      mode = ATH9K_MODE_11NA_HT40PLUS;
+-              break;
++                      return &ar5416_11na_ratetable;
++              return &ar5416_11a_ratetable;
+       default:
+               ath_print(common, ATH_DBG_CONFIG, "Invalid band\n");
+               return NULL;
+       }
+-
+-      BUG_ON(mode >= ATH9K_MODE_MAX);
+-
+-      ath_print(common, ATH_DBG_CONFIG,
+-                "Choosing rate table for mode: %d\n", mode);
+-
+-      return hw_rate_table[mode];
+ }
+ static void ath_rc_init(struct ath_softc *sc,
+@@ -1480,7 +1454,7 @@ static void ath_rate_init(void *priv, st
+       /* Choose rate table first */
+       rate_table = ath_choose_rate_table(sc, sband->band,
+-                            sta->ht_cap.ht_supported, is_cw40);
++                            sta->ht_cap.ht_supported);
+       ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi);
+       ath_rc_init(sc, priv_sta, sband, sta, rate_table);
+@@ -1520,8 +1494,7 @@ static void ath_rate_update(void *priv, 
+               if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) {
+                       rate_table = ath_choose_rate_table(sc, sband->band,
+-                                                 sta->ht_cap.ht_supported,
+-                                                 oper_cw40);
++                                                 sta->ht_cap.ht_supported);
+                       ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta,
+                                                  oper_cw40, oper_sgi);
+                       ath_rc_init(sc, priv_sta, sband, sta, rate_table);
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1812,37 +1812,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+               return -EINVAL;
+       }
+-      bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
++      if (eeval & AR5416_OPFLAGS_11A)
++              pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
+-      if (eeval & AR5416_OPFLAGS_11A) {
+-              set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
+-              if (ah->config.ht_enable) {
+-                      if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
+-                              set_bit(ATH9K_MODE_11NA_HT20,
+-                                      pCap->wireless_modes);
+-                      if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
+-                              set_bit(ATH9K_MODE_11NA_HT40PLUS,
+-                                      pCap->wireless_modes);
+-                              set_bit(ATH9K_MODE_11NA_HT40MINUS,
+-                                      pCap->wireless_modes);
+-                      }
+-              }
+-      }
+-
+-      if (eeval & AR5416_OPFLAGS_11G) {
+-              set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
+-              if (ah->config.ht_enable) {
+-                      if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
+-                              set_bit(ATH9K_MODE_11NG_HT20,
+-                                      pCap->wireless_modes);
+-                      if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
+-                              set_bit(ATH9K_MODE_11NG_HT40PLUS,
+-                                      pCap->wireless_modes);
+-                              set_bit(ATH9K_MODE_11NG_HT40MINUS,
+-                                      pCap->wireless_modes);
+-                      }
+-              }
+-      }
++      if (eeval & AR5416_OPFLAGS_11G)
++              pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
+       pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
+       /*
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -164,18 +164,6 @@ enum ath_ini_subsys {
+       ATH_INI_NUM_SPLIT,
+ };
+-enum wireless_mode {
+-      ATH9K_MODE_11A = 0,
+-      ATH9K_MODE_11G,
+-      ATH9K_MODE_11NA_HT20,
+-      ATH9K_MODE_11NG_HT20,
+-      ATH9K_MODE_11NA_HT40PLUS,
+-      ATH9K_MODE_11NA_HT40MINUS,
+-      ATH9K_MODE_11NG_HT40PLUS,
+-      ATH9K_MODE_11NG_HT40MINUS,
+-      ATH9K_MODE_MAX,
+-};
+-
+ enum ath9k_hw_caps {
+       ATH9K_HW_CAP_HT                         = BIT(0),
+       ATH9K_HW_CAP_RFSILENT                   = BIT(1),
+@@ -190,11 +178,12 @@ enum ath9k_hw_caps {
+       ATH9K_HW_CAP_SGI_20                     = BIT(10),
+       ATH9K_HW_CAP_PAPRD                      = BIT(11),
+       ATH9K_HW_CAP_ANT_DIV_COMB               = BIT(12),
++      ATH9K_HW_CAP_2GHZ                       = BIT(13),
++      ATH9K_HW_CAP_5GHZ                       = BIT(14),
+ };
+ struct ath9k_hw_capabilities {
+       u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
+-      DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */
+       u16 total_queues;
+       u16 keycache_size;
+       u16 low_5ghz_chan, high_5ghz_chan;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -486,7 +486,7 @@ static int ath9k_init_channels_rates(str
+                    ARRAY_SIZE(ath9k_5ghz_chantable) !=
+                    ATH9K_NUM_CHANNELS);
+-      if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
++      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
+               channels = kmemdup(ath9k_2ghz_chantable,
+                       sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
+               if (!channels)
+@@ -501,7 +501,7 @@ static int ath9k_init_channels_rates(str
+                       ARRAY_SIZE(ath9k_legacy_rates);
+       }
+-      if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
++      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
+               channels = kmemdup(ath9k_5ghz_chantable,
+                       sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
+               if (!channels) {
+@@ -690,17 +690,17 @@ void ath9k_set_hw_capab(struct ath_softc
+       hw->rate_control_algorithm = "ath9k_rate_control";
+ #endif
+-      if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
++      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+               hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+                       &sc->sbands[IEEE80211_BAND_2GHZ];
+-      if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
++      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+               hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+                       &sc->sbands[IEEE80211_BAND_5GHZ];
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+-              if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
++              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+                       setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+-              if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
++              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+                       setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+       }
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -566,7 +566,7 @@ static void ath9k_init_crypto(struct ath
+ static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
+ {
+-      if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) {
++      if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
+               priv->sbands[IEEE80211_BAND_2GHZ].channels =
+                       ath9k_2ghz_channels;
+               priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
+@@ -577,7 +577,7 @@ static void ath9k_init_channels_rates(st
+                       ARRAY_SIZE(ath9k_legacy_rates);
+       }
+-      if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) {
++      if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
+               priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels;
+               priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
+               priv->sbands[IEEE80211_BAND_5GHZ].n_channels =
+@@ -740,18 +740,18 @@ static void ath9k_set_hw_capab(struct at
+       hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) +
+               sizeof(struct htc_frame_hdr) + 4;
+-      if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
++      if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+               hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+                       &priv->sbands[IEEE80211_BAND_2GHZ];
+-      if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
++      if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+               hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+                       &priv->sbands[IEEE80211_BAND_5GHZ];
+       if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+-              if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes))
++              if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+                       setup_ht_cap(priv,
+                                    &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+-              if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes))
++              if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+                       setup_ht_cap(priv,
+                                    &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+       }
diff --git a/package/mac80211/patches/550-ath9k_interrupt_mask_optimization.patch b/package/mac80211/patches/550-ath9k_interrupt_mask_optimization.patch
new file mode 100644 (file)
index 0000000..d6a1d75
--- /dev/null
@@ -0,0 +1,282 @@
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -117,12 +117,11 @@ EXPORT_SYMBOL(ath9k_hw_numtxpending);
+ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
+ {
+       u32 txcfg, curLevel, newLevel;
+-      enum ath9k_int omask;
+       if (ah->tx_trig_level >= ah->config.max_txtrig_level)
+               return false;
+-      omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL);
++      ath9k_hw_disable_interrupts(ah);
+       txcfg = REG_READ(ah, AR_TXCFG);
+       curLevel = MS(txcfg, AR_FTRIG);
+@@ -136,7 +135,7 @@ bool ath9k_hw_updatetxtriglevel(struct a
+               REG_WRITE(ah, AR_TXCFG,
+                         (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
+-      ath9k_hw_set_interrupts(ah, omask);
++      ath9k_hw_enable_interrupts(ah);
+       ah->tx_trig_level = newLevel;
+@@ -849,28 +848,59 @@ bool ath9k_hw_intrpend(struct ath_hw *ah
+ }
+ EXPORT_SYMBOL(ath9k_hw_intrpend);
+-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
+-                                            enum ath9k_int ints)
++void ath9k_hw_disable_interrupts(struct ath_hw *ah)
++{
++      struct ath_common *common = ath9k_hw_common(ah);
++
++      ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
++      REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
++      (void) REG_READ(ah, AR_IER);
++      if (!AR_SREV_9100(ah)) {
++              REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
++              (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
++
++              REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
++              (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
++      }
++}
++EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
++
++void ath9k_hw_enable_interrupts(struct ath_hw *ah)
++{
++      struct ath_common *common = ath9k_hw_common(ah);
++
++      if (!(ah->imask & ATH9K_INT_GLOBAL))
++              return;
++
++      ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
++      REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
++      if (!AR_SREV_9100(ah)) {
++              REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
++                        AR_INTR_MAC_IRQ);
++              REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
++
++
++              REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
++                        AR_INTR_SYNC_DEFAULT);
++              REG_WRITE(ah, AR_INTR_SYNC_MASK,
++                        AR_INTR_SYNC_DEFAULT);
++      }
++      ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
++                REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
++}
++EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
++
++void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
+ {
+       enum ath9k_int omask = ah->imask;
+       u32 mask, mask2;
+       struct ath9k_hw_capabilities *pCap = &ah->caps;
+       struct ath_common *common = ath9k_hw_common(ah);
+-      ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
+-
+-      if (omask & ATH9K_INT_GLOBAL) {
+-              ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
+-              REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+-              (void) REG_READ(ah, AR_IER);
+-              if (!AR_SREV_9100(ah)) {
+-                      REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+-                      (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
++      if (!(ints & ATH9K_INT_GLOBAL))
++              ath9k_hw_enable_interrupts(ah);
+-                      REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+-                      (void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
+-              }
+-      }
++      ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
+       /* TODO: global int Ref count */
+       mask = ints & ATH9K_INT_COMMON;
+@@ -946,24 +976,8 @@ enum ath9k_int ath9k_hw_set_interrupts(s
+                       REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
+       }
+-      if (ints & ATH9K_INT_GLOBAL) {
+-              ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
+-              REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+-              if (!AR_SREV_9100(ah)) {
+-                      REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
+-                                AR_INTR_MAC_IRQ);
+-                      REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+-
+-
+-                      REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
+-                                AR_INTR_SYNC_DEFAULT);
+-                      REG_WRITE(ah, AR_INTR_SYNC_MASK,
+-                                AR_INTR_SYNC_DEFAULT);
+-              }
+-              ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
+-                        REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
+-      }
++      ath9k_hw_enable_interrupts(ah);
+-      return omask;
++      return;
+ }
+ EXPORT_SYMBOL(ath9k_hw_set_interrupts);
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -669,6 +669,7 @@ enum ath9k_key_type {
+ struct ath_hw;
+ struct ath9k_channel;
++enum ath9k_int;
+ u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
+ void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
+@@ -700,8 +701,9 @@ int ath9k_hw_beaconq_setup(struct ath_hw
+ /* Interrupt Handling */
+ bool ath9k_hw_intrpend(struct ath_hw *ah);
+-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
+-                                     enum ath9k_int ints);
++void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
++void ath9k_hw_enable_interrupts(struct ath_hw *ah);
++void ath9k_hw_disable_interrupts(struct ath_hw *ah);
+ void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -237,7 +237,7 @@ int ath_set_channel(struct ath_softc *sc
+        * hardware at the new frequency, and then re-enable
+        * the relevant bits of the h/w.
+        */
+-      ath9k_hw_set_interrupts(ah, 0);
++      ath9k_hw_disable_interrupts(ah);
+       ath_drain_all_txq(sc, false);
+       stopped = ath_stoprecv(sc);
+@@ -644,7 +644,7 @@ void ath9k_tasklet(unsigned long data)
+                       ath_gen_timer_isr(sc->sc_ah);
+       /* re-enable hardware interrupt */
+-      ath9k_hw_set_interrupts(ah, ah->imask);
++      ath9k_hw_enable_interrupts(ah);
+       ath9k_ps_restore(sc);
+ }
+@@ -743,7 +743,7 @@ irqreturn_t ath_isr(int irq, void *dev)
+                * interrupt; otherwise it will continue to
+                * fire.
+                */
+-              ath9k_hw_set_interrupts(ah, 0);
++              ath9k_hw_disable_interrupts(ah);
+               /*
+                * Let the hal handle the event. We assume
+                * it will clear whatever condition caused
+@@ -752,7 +752,7 @@ irqreturn_t ath_isr(int irq, void *dev)
+               spin_lock(&common->cc_lock);
+               ath9k_hw_proc_mib_event(ah);
+               spin_unlock(&common->cc_lock);
+-              ath9k_hw_set_interrupts(ah, ah->imask);
++              ath9k_hw_enable_interrupts(ah);
+       }
+       if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+@@ -769,8 +769,8 @@ chip_reset:
+       ath_debug_stat_interrupt(sc, status);
+       if (sched) {
+-              /* turn off every interrupt except SWBA */
+-              ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA));
++              /* turn off every interrupt */
++              ath9k_hw_disable_interrupts(ah);
+               tasklet_schedule(&sc->intr_tq);
+       }
+@@ -925,7 +925,7 @@ void ath_radio_disable(struct ath_softc 
+       }
+       /* Disable interrupts */
+-      ath9k_hw_set_interrupts(ah, 0);
++      ath9k_hw_disable_interrupts(ah);
+       ath_drain_all_txq(sc, false);   /* clear pending tx frames */
+       ath_stoprecv(sc);               /* turn off frame recv */
+@@ -962,7 +962,7 @@ int ath_reset(struct ath_softc *sc, bool
+       ieee80211_stop_queues(hw);
+-      ath9k_hw_set_interrupts(ah, 0);
++      ath9k_hw_disable_interrupts(ah);
+       ath_drain_all_txq(sc, retry_tx);
+       ath_stoprecv(sc);
+       ath_flushrecv(sc);
+@@ -1367,7 +1367,7 @@ static void ath9k_stop(struct ieee80211_
+       /* make sure h/w will not generate any interrupt
+        * before setting the invalid flag. */
+-      ath9k_hw_set_interrupts(ah, 0);
++      ath9k_hw_disable_interrupts(ah);
+       if (!(sc->sc_flags & SC_OP_INVALID)) {
+               ath_drain_all_txq(sc, false);
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -500,10 +500,10 @@ static void ath_beacon_config_ap(struct 
+       /* Set the computed AP beacon timers */
+-      ath9k_hw_set_interrupts(ah, 0);
++      ath9k_hw_disable_interrupts(ah);
+       ath9k_beacon_init(sc, nexttbtt, intval);
+       sc->beacon.bmisscnt = 0;
+-      ath9k_hw_set_interrupts(ah, ah->imask);
++      ath9k_hw_enable_interrupts(ah);
+       /* Clear the reset TSF flag, so that subsequent beacon updation
+          will not reset the HW TSF. */
+@@ -635,7 +635,7 @@ static void ath_beacon_config_sta(struct
+       /* Set the computed STA beacon timers */
+-      ath9k_hw_set_interrupts(ah, 0);
++      ath9k_hw_disable_interrupts(ah);
+       ath9k_hw_set_sta_beacon_timers(ah, &bs);
+       ah->imask |= ATH9K_INT_BMISS;
+       ath9k_hw_set_interrupts(ah, ah->imask);
+@@ -683,10 +683,10 @@ static void ath_beacon_config_adhoc(stru
+       /* Set the computed ADHOC beacon timers */
+-      ath9k_hw_set_interrupts(ah, 0);
++      ath9k_hw_disable_interrupts(ah);
+       ath9k_beacon_init(sc, nexttbtt, intval);
+       sc->beacon.bmisscnt = 0;
+-      ath9k_hw_set_interrupts(ah, ah->imask);
++      ath9k_hw_enable_interrupts(ah);
+ }
+ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -275,7 +275,7 @@ static void ath9k_gen_timer_start(struct
+       ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
+       if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
+-              ath9k_hw_set_interrupts(ah, 0);
++              ath9k_hw_disable_interrupts(ah);
+               ah->imask |= ATH9K_INT_GENTIMER;
+               ath9k_hw_set_interrupts(ah, ah->imask);
+       }
+@@ -289,7 +289,7 @@ static void ath9k_gen_timer_stop(struct 
+       /* if no timer is enabled, turn off interrupt mask */
+       if (timer_table->timer_mask.val == 0) {
+-              ath9k_hw_set_interrupts(ah, 0);
++              ath9k_hw_disable_interrupts(ah);
+               ah->imask &= ~ATH9K_INT_GENTIMER;
+               ath9k_hw_set_interrupts(ah, ah->imask);
+       }
diff --git a/package/mac80211/patches/551-ath9k_isr_optimization.patch b/package/mac80211/patches/551-ath9k_isr_optimization.patch
new file mode 100644 (file)
index 0000000..dc267f3
--- /dev/null
@@ -0,0 +1,60 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+@@ -90,13 +90,10 @@ static bool ar9002_hw_get_isr(struct ath
+               *masked = isr & ATH9K_INT_COMMON;
+-              if (ah->config.rx_intr_mitigation) {
+-                      if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
+-                              *masked |= ATH9K_INT_RX;
+-              }
+-
+-              if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
++              if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM |
++                         AR_ISR_RXOK | AR_ISR_RXERR))
+                       *masked |= ATH9K_INT_RX;
++
+               if (isr &
+                   (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
+                    AR_ISR_TXEOL)) {
+@@ -118,14 +115,6 @@ static bool ar9002_hw_get_isr(struct ath
+                                 "receive FIFO overrun interrupt\n");
+               }
+-              if (!AR_SREV_9100(ah)) {
+-                      if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+-                              u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
+-                              if (isr5 & AR_ISR_S5_TIM_TIMER)
+-                                      *masked |= ATH9K_INT_TIM_TIMER;
+-                      }
+-              }
+-
+               *masked |= mask2;
+       }
+@@ -136,17 +125,18 @@ static bool ar9002_hw_get_isr(struct ath
+               u32 s5_s;
+               s5_s = REG_READ(ah, AR_ISR_S5_S);
+-              if (isr & AR_ISR_GENTMR) {
+-                      ah->intr_gen_timer_trigger =
++              ah->intr_gen_timer_trigger =
+                               MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
+-                      ah->intr_gen_timer_thresh =
+-                              MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
++              ah->intr_gen_timer_thresh =
++                      MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
+-                      if (ah->intr_gen_timer_trigger)
+-                              *masked |= ATH9K_INT_GENTIMER;
++              if (ah->intr_gen_timer_trigger)
++                      *masked |= ATH9K_INT_GENTIMER;
+-              }
++              if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
++                  !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
++                      *masked |= ATH9K_INT_TIM_TIMER;
+       }
+       if (sync_cause) {
diff --git a/package/mac80211/patches/552-ath9k_txdesc_optimization.patch b/package/mac80211/patches/552-ath9k_txdesc_optimization.patch
new file mode 100644 (file)
index 0000000..75d9f65
--- /dev/null
@@ -0,0 +1,248 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+@@ -208,77 +208,68 @@ static int ar9002_hw_proc_txdesc(struct 
+                                struct ath_tx_status *ts)
+ {
+       struct ar5416_desc *ads = AR5416DESC(ds);
++      u32 status;
+-      if ((ads->ds_txstatus9 & AR_TxDone) == 0)
++      status = ACCESS_ONCE(ads->ds_txstatus9);
++      if ((status & AR_TxDone) == 0)
+               return -EINPROGRESS;
+-      ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
+       ts->ts_tstamp = ads->AR_SendTimestamp;
+       ts->ts_status = 0;
+       ts->ts_flags = 0;
+-      if (ads->ds_txstatus1 & AR_FrmXmitOK)
++      if (status & AR_TxOpExceeded)
++              ts->ts_status |= ATH9K_TXERR_XTXOP;
++      ts->tid = MS(status, AR_TxTid);
++      ts->ts_rateindex = MS(status, AR_FinalTxIdx);
++      ts->ts_seqnum = MS(status, AR_SeqNum);
++
++      status = ACCESS_ONCE(ads->ds_txstatus0);
++      ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
++      ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
++      ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
++      if (status & AR_TxBaStatus) {
++              ts->ts_flags |= ATH9K_TX_BA;
++              ts->ba_low = ads->AR_BaBitmapLow;
++              ts->ba_high = ads->AR_BaBitmapHigh;
++      }
++
++      status = ACCESS_ONCE(ads->ds_txstatus1);
++      if (status & AR_FrmXmitOK)
+               ts->ts_status |= ATH9K_TX_ACKED;
+-      if (ads->ds_txstatus1 & AR_ExcessiveRetries)
++      if (status & AR_ExcessiveRetries)
+               ts->ts_status |= ATH9K_TXERR_XRETRY;
+-      if (ads->ds_txstatus1 & AR_Filtered)
++      if (status & AR_Filtered)
+               ts->ts_status |= ATH9K_TXERR_FILT;
+-      if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
++      if (status & AR_FIFOUnderrun) {
+               ts->ts_status |= ATH9K_TXERR_FIFO;
+               ath9k_hw_updatetxtriglevel(ah, true);
+       }
+-      if (ads->ds_txstatus9 & AR_TxOpExceeded)
+-              ts->ts_status |= ATH9K_TXERR_XTXOP;
+-      if (ads->ds_txstatus1 & AR_TxTimerExpired)
++      if (status & AR_TxTimerExpired)
+               ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+-
+-      if (ads->ds_txstatus1 & AR_DescCfgErr)
++      if (status & AR_DescCfgErr)
+               ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+-      if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
++      if (status & AR_TxDataUnderrun) {
+               ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+               ath9k_hw_updatetxtriglevel(ah, true);
+       }
+-      if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
++      if (status & AR_TxDelimUnderrun) {
+               ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+               ath9k_hw_updatetxtriglevel(ah, true);
+       }
+-      if (ads->ds_txstatus0 & AR_TxBaStatus) {
+-              ts->ts_flags |= ATH9K_TX_BA;
+-              ts->ba_low = ads->AR_BaBitmapLow;
+-              ts->ba_high = ads->AR_BaBitmapHigh;
+-      }
+-
+-      ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
+-      switch (ts->ts_rateindex) {
+-      case 0:
+-              ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
+-              break;
+-      case 1:
+-              ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
+-              break;
+-      case 2:
+-              ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
+-              break;
+-      case 3:
+-              ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
+-              break;
+-      }
++      ts->ts_shortretry = MS(status, AR_RTSFailCnt);
++      ts->ts_longretry = MS(status, AR_DataFailCnt);
++      ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
++
++      status = ACCESS_ONCE(ads->ds_txstatus5);
++      ts->ts_rssi = MS(status, AR_TxRSSICombined);
++      ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
++      ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
++      ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
+-      ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
+-      ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
+-      ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
+-      ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
+-      ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
+-      ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
+-      ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
+       ts->evm0 = ads->AR_TxEVM0;
+       ts->evm1 = ads->AR_TxEVM1;
+       ts->evm2 = ads->AR_TxEVM2;
+-      ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
+-      ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
+-      ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
+-      ts->tid = MS(ads->ds_txstatus9, AR_TxTid);
+-      ts->ts_antenna = 0;
+       return 0;
+ }
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -104,13 +104,11 @@ struct ath_tx_status {
+       u32 ts_tstamp;
+       u16 ts_seqnum;
+       u8 ts_status;
+-      u8 ts_ratecode;
+       u8 ts_rateindex;
+       int8_t ts_rssi;
+       u8 ts_shortretry;
+       u8 ts_longretry;
+       u8 ts_virtcol;
+-      u8 ts_antenna;
+       u8 ts_flags;
+       int8_t ts_rssi_ctl0;
+       int8_t ts_rssi_ctl1;
+@@ -121,7 +119,6 @@ struct ath_tx_status {
+       u8 qid;
+       u16 desc_id;
+       u8 tid;
+-      u8 pad[2];
+       u32 ba_low;
+       u32 ba_high;
+       u32 evm0;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -237,10 +237,12 @@ static int ar9003_hw_proc_txdesc(struct 
+                                struct ath_tx_status *ts)
+ {
+       struct ar9003_txs *ads;
++      u32 status;
+       ads = &ah->ts_ring[ah->ts_tail];
+-      if ((ads->status8 & AR_TxDone) == 0)
++      status = ACCESS_ONCE(ads->status8);
++      if ((status & AR_TxDone) == 0)
+               return -EINPROGRESS;
+       ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
+@@ -253,57 +255,58 @@ static int ar9003_hw_proc_txdesc(struct 
+               return -EIO;
+       }
++      if (status & AR_TxOpExceeded)
++              ts->ts_status |= ATH9K_TXERR_XTXOP;
++      ts->ts_rateindex = MS(status, AR_FinalTxIdx);
++      ts->ts_seqnum = MS(status, AR_SeqNum);
++      ts->tid = MS(status, AR_TxTid);
++
+       ts->qid = MS(ads->ds_info, AR_TxQcuNum);
+       ts->desc_id = MS(ads->status1, AR_TxDescId);
+-      ts->ts_seqnum = MS(ads->status8, AR_SeqNum);
+       ts->ts_tstamp = ads->status4;
+       ts->ts_status = 0;
+       ts->ts_flags  = 0;
+-      if (ads->status3 & AR_ExcessiveRetries)
++      status = ACCESS_ONCE(ads->status2);
++      ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
++      ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
++      ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
++      if (status & AR_TxBaStatus) {
++              ts->ts_flags |= ATH9K_TX_BA;
++              ts->ba_low = ads->status5;
++              ts->ba_high = ads->status6;
++      }
++
++      status = ACCESS_ONCE(ads->status3);
++      if (status & AR_ExcessiveRetries)
+               ts->ts_status |= ATH9K_TXERR_XRETRY;
+-      if (ads->status3 & AR_Filtered)
++      if (status & AR_Filtered)
+               ts->ts_status |= ATH9K_TXERR_FILT;
+-      if (ads->status3 & AR_FIFOUnderrun) {
++      if (status & AR_FIFOUnderrun) {
+               ts->ts_status |= ATH9K_TXERR_FIFO;
+               ath9k_hw_updatetxtriglevel(ah, true);
+       }
+-      if (ads->status8 & AR_TxOpExceeded)
+-              ts->ts_status |= ATH9K_TXERR_XTXOP;
+-      if (ads->status3 & AR_TxTimerExpired)
++      if (status & AR_TxTimerExpired)
+               ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+-
+-      if (ads->status3 & AR_DescCfgErr)
++      if (status & AR_DescCfgErr)
+               ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+-      if (ads->status3 & AR_TxDataUnderrun) {
++      if (status & AR_TxDataUnderrun) {
+               ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+               ath9k_hw_updatetxtriglevel(ah, true);
+       }
+-      if (ads->status3 & AR_TxDelimUnderrun) {
++      if (status & AR_TxDelimUnderrun) {
+               ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+               ath9k_hw_updatetxtriglevel(ah, true);
+       }
+-      if (ads->status2 & AR_TxBaStatus) {
+-              ts->ts_flags |= ATH9K_TX_BA;
+-              ts->ba_low = ads->status5;
+-              ts->ba_high = ads->status6;
+-      }
+-
+-      ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx);
+-
+-      ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined);
+-      ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00);
+-      ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01);
+-      ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02);
+-      ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10);
+-      ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11);
+-      ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12);
+-      ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt);
+-      ts->ts_longretry = MS(ads->status3, AR_DataFailCnt);
+-      ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt);
+-      ts->ts_antenna = 0;
+-
+-      ts->tid = MS(ads->status8, AR_TxTid);
++      ts->ts_shortretry = MS(status, AR_RTSFailCnt);
++      ts->ts_longretry = MS(status, AR_DataFailCnt);
++      ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
++
++      status = ACCESS_ONCE(ads->status7);
++      ts->ts_rssi = MS(status, AR_TxRSSICombined);
++      ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
++      ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
++      ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
+       memset(ads, 0, sizeof(*ads));
diff --git a/package/mac80211/patches/553-ath9k_no_node_rssi.patch b/package/mac80211/patches/553-ath9k_no_node_rssi.patch
new file mode 100644 (file)
index 0000000..5991485
--- /dev/null
@@ -0,0 +1,145 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -271,7 +271,6 @@ struct ath_node {
+       struct ath_atx_ac ac[WME_NUM_AC];
+       u16 maxampdu;
+       u8 mpdudensity;
+-      int last_rssi;
+ };
+ #define AGGR_CLEANUP         BIT(1)
+@@ -666,6 +665,7 @@ struct ath_wiphy {
+       bool idle;
+       int chan_idx;
+       int chan_is_ht;
++      int last_rssi;
+ };
+ void ath9k_tasklet(unsigned long data);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -553,7 +553,6 @@ static void ath_node_attach(struct ath_s
+               an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+                                    sta->ht_cap.ampdu_factor);
+               an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
+-              an->last_rssi = ATH_RSSI_DUMMY_MARKER;
+       }
+ }
+@@ -822,9 +821,11 @@ static u32 ath_get_extchanmode(struct at
+ }
+ static void ath9k_bss_assoc_info(struct ath_softc *sc,
++                               struct ieee80211_hw *hw,
+                                struct ieee80211_vif *vif,
+                                struct ieee80211_bss_conf *bss_conf)
+ {
++      struct ath_wiphy *aphy = hw->priv;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+@@ -848,6 +849,7 @@ static void ath9k_bss_assoc_info(struct 
+               ath_beacon_config(sc, vif);
+               /* Reset rssi stats */
++              aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
+               sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
+               sc->sc_flags |= SC_OP_ANI_RUN;
+@@ -1969,7 +1971,7 @@ static void ath9k_bss_info_changed(struc
+       if (changed & BSS_CHANGED_ASSOC) {
+               ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
+                       bss_conf->assoc);
+-              ath9k_bss_assoc_info(sc, vif, bss_conf);
++              ath9k_bss_assoc_info(sc, hw, vif, bss_conf);
+       }
+       mutex_unlock(&sc->mutex);
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -960,36 +960,23 @@ static void ath9k_process_rssi(struct at
+                              struct ieee80211_hdr *hdr,
+                              struct ath_rx_status *rx_stats)
+ {
++      struct ath_wiphy *aphy = hw->priv;
+       struct ath_hw *ah = common->ah;
+-      struct ieee80211_sta *sta;
+-      struct ath_node *an;
+-      int last_rssi = ATH_RSSI_DUMMY_MARKER;
++      int last_rssi;
+       __le16 fc;
+-      fc = hdr->frame_control;
++      if (ah->opmode != NL80211_IFTYPE_STATION)
++              return;
+-      rcu_read_lock();
+-      /*
+-       * XXX: use ieee80211_find_sta! This requires quite a bit of work
+-       * under the current ath9k virtual wiphy implementation as we have
+-       * no way of tying a vif to wiphy. Typically vifs are attached to
+-       * at least one sdata of a wiphy on mac80211 but with ath9k virtual
+-       * wiphy you'd have to iterate over every wiphy and each sdata.
+-       */
+-      if (is_multicast_ether_addr(hdr->addr1))
+-              sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
+-      else
+-              sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
++      fc = hdr->frame_control;
++      if (!ieee80211_is_beacon(fc) ||
++          compare_ether_addr(hdr->addr3, common->curbssid))
++              return;
+-      if (sta) {
+-              an = (struct ath_node *) sta->drv_priv;
+-              if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
+-                 !rx_stats->rs_moreaggr)
+-                      ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
+-              last_rssi = an->last_rssi;
+-      }
+-      rcu_read_unlock();
++      if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
++              ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
++      last_rssi = aphy->last_rssi;
+       if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+               rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
+                                             ATH_RSSI_EP_MULTIPLIER);
+@@ -997,8 +984,7 @@ static void ath9k_process_rssi(struct at
+               rx_stats->rs_rssi = 0;
+       /* Update Beacon RSSI, this is used by ANI. */
+-      if (ieee80211_is_beacon(fc))
+-              ah->stats.avgbrssi = rx_stats->rs_rssi;
++      ah->stats.avgbrssi = rx_stats->rs_rssi;
+ }
+ /*
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -729,6 +729,7 @@ int ath9k_init_device(u16 devid, struct 
+                   const struct ath_bus_ops *bus_ops)
+ {
+       struct ieee80211_hw *hw = sc->hw;
++      struct ath_wiphy *aphy = hw->priv;
+       struct ath_common *common;
+       struct ath_hw *ah;
+       int error = 0;
+@@ -781,6 +782,7 @@ int ath9k_init_device(u16 devid, struct 
+       INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
+       INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
+       sc->wiphy_scheduler_int = msecs_to_jiffies(500);
++      aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
+       ath_init_leds(sc);
+       ath_start_rfkill_poll(sc);
+--- a/drivers/net/wireless/ath/ath9k/virtual.c
++++ b/drivers/net/wireless/ath/ath9k/virtual.c
+@@ -107,6 +107,7 @@ int ath9k_wiphy_add(struct ath_softc *sc
+       aphy->sc = sc;
+       aphy->hw = hw;
+       sc->sec_wiphy[i] = aphy;
++      aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
+       spin_unlock_bh(&sc->wiphy_lock);
+       memcpy(addr, common->macaddr, ETH_ALEN);
diff --git a/package/mac80211/patches/554-ath9k_bt_timer_start.patch b/package/mac80211/patches/554-ath9k_bt_timer_start.patch
new file mode 100644 (file)
index 0000000..33aadb7
--- /dev/null
@@ -0,0 +1,15 @@
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -326,10 +326,8 @@ static void ath_btcoex_period_timer(unsi
+               timer_period = is_btscan ? btcoex->btscan_no_stomp :
+                                          btcoex->btcoex_no_stomp;
+-              ath9k_gen_timer_start(ah,
+-                                    btcoex->no_stomp_timer,
+-                                    (ath9k_hw_gettsf32(ah) +
+-                                     timer_period), timer_period * 10);
++              ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0,
++                                    timer_period * 10);
+               btcoex->hw_timer_enabled = true;
+       }
diff --git a/package/mac80211/patches/555-ath9k_hw_gettsf32_static.patch b/package/mac80211/patches/555-ath9k_hw_gettsf32_static.patch
new file mode 100644 (file)
index 0000000..6fc4bc7
--- /dev/null
@@ -0,0 +1,25 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2324,11 +2324,10 @@ static u32 rightmost_index(struct ath_ge
+       return timer_table->gen_timer_index[b];
+ }
+-u32 ath9k_hw_gettsf32(struct ath_hw *ah)
++static u32 ath9k_hw_gettsf32(struct ath_hw *ah)
+ {
+       return REG_READ(ah, AR_TSF_L32);
+ }
+-EXPORT_SYMBOL(ath9k_hw_gettsf32);
+ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
+                                         void (*trigger)(void *),
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -892,7 +892,6 @@ void ath9k_hw_gen_timer_stop(struct ath_
+ void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
+ void ath_gen_timer_isr(struct ath_hw *hw);
+-u32 ath9k_hw_gettsf32(struct ath_hw *ah);
+ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
diff --git a/package/mac80211/patches/556-ath9k_desc_alignment.patch b/package/mac80211/patches/556-ath9k_desc_alignment.patch
new file mode 100644 (file)
index 0000000..6295f5e
--- /dev/null
@@ -0,0 +1,49 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h
+@@ -65,7 +65,7 @@ struct ar9003_rxs {
+       u32 status9;
+       u32 status10;
+       u32 status11;
+-} __packed;
++} __packed __aligned(4);
+ /* Transmit Control Descriptor */
+ struct ar9003_txc {
+@@ -93,7 +93,7 @@ struct ar9003_txc {
+       u32 ctl21;  /* DMA control 21 */
+       u32 ctl22;  /* DMA control 22 */
+       u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */
+-} __packed;
++} __packed __aligned(4);
+ struct ar9003_txs {
+       u32 ds_info;
+@@ -105,7 +105,7 @@ struct ar9003_txs {
+       u32 status6;
+       u32 status7;
+       u32 status8;
+-} __packed;
++} __packed __aligned(4);
+ void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
+ void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -237,7 +237,7 @@ struct ath_desc {
+       u32 ds_ctl1;
+       u32 ds_hw[20];
+       void *ds_vdata;
+-} __packed;
++} __packed __aligned(4);
+ #define ATH9K_TXDESC_CLRDMASK         0x0001
+ #define ATH9K_TXDESC_NOACK            0x0002
+@@ -307,7 +307,7 @@ struct ar5416_desc {
+                       u32 status8;
+               } rx;
+       } u;
+-} __packed;
++} __packed __aligned(4);
+ #define AR5416DESC(_ds)         ((struct ar5416_desc *)(_ds))
+ #define AR5416DESC_CONST(_ds)   ((const struct ar5416_desc *)(_ds))
This page took 0.099963 seconds and 4 git commands to generate.