mac80211: update to wireless-testing 2010-10-15, add a few ath9k fixes and performance enhancements
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@23470 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
f7e576d8a7
commit
1d0359c6f2
|
@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk
|
||||||
|
|
||||||
PKG_NAME:=mac80211
|
PKG_NAME:=mac80211
|
||||||
|
|
||||||
PKG_VERSION:=2010-10-07
|
PKG_VERSION:=2010-10-15
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
|
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
|
||||||
# http://www.orbit-lab.org/kernel/compat-wireless-2.6/2010/11 \
|
# http://www.orbit-lab.org/kernel/compat-wireless-2.6/2010/11 \
|
||||||
# http://wireless.kernel.org/download/compat-wireless-2.6
|
# http://wireless.kernel.org/download/compat-wireless-2.6
|
||||||
PKG_MD5SUM:=c46aada7c3ba92095dbac0a794538fe5
|
PKG_MD5SUM:=3c1cfce9a4a14af671c69dad02b973a4
|
||||||
|
|
||||||
PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
|
PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
|
||||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
|
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
|
||||||
|
|
|
@ -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;
|
|
|
@ -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);
|
|
@ -1,25 +0,0 @@
|
||||||
[PATCH] mac80211: hoist sta->lock from reorder release timer
|
|
||||||
|
|
||||||
The patch "mac80211: AMPDU rx reorder timeout timer" clashes
|
|
||||||
with "mac80211: use netif_receive_skb in ieee80211_rx callpath"
|
|
||||||
|
|
||||||
The timer itself is part of the station's private struct and
|
|
||||||
it gets killed whenever the station is removed. Therefore
|
|
||||||
the extra sta->lock protection (that can interferes with the
|
|
||||||
tx path) is not necessary.
|
|
||||||
|
|
||||||
Reported-by: Ming Lei <tom.leiming@gmail.com>
|
|
||||||
Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
|
|
||||||
---
|
|
||||||
--- a/net/mac80211/agg-rx.c
|
|
||||||
+++ b/net/mac80211/agg-rx.c
|
|
||||||
@@ -129,9 +129,7 @@ static void sta_rx_agg_reorder_timer_exp
|
|
||||||
timer_to_tid[0]);
|
|
||||||
|
|
||||||
rcu_read_lock();
|
|
||||||
- spin_lock(&sta->lock);
|
|
||||||
ieee80211_release_reorder_timeout(sta, *ptid);
|
|
||||||
- spin_unlock(&sta->lock);
|
|
||||||
rcu_read_unlock();
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
|
@ -8,7 +8,7 @@
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
@@ -446,8 +447,16 @@ static int ath9k_hw_init_macaddr(struct
|
@@ -449,8 +450,16 @@ static int ath9k_hw_init_macaddr(struct
|
||||||
common->macaddr[2 * i] = eeval >> 8;
|
common->macaddr[2 * i] = eeval >> 8;
|
||||||
common->macaddr[2 * i + 1] = eeval & 0xff;
|
common->macaddr[2 * i + 1] = eeval & 0xff;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
+++ b/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_hw *ah = NULL;
|
||||||
struct ath_common *common;
|
struct ath_common *common;
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
int ret = 0, i;
|
int ret = 0, i;
|
||||||
int csz = 0;
|
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;
|
ah->hw_version.subsysid = subsysid;
|
||||||
sc->sc_ah = ah;
|
sc->sc_ah = ah;
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
common->bus_ops = bus_ops;
|
common->bus_ops = bus_ops;
|
||||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||||
+++ b/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.magic = AR5416_MAGIC;
|
||||||
ah->hw_version.subvendorid = 0;
|
ah->hw_version.subvendorid = 0;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "hw-ops.h"
|
#include "hw-ops.h"
|
||||||
#include "rc.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)
|
static int ath9k_hw_init_macaddr(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
struct ath_common *common = ath9k_hw_common(ah);
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
--- a/drivers/net/wireless/ath/ath9k/hw.c
|
||||||
+++ b/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) {
|
if (ah->config.rx_intr_mitigation) {
|
||||||
REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
|
REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "ath9k.h"
|
#include "ath9k.h"
|
||||||
|
|
||||||
static char *dev_info = "ath9k";
|
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;
|
pdata = (struct ath9k_platform_data *) sc->dev->platform_data;
|
||||||
if (!pdata)
|
if (!pdata)
|
||||||
ah->ah_flags |= AH_USE_EEPROM;
|
ah->ah_flags |= AH_USE_EEPROM;
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
common = ath9k_hw_common(ah);
|
common = ath9k_hw_common(ah);
|
||||||
common->ops = &ath9k_common_ops;
|
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);
|
SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
|
int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||||
const struct ath_bus_ops *bus_ops)
|
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);
|
common = ath9k_hw_common(ah);
|
||||||
ath9k_set_hw_capab(sc, hw);
|
ath9k_set_hw_capab(sc, hw);
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
ath9k_reg_notifier);
|
ath9k_reg_notifier);
|
||||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||||
+++ b/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;
|
int beacon_interval;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1,347 +0,0 @@
|
||||||
--- a/drivers/net/wireless/ath/ath.h
|
|
||||||
+++ b/drivers/net/wireless/ath/ath.h
|
|
||||||
@@ -19,6 +19,7 @@
|
|
||||||
|
|
||||||
#include <linux/skbuff.h>
|
|
||||||
#include <linux/if_ether.h>
|
|
||||||
+#include <linux/spinlock.h>
|
|
||||||
#include <net/mac80211.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -42,6 +43,13 @@ struct ath_ani {
|
|
||||||
struct timer_list timer;
|
|
||||||
};
|
|
||||||
|
|
||||||
+struct ath_cycle_counters {
|
|
||||||
+ u32 cycles;
|
|
||||||
+ u32 rx_busy;
|
|
||||||
+ u32 rx_frame;
|
|
||||||
+ u32 tx_frame;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
enum ath_device_state {
|
|
||||||
ATH_HW_UNAVAILABLE,
|
|
||||||
ATH_HW_INITIALIZED,
|
|
||||||
@@ -147,6 +155,10 @@ struct ath_common {
|
|
||||||
|
|
||||||
unsigned int clockrate;
|
|
||||||
|
|
||||||
+ spinlock_t cc_lock;
|
|
||||||
+ struct ath_cycle_counters cc_ani;
|
|
||||||
+ struct ath_cycle_counters cc_survey;
|
|
||||||
+
|
|
||||||
struct ath_regulatory regulatory;
|
|
||||||
const struct ath_ops *ops;
|
|
||||||
const struct ath_bus_ops *bus_ops;
|
|
||||||
@@ -163,5 +175,7 @@ int ath_key_config(struct ath_common *co
|
|
||||||
struct ieee80211_sta *sta,
|
|
||||||
struct ieee80211_key_conf *key);
|
|
||||||
bool ath_hw_keyreset(struct ath_common *common, u16 entry);
|
|
||||||
+void ath_hw_cycle_counters_update(struct ath_common *common);
|
|
||||||
+int32_t ath_hw_get_listen_time(struct ath_common *common);
|
|
||||||
|
|
||||||
#endif /* ATH_H */
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/ani.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/ani.c
|
|
||||||
@@ -465,18 +465,6 @@ static void ath9k_hw_ani_lower_immunity(
|
|
||||||
ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
|
|
||||||
-{
|
|
||||||
- struct ath_common *common = ath9k_hw_common(ah);
|
|
||||||
- int32_t listen_time;
|
|
||||||
-
|
|
||||||
- ath9k_hw_update_cycle_counters(ah);
|
|
||||||
- listen_time = ah->listen_time / (common->clockrate * 1000);
|
|
||||||
- ah->listen_time = 0;
|
|
||||||
-
|
|
||||||
- return listen_time;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
|
|
||||||
{
|
|
||||||
struct ar5416AniState *aniState;
|
|
||||||
@@ -655,7 +643,9 @@ static void ath9k_hw_ani_read_counters(s
|
|
||||||
u32 phyCnt1, phyCnt2;
|
|
||||||
int32_t listenTime;
|
|
||||||
|
|
||||||
- listenTime = ath9k_hw_ani_get_listen_time(ah);
|
|
||||||
+ ath_hw_cycle_counters_update(common);
|
|
||||||
+ listenTime = ath_hw_get_listen_time(common);
|
|
||||||
+
|
|
||||||
if (listenTime < 0) {
|
|
||||||
ah->stats.ast_ani_lneg++;
|
|
||||||
ath9k_ani_restart(ah);
|
|
||||||
@@ -796,54 +786,6 @@ void ath9k_hw_disable_mib_counters(struc
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
|
|
||||||
|
|
||||||
-void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
|
|
||||||
-{
|
|
||||||
- struct ath_cycle_counters cc;
|
|
||||||
- bool clear;
|
|
||||||
-
|
|
||||||
- memcpy(&cc, &ah->cc, sizeof(cc));
|
|
||||||
-
|
|
||||||
- /* freeze counters */
|
|
||||||
- REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
|
|
||||||
-
|
|
||||||
- ah->cc.cycles = REG_READ(ah, AR_CCCNT);
|
|
||||||
- if (ah->cc.cycles < cc.cycles) {
|
|
||||||
- clear = true;
|
|
||||||
- goto skip;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
|
|
||||||
- ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
|
|
||||||
- ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);
|
|
||||||
-
|
|
||||||
- /* prevent wraparound */
|
|
||||||
- if (ah->cc.cycles & BIT(31))
|
|
||||||
- clear = true;
|
|
||||||
-
|
|
||||||
-#define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
|
|
||||||
- CC_DELTA(cycles, AR_CCCNT);
|
|
||||||
- CC_DELTA(rx_frame, AR_RFCNT);
|
|
||||||
- CC_DELTA(rx_clear, AR_RCCNT);
|
|
||||||
- CC_DELTA(tx_frame, AR_TFCNT);
|
|
||||||
-#undef CC_DELTA
|
|
||||||
-
|
|
||||||
- ah->listen_time += (ah->cc.cycles - cc.cycles) -
|
|
||||||
- ((ah->cc.rx_frame - cc.rx_frame) +
|
|
||||||
- (ah->cc.tx_frame - cc.tx_frame));
|
|
||||||
-
|
|
||||||
-skip:
|
|
||||||
- if (clear) {
|
|
||||||
- REG_WRITE(ah, AR_CCCNT, 0);
|
|
||||||
- REG_WRITE(ah, AR_RFCNT, 0);
|
|
||||||
- REG_WRITE(ah, AR_RCCNT, 0);
|
|
||||||
- REG_WRITE(ah, AR_TFCNT, 0);
|
|
||||||
- memset(&ah->cc, 0, sizeof(ah->cc));
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- /* unfreeze counters */
|
|
||||||
- REG_WRITE(ah, AR_MIBC, 0);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
/*
|
|
||||||
* Process a MIB interrupt. We may potentially be invoked because
|
|
||||||
* any of the MIB counters overflow/trigger so don't assume we're
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/ani.h
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/ani.h
|
|
||||||
@@ -93,13 +93,6 @@ struct ath9k_mib_stats {
|
|
||||||
u32 beacons;
|
|
||||||
};
|
|
||||||
|
|
||||||
-struct ath_cycle_counters {
|
|
||||||
- u32 cycles;
|
|
||||||
- u32 rx_frame;
|
|
||||||
- u32 rx_clear;
|
|
||||||
- u32 tx_frame;
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
/* INI default values for ANI registers */
|
|
||||||
struct ath9k_ani_default {
|
|
||||||
u16 m1ThreshLow;
|
|
||||||
@@ -164,7 +157,6 @@ struct ar5416Stats {
|
|
||||||
|
|
||||||
void ath9k_enable_mib_counters(struct ath_hw *ah);
|
|
||||||
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
|
|
||||||
-void ath9k_hw_update_cycle_counters(struct ath_hw *ah);
|
|
||||||
void ath9k_hw_ani_setup(struct ath_hw *ah);
|
|
||||||
void ath9k_hw_ani_init(struct ath_hw *ah);
|
|
||||||
int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
|
|
||||||
@@ -1254,13 +1254,12 @@ void ar9003_hw_bb_watchdog_dbg_info(stru
|
|
||||||
"** BB mode: BB_gen_controls=0x%08x **\n",
|
|
||||||
REG_READ(ah, AR_PHY_GEN_CTRL));
|
|
||||||
|
|
||||||
- ath9k_hw_update_cycle_counters(ah);
|
|
||||||
-#define PCT(_field) (ah->cc_delta._field * 100 / ah->cc_delta.cycles)
|
|
||||||
- if (ah->cc_delta.cycles)
|
|
||||||
+#define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
|
|
||||||
+ if (common->cc_survey.cycles)
|
|
||||||
ath_print(common, ATH_DBG_RESET,
|
|
||||||
"** BB busy times: rx_clear=%d%%, "
|
|
||||||
"rx_frame=%d%%, tx_frame=%d%% **\n",
|
|
||||||
- PCT(rx_clear), PCT(rx_frame), PCT(tx_frame));
|
|
||||||
+ PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));
|
|
||||||
|
|
||||||
ath_print(common, ATH_DBG_RESET,
|
|
||||||
"==== BB update: done ====\n\n");
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
|
||||||
@@ -740,8 +740,6 @@ struct ath_hw {
|
|
||||||
int coarse_low[5];
|
|
||||||
int firpwr[5];
|
|
||||||
enum ath9k_ani_cmd ani_function;
|
|
||||||
- struct ath_cycle_counters cc, cc_delta;
|
|
||||||
- int32_t listen_time;
|
|
||||||
|
|
||||||
/* Bluetooth coexistance */
|
|
||||||
struct ath_btcoex_hw btcoex_hw;
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
|
||||||
@@ -400,6 +400,7 @@ void ath_ani_calibrate(unsigned long dat
|
|
||||||
bool aniflag = false;
|
|
||||||
unsigned int timestamp = jiffies_to_msecs(jiffies);
|
|
||||||
u32 cal_interval, short_cal_interval, long_cal_interval;
|
|
||||||
+ unsigned long flags;
|
|
||||||
|
|
||||||
if (ah->caldata && ah->caldata->nfcal_interference)
|
|
||||||
long_cal_interval = ATH_LONG_CALINTERVAL_INT;
|
|
||||||
@@ -450,8 +451,11 @@ void ath_ani_calibrate(unsigned long dat
|
|
||||||
/* Skip all processing if there's nothing to do. */
|
|
||||||
if (longcal || shortcal || aniflag) {
|
|
||||||
/* Call ANI routine if necessary */
|
|
||||||
- if (aniflag)
|
|
||||||
+ if (aniflag) {
|
|
||||||
+ spin_lock_irqsave(&common->cc_lock, flags);
|
|
||||||
ath9k_hw_ani_monitor(ah, ah->curchan);
|
|
||||||
+ spin_unlock_irqrestore(&common->cc_lock, flags);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* Perform calibration if necessary */
|
|
||||||
if (longcal || shortcal) {
|
|
||||||
@@ -636,6 +640,7 @@ irqreturn_t ath_isr(int irq, void *dev)
|
|
||||||
|
|
||||||
struct ath_softc *sc = dev;
|
|
||||||
struct ath_hw *ah = sc->sc_ah;
|
|
||||||
+ struct ath_common *common = ath9k_hw_common(ah);
|
|
||||||
enum ath9k_int status;
|
|
||||||
bool sched = false;
|
|
||||||
|
|
||||||
@@ -685,7 +690,12 @@ irqreturn_t ath_isr(int irq, void *dev)
|
|
||||||
|
|
||||||
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
|
|
||||||
(status & ATH9K_INT_BB_WATCHDOG)) {
|
|
||||||
+
|
|
||||||
+ spin_lock(&common->cc_lock);
|
|
||||||
+ ath_hw_cycle_counters_update(common);
|
|
||||||
ar9003_hw_bb_watchdog_dbg_info(ah);
|
|
||||||
+ spin_unlock(&common->cc_lock);
|
|
||||||
+
|
|
||||||
goto chip_reset;
|
|
||||||
}
|
|
||||||
|
|
||||||
--- a/drivers/net/wireless/ath/ath9k/reg.h
|
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/reg.h
|
|
||||||
@@ -107,12 +107,6 @@
|
|
||||||
#define AR_RXCFG_DMASZ_256B 6
|
|
||||||
#define AR_RXCFG_DMASZ_512B 7
|
|
||||||
|
|
||||||
-#define AR_MIBC 0x0040
|
|
||||||
-#define AR_MIBC_COW 0x00000001
|
|
||||||
-#define AR_MIBC_FMC 0x00000002
|
|
||||||
-#define AR_MIBC_CMC 0x00000004
|
|
||||||
-#define AR_MIBC_MCS 0x00000008
|
|
||||||
-
|
|
||||||
#define AR_TOPS 0x0044
|
|
||||||
#define AR_TOPS_MASK 0x0000FFFF
|
|
||||||
|
|
||||||
@@ -1524,11 +1518,6 @@ enum {
|
|
||||||
#define AR_TPC_CHIRP 0x003f0000
|
|
||||||
#define AR_TPC_CHIRP_S 0x16
|
|
||||||
|
|
||||||
-#define AR_TFCNT 0x80ec
|
|
||||||
-#define AR_RFCNT 0x80f0
|
|
||||||
-#define AR_RCCNT 0x80f4
|
|
||||||
-#define AR_CCCNT 0x80f8
|
|
||||||
-
|
|
||||||
#define AR_QUIET1 0x80fc
|
|
||||||
#define AR_QUIET1_NEXT_QUIET_S 0
|
|
||||||
#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
|
|
||||||
--- a/drivers/net/wireless/ath/hw.c
|
|
||||||
+++ b/drivers/net/wireless/ath/hw.c
|
|
||||||
@@ -124,3 +124,62 @@ void ath_hw_setbssidmask(struct ath_comm
|
|
||||||
REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(ath_hw_setbssidmask);
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/**
|
|
||||||
+ * ath_hw_cycle_counters_update - common function to update cycle counters
|
|
||||||
+ *
|
|
||||||
+ * @common: the ath_common struct for the device.
|
|
||||||
+ *
|
|
||||||
+ * This function is used to update all cycle counters in one place.
|
|
||||||
+ * It has to be called while holding common->cc_lock!
|
|
||||||
+ */
|
|
||||||
+void ath_hw_cycle_counters_update(struct ath_common *common)
|
|
||||||
+{
|
|
||||||
+ u32 cycles, busy, rx, tx;
|
|
||||||
+ void *ah = common->ah;
|
|
||||||
+
|
|
||||||
+ /* freeze */
|
|
||||||
+ REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
|
|
||||||
+
|
|
||||||
+ /* read */
|
|
||||||
+ cycles = REG_READ(ah, AR_CCCNT);
|
|
||||||
+ busy = REG_READ(ah, AR_RCCNT);
|
|
||||||
+ rx = REG_READ(ah, AR_RFCNT);
|
|
||||||
+ tx = REG_READ(ah, AR_TFCNT);
|
|
||||||
+
|
|
||||||
+ /* clear */
|
|
||||||
+ REG_WRITE(ah, 0, AR_CCCNT);
|
|
||||||
+ REG_WRITE(ah, 0, AR_RFCNT);
|
|
||||||
+ REG_WRITE(ah, 0, AR_RCCNT);
|
|
||||||
+ REG_WRITE(ah, 0, AR_TFCNT);
|
|
||||||
+
|
|
||||||
+ /* unfreeze */
|
|
||||||
+ REG_WRITE(ah, 0, AR_MIBC);
|
|
||||||
+
|
|
||||||
+ /* update all cycle counters here */
|
|
||||||
+ common->cc_ani.cycles += cycles;
|
|
||||||
+ common->cc_ani.rx_busy += busy;
|
|
||||||
+ common->cc_ani.rx_frame += rx;
|
|
||||||
+ common->cc_ani.tx_frame += tx;
|
|
||||||
+
|
|
||||||
+ common->cc_survey.cycles += cycles;
|
|
||||||
+ common->cc_survey.rx_busy += busy;
|
|
||||||
+ common->cc_survey.rx_frame += rx;
|
|
||||||
+ common->cc_survey.tx_frame += tx;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL(ath_hw_cycle_counters_update);
|
|
||||||
+
|
|
||||||
+int32_t ath_hw_get_listen_time(struct ath_common *common)
|
|
||||||
+{
|
|
||||||
+ struct ath_cycle_counters *cc = &common->cc_ani;
|
|
||||||
+ int32_t listen_time;
|
|
||||||
+
|
|
||||||
+ listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
|
|
||||||
+ (common->clockrate * 1000);
|
|
||||||
+
|
|
||||||
+ memset(cc, 0, sizeof(*cc));
|
|
||||||
+
|
|
||||||
+ return listen_time;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL(ath_hw_get_listen_time);
|
|
||||||
--- a/drivers/net/wireless/ath/reg.h
|
|
||||||
+++ b/drivers/net/wireless/ath/reg.h
|
|
||||||
@@ -17,6 +17,12 @@
|
|
||||||
#ifndef ATH_REGISTERS_H
|
|
||||||
#define ATH_REGISTERS_H
|
|
||||||
|
|
||||||
+#define AR_MIBC 0x0040
|
|
||||||
+#define AR_MIBC_COW 0x00000001
|
|
||||||
+#define AR_MIBC_FMC 0x00000002
|
|
||||||
+#define AR_MIBC_CMC 0x00000004
|
|
||||||
+#define AR_MIBC_MCS 0x00000008
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* BSSID mask registers. See ath_hw_set_bssid_mask()
|
|
||||||
* for detailed documentation about these registers.
|
|
||||||
@@ -24,6 +30,11 @@
|
|
||||||
#define AR_BSSMSKL 0x80e0
|
|
||||||
#define AR_BSSMSKU 0x80e4
|
|
||||||
|
|
||||||
+#define AR_TFCNT 0x80ec
|
|
||||||
+#define AR_RFCNT 0x80f0
|
|
||||||
+#define AR_RCCNT 0x80f4
|
|
||||||
+#define AR_CCCNT 0x80f8
|
|
||||||
+
|
|
||||||
#define AR_KEYTABLE_0 0x8800
|
|
||||||
#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
|
|
||||||
#define AR_KEY_CACHE_SIZE 128
|
|
|
@ -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);
|
|
|
@ -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);
|
|
||||||
|
|
|
@ -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);
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)
|
|
@ -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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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) {
|
|
@ -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));
|
||||||
|
|
|
@ -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);
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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))
|
Loading…
Reference in New Issue