From: Felix Fietkau Date: Sat, 16 Oct 2010 02:30:30 +0000 (+0000) Subject: mac80211: update to wireless-testing 2010-10-15, add a few ath9k fixes and performanc... X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=8083a4380b0832bba5502e0ff05f112367ee7edc;p=openwrt%2Fstaging%2Fneocturne.git mac80211: update to wireless-testing 2010-10-15, add a few ath9k fixes and performance enhancements SVN-Revision: 23470 --- diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index 7a095bca32..ef219d3ec8 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -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 index d7fb4df3e2..0000000000 --- a/package/mac80211/patches/020-nl80211_fix.patch +++ /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 index 0000000000..46f1202d09 --- /dev/null +++ b/package/mac80211/patches/300-ath5k_cc_lock_fix.patch @@ -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 index a42d7ec13a..0000000000 --- a/package/mac80211/patches/300-mac80211_release_reorder_fix.patch +++ /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 -Signed-off-by: Christian Lamparter ---- ---- 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 index 0000000000..b9e82d18a4 --- /dev/null +++ b/package/mac80211/patches/301-ath9k_cc_lock_fix.patch @@ -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); diff --git a/package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch b/package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch index 7dd3584d68..1f3712a609 100644 --- a/package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch +++ b/package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch @@ -8,7 +8,7 @@ #include #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; } diff --git a/package/mac80211/patches/406-ath9k-set-AH_USE_EEPROM-only-if-no-platform-data-present.patch b/package/mac80211/patches/406-ath9k-set-AH_USE_EEPROM-only-if-no-platform-data-present.patch index 1d90d6c14c..615bce5619 100644 --- a/package/mac80211/patches/406-ath9k-set-AH_USE_EEPROM-only-if-no-platform-data-present.patch +++ b/package/mac80211/patches/406-ath9k-set-AH_USE_EEPROM-only-if-no-platform-data-present.patch @@ -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; diff --git a/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch b/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch index 1a5ff02bb3..315e7992c5 100644 --- a/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch +++ b/package/mac80211/patches/407-ath9k-override-mac-address-from-platform-data.patch @@ -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); diff --git a/package/mac80211/patches/408-ath9k_tweak_rx_intr_mitigation.patch b/package/mac80211/patches/408-ath9k_tweak_rx_intr_mitigation.patch index c2bf8187ac..b9bf3e70d1 100644 --- a/package/mac80211/patches/408-ath9k_tweak_rx_intr_mitigation.patch +++ b/package/mac80211/patches/408-ath9k_tweak_rx_intr_mitigation.patch @@ -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); diff --git a/package/mac80211/patches/409-ath9k-add-wndr3700-antenna-initialization.patch b/package/mac80211/patches/409-ath9k-add-wndr3700-antenna-initialization.patch index b79dd51a23..2007e4a6f7 100644 --- a/package/mac80211/patches/409-ath9k-add-wndr3700-antenna-initialization.patch +++ b/package/mac80211/patches/409-ath9k-add-wndr3700-antenna-initialization.patch @@ -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 index 3266e0e103..0000000000 --- a/package/mac80211/patches/520-ath9k_common_clockrate.patch +++ /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 index 0000000000..f130f4132e --- /dev/null +++ b/package/mac80211/patches/520-ath9k_ps_survey_fix.patch @@ -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 index 08c18342e7..0000000000 --- a/package/mac80211/patches/521-ath5k_common_clockrate.patch +++ /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 index 0000000000..598286ec9e --- /dev/null +++ b/package/mac80211/patches/521-ath9k_ani_listen_time_fix.patch @@ -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 index 0000000000..45bb95d4ee --- /dev/null +++ b/package/mac80211/patches/522-ath9k_ani_overflow_fix.patch @@ -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 index f719575264..0000000000 --- a/package/mac80211/patches/522-ath_common_counters.patch +++ /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 - #include -+#include - #include - - /* -@@ -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 index 1899f8d465..0000000000 --- a/package/mac80211/patches/523-ath5k_use_common_counters.patch +++ /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 index 0000000000..9f284df2cc --- /dev/null +++ b/package/mac80211/patches/523-ath9k_cycle_counter_lock_fix.patch @@ -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 index af71234121..0000000000 --- a/package/mac80211/patches/524-mac80211_survey_channel_stats.patch +++ /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 index ae743934bd..0000000000 --- a/package/mac80211/patches/525-ath9k_channel_count_check.patch +++ /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 index 57ba398b02..0000000000 --- a/package/mac80211/patches/526-ath9k_survey_channel_stats.patch +++ /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 index f130f4132e..0000000000 --- a/package/mac80211/patches/527-ath9k_ps_survey_fix.patch +++ /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 index 598286ec9e..0000000000 --- a/package/mac80211/patches/528-ath9k_ani_listen_time_fix.patch +++ /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 index 45bb95d4ee..0000000000 --- a/package/mac80211/patches/529-ath9k_ani_overflow_fix.patch +++ /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 index 9f284df2cc..0000000000 --- a/package/mac80211/patches/530-ath9k_cycle_counter_lock_fix.patch +++ /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 index 0000000000..4e413f88d1 --- /dev/null +++ b/package/mac80211/patches/540-ath9k_rc_debugfs.patch @@ -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 index 0000000000..b3c0413178 --- /dev/null +++ b/package/mac80211/patches/541-ath9k_rc_rate_table_cleanup.patch @@ -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 index 0000000000..ae6854637d --- /dev/null +++ b/package/mac80211/patches/542-ath9k_no_mode_idx.patch @@ -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 index 0000000000..d6a1d7525f --- /dev/null +++ b/package/mac80211/patches/550-ath9k_interrupt_mask_optimization.patch @@ -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 index 0000000000..dc267f33b0 --- /dev/null +++ b/package/mac80211/patches/551-ath9k_isr_optimization.patch @@ -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 index 0000000000..75d9f653d9 --- /dev/null +++ b/package/mac80211/patches/552-ath9k_txdesc_optimization.patch @@ -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 index 0000000000..5991485338 --- /dev/null +++ b/package/mac80211/patches/553-ath9k_no_node_rssi.patch @@ -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 index 0000000000..33aadb74f0 --- /dev/null +++ b/package/mac80211/patches/554-ath9k_bt_timer_start.patch @@ -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 index 0000000000..6fc4bc7210 --- /dev/null +++ b/package/mac80211/patches/555-ath9k_hw_gettsf32_static.patch @@ -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 index 0000000000..6295f5eed2 --- /dev/null +++ b/package/mac80211/patches/556-ath9k_desc_alignment.patch @@ -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))