PKG_NAME:=mac80211
-PKG_VERSION:=2011-09-14
+PKG_VERSION:=2011-11-15
PKG_RELEASE:=1
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
-PKG_MD5SUM:=a5627e6079e8d0f0baf7045141503a3d
+PKG_MD5SUM:=0bb667c7fecbc244840d806df0604661
PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
$(call KernelPackage/mac80211/Default)
TITLE:=Atheros 802.11n wireless devices (common code for ath9k and ath9k_htc)
URL:=http://linuxwireless.org/en/users/Drivers/ath9k
- DEPENDS+= @PCI_SUPPORT||TARGET_ar71xx +kmod-ath +@DRIVER_11N_SUPPORT
+ DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx +kmod-ath +@DRIVER_11N_SUPPORT
FILES:= \
$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \
$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_hw.ko
define KernelPackage/carl9170
$(call KernelPackage/mac80211/Default)
TITLE:=Driver for Atheros AR9170 USB sticks
- DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +@DRIVER_11N_SUPPORT
+ DEPENDS:=@USB_SUPPORT +kmod-mac80211 +kmod-ath +kmod-usb-core +kmod-input-core +@DRIVER_11N_SUPPORT
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/carl9170/carl9170.ko
AUTOLOAD:=$(call AutoLoad,60,carl9170)
endef
define KernelPackage/libertas-usb
$(call KernelPackage/mac80211/Default)
- DEPENDS+= @USB_SUPPORT +kmod-mac80211 +kmod-usb-core +kmod-lib80211
+ DEPENDS+= @USB_SUPPORT +kmod-cfg80211 +kmod-usb-core +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
TITLE:=Marvell 88W8015 Wireless Driver
FILES:= \
$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
define KernelPackage/libertas-sd
$(call KernelPackage/mac80211/Default)
- DEPENDS+= +kmod-mac80211 +kmod-lib80211 +@DRIVER_WEXT_SUPPORT @!LINUX_2_6_30
+ DEPENDS+= +kmod-cfg80211 +kmod-lib80211 +@DRIVER_WEXT_SUPPORT
TITLE:=Marvell 88W8686 Wireless Driver
FILES:= \
$(PKG_BUILD_DIR)/drivers/net/wireless/libertas/libertas.ko \
define KernelPackage/net-libipw
$(call KernelPackage/mac80211/Default)
TITLE:=libipw for ipw2100 and ipw2200
- DEPENDS:=@PCI_SUPPORT +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic +kmod-lib80211 +kmod-cfg80211
+ DEPENDS:=@PCI_SUPPORT +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic +kmod-lib80211 +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/libipw.ko
AUTOLOAD:=$(call AutoLoad,49,libipw)
endef
define KernelPackage/net-hermes-pci
$(call KernelPackage/mac80211/Default)
TITLE:=Intersil Prism 2.5 PCI support
- DEPENDS:=@PCI_SUPPORT +kmod-net-hermes +kmod-cfg80211
+ DEPENDS:=@PCI_SUPPORT +kmod-net-hermes
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_pci.ko
AUTOLOAD:=$(call AutoLoad,55,orinoco_pci)
endef
define KernelPackage/net-hermes-plx
$(call KernelPackage/mac80211/Default)
TITLE:=PLX9052 based PCI adaptor
- DEPENDS:=@PCI_SUPPORT +kmod-net-hermes +kmod-cfg80211
+ DEPENDS:=@PCI_SUPPORT +kmod-net-hermes
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_plx.ko
AUTOLOAD:=$(call AutoLoad,55,orinoco_plx)
endef
define KernelPackage/net-hermes-pcmcia
$(call KernelPackage/mac80211/Default)
TITLE:=Hermes based PCMCIA adaptors
- DEPENDS:=@PCMCIA_SUPPORT +kmod-net-hermes +kmod-cfg80211 @BROKEN
+ DEPENDS:=@PCMCIA_SUPPORT +kmod-net-hermes @BROKEN
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/orinoco/orinoco_cs.ko
AUTOLOAD:=$(call AutoLoad,55,orinoco_cs)
endef
$(call KernelPackage/mac80211/Default)
DEPENDS:= +kmod-mac80211 @PCI_SUPPORT
TITLE:=Intel AGN Wireless support
- FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/iwlagn.$(LINUX_KMOD_SUFFIX)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/iwlwifi.ko
AUTOLOAD:=$(call AutoLoad,60,iwlagn)
MENU:=1
endef
$(call KernelPackage/mac80211/Default)
DEPENDS:= +kmod-mac80211 @PCI_SUPPORT
TITLE:=Intel legacy Wireless support
- FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl-legacy.$(LINUX_KMOD_SUFFIX)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl-legacy.ko
AUTOLOAD:=$(call AutoLoad,60,iwl-legacy)
endef
$(call KernelPackage/mac80211/Default)
DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy
TITLE:=Intel iwl3945 Wireless support
- FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl3945.$(LINUX_KMOD_SUFFIX)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl3945.ko
AUTOLOAD:=$(call AutoLoad,61,iwl3945)
endef
$(call KernelPackage/mac80211/Default)
DEPENDS:= +kmod-mac80211 +kmod-iwl-legacy
TITLE:=Intel iwl4965 Wireless support
- FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl4965.$(LINUX_KMOD_SUFFIX)
+ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl4965.ko
AUTOLOAD:=$(call AutoLoad,61,iwl4965)
endef
ARCH="$(LINUX_KARCH)" \
EXTRA_CFLAGS="$(BUILDFLAGS)" \
$(foreach opt,$(CONFOPTS),CONFIG_$(opt)=m) \
+ CONFIG_CFG80211=$(if $(CONFIG_PACKAGE_kmod-cfg80211),m) \
CONFIG_MAC80211=$(if $(CONFIG_PACKAGE_kmod-mac80211),m) \
CONFIG_MAC80211_RC_MINSTREL=y \
CONFIG_MAC80211_LEDS=$(CONFIG_LEDS_TRIGGERS) \
CONFIG_RT2800_LIB=$(if $(CONFIG_PACKAGE_kmod-rt2800-lib),m) \
CONFIG_RT2800PCI=$(if $(CONFIG_PACKAGE_kmod-rt2800-pci),m) \
CONFIG_RT2800USB=$(if $(CONFIG_PACKAGE_kmod-rt2800-usb),m) \
+ CONFIG_RT2800USB_RT53XX=$(if $(CONFIG_PACKAGE_kmod-rt2800-usb),y) \
CONFIG_RTL8180=$(if $(CONFIG_PACKAGE_kmod-rtl8180),m) \
CONFIG_RTL8187=$(if $(CONFIG_PACKAGE_kmod-rtl8187),m) \
CONFIG_RTL8192CE= \
CONFIG_LIB80211_CRYPT_WEP=$(if $(CONFIG_PACKAGE_kmod-lib80211),m) \
CONFIG_LIB80211_CRYPT_CCMP=$(if $(CONFIG_PACKAGE_kmod-lib80211),m) \
CONFIG_LIB80211_CRYPT_TKIP=$(if $(CONFIG_PACKAGE_kmod-lib80211),m) \
- CONFIG_IWLAGN=$(if $(CONFIG_PACKAGE_kmod-iwlagn),m) \
+ CONFIG_IWLWIFI=$(if $(CONFIG_PACKAGE_kmod-iwlagn),m) \
CONFIG_IWLWIFI_LEGACY=$(if $(CONFIG_PACKAGE_kmod-iwl-legacy),m) \
CONFIG_COMPAT_IWL4965=$(if $(CONFIG_PACKAGE_kmod-iwl4965),m) \
CONFIG_IWL3945=$(if $(CONFIG_PACKAGE_kmod-iwl3945),m) \
CONFIG_ATL2= \
CONFIG_ATL1E= \
CONFIG_ATL1C= \
+ CONFIG_BRCMFMAC= \
+ CONFIG_BRCMUMAC= \
+ CONFIG_BRCMSMAC= \
KLIB_BUILD="$(LINUX_DIR)" \
MODPROBE=: \
KLIB=$(TARGET_MODULES_DIR) \
rm -f $(PKG_BUILD_DIR)/include/net/ieee80211.h
endef
-ifneq ($(CONFIG_PACKAGE_kmod-cfg80211),)
+ifneq ($(CONFIG_PACKAGE_kmod-cfg80211)$(CONFIG_PACKAGE_kmod-lib80211),)
define Build/Compile/kmod
rm -rf $(PKG_BUILD_DIR)/modules
$(MAKE) $(PKG_JOBS) -C "$(PKG_BUILD_DIR)" $(MAKE_OPTS) all
--- a/config.mk
+++ b/config.mk
-@@ -340,8 +340,8 @@ CONFIG_B43_BCMA_PIO=y
+@@ -339,8 +339,8 @@ CONFIG_B43_BCMA_PIO=y
CONFIG_P54_PCI=m
ifeq ($(CONFIG_MAC80211),y)
$(error "ERROR: you have MAC80211 compiled into the kernel, CONFIG_MAC80211=y, as such you cannot replace its mac80211 driver. You need this set to CONFIG_MAC80211=m. If you are using Fedora upgrade your kernel as later version should this set as modular. For further information on Fedora see https://bugzilla.redhat.com/show_bug.cgi?id=470143. If you are using your own kernel recompile it and make mac80211 modular")
-@@ -642,10 +642,10 @@ endif #CONFIG_COMPAT_KERNEL_2_6_27
+@@ -632,10 +632,10 @@ endif #CONFIG_COMPAT_KERNEL_2_6_27
# We need the backported rfkill module on kernel < 2.6.31.
# In more recent kernel versions use the in kernel rfkill module.
ifdef CONFIG_COMPAT_KERNEL_2_6_31
else
include $(KLIB_BUILD)/.config
endif
-@@ -316,7 +315,8 @@ CONFIG_IPW2200_QOS=y
+@@ -315,7 +314,8 @@ CONFIG_IPW2200_QOS=y
# % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
endif #CONFIG_WIRELESS_EXT
# Sonics Silicon Backplane
CONFIG_SSB_SPROM=y
-@@ -329,7 +329,7 @@ endif #CONFIG_PCMCIA
+@@ -328,7 +328,7 @@ endif #CONFIG_PCMCIA
# CONFIG_SSB_DEBUG=y
CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_B43_SSB=y
CONFIG_BCMA=m
CONFIG_BCMA_BLOCKIO=y
-@@ -538,7 +538,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -535,7 +535,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
ifdef CONFIG_MMC
ifeq ($(CONFIG_STAGING_EXCLUDE_BUILD),)
--- a/config.mk
+++ b/config.mk
-@@ -331,12 +331,12 @@ CONFIG_SSB_DRIVER_PCICORE=y
+@@ -330,12 +330,12 @@ CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_B43_SSB=y
endif #__CONFIG_SSB
endif #CONFIG_STAGING
# mac80211 test driver
-@@ -368,13 +368,13 @@ endif #CONFIG_CRC_ITU_T
+@@ -367,13 +367,13 @@ endif #CONFIG_CRC_ITU_T
CONFIG_MWL8K=m
# Ethernet drivers go here
endif #CONFIG_COMPAT_KERNEL_2_6_27
ifdef CONFIG_WIRELESS_EXT
-@@ -435,21 +435,21 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+@@ -432,21 +432,21 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
# Note: this depends on CONFIG_USB_NET_RNDIS_HOST and CONFIG_USB_NET_CDCETHER
# it also requires new RNDIS_HOST and CDC_ETHER modules which we add
ifdef CONFIG_COMPAT_KERNEL_2_6_29
else
include $(KLIB_BUILD)/.config
endif
-@@ -248,7 +248,7 @@ CONFIG_B43=m
+@@ -247,7 +247,7 @@ CONFIG_B43=m
CONFIG_B43_HWRNG=y
CONFIG_B43_PCI_AUTOSELECT=y
ifdef CONFIG_PCMCIA
--- a/config.mk
+++ b/config.mk
-@@ -521,7 +521,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -518,7 +518,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
ifdef CONFIG_MMC
--- a/config.mk
+++ b/config.mk
-@@ -254,7 +254,7 @@ ifdef CONFIG_MAC80211_LEDS
+@@ -253,8 +253,8 @@ ifdef CONFIG_MAC80211_LEDS
CONFIG_B43_LEDS=y
endif #CONFIG_MAC80211_LEDS
CONFIG_B43_PHY_LP=y
-CONFIG_B43_PHY_N=y
+-CONFIG_B43_PHY_HT=y
+# CONFIG_B43_PHY_N=y
- # CONFIG_B43_PHY_HT=y
++# CONFIG_B43_PHY_HT=y
# CONFIG_B43_PHY_LCN=y
# CONFIG_B43_FORCE_PIO=y
+ # CONFIG_B43_DEBUG=y
--- a/config.mk
+++ b/config.mk
-@@ -330,7 +330,7 @@ CONFIG_RTL8180=m
+@@ -329,7 +329,7 @@ CONFIG_RTL8180=m
CONFIG_ADM8211=m
CONFIG_RT2400PCI=m
CONFIG_RT2500PCI=m
ifdef CONFIG_CRC_CCITT
-@@ -470,7 +470,7 @@ CONFIG_RT2800USB_RT35XX=y
+@@ -467,7 +467,7 @@ CONFIG_RT2800USB_RT35XX=y
# CONFIG_RT2800USB_RT53XX=y
CONFIG_RT2800USB_UNKNOWN=y
endif #CONFIG_CRC_CCITT
static int __init compat_init(void)
{
/* pm-qos for kernels <= 2.6.24, this is a no-op on newer kernels */
-@@ -45,15 +56,15 @@ static int __init compat_init(void)
+@@ -46,7 +57,8 @@ static int __init compat_init(void)
COMPAT_BASE_TREE " " COMPAT_BASE_TREE_VERSION
"\n");
}
module_init(compat_init);
- static void __exit compat_exit(void)
- {
+@@ -55,7 +67,8 @@ static void __exit compat_exit(void)
compat_pm_qos_power_deinit();
--
+ compat_system_workqueue_destroy();
+
- return;
+ firmware_class_exit();
++ return;
}
module_exit(compat_exit);
--- /dev/null
+--- a/compat/compat-2.6.36.c
++++ b/compat/compat-2.6.36.c
+@@ -93,6 +93,8 @@ void compat_usb_scuttle_anchored_urbs(st
+ }
+ EXPORT_SYMBOL_GPL(compat_usb_scuttle_anchored_urbs);
+
++#endif /* CONFIG_COMPAT_USB_URB_THREAD_FIX */
++
+ struct workqueue_struct *system_nrt_wq __read_mostly;
+ EXPORT_SYMBOL_GPL(system_nrt_wq);
+
+@@ -106,6 +108,3 @@ void compat_system_workqueue_destroy()
+ {
+ destroy_workqueue(system_nrt_wq);
+ }
+-
+-#endif /* CONFIG_COMPAT_USB_URB_THREAD_FIX */
+-
#include <pcmcia/cs_types.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
-@@ -65,9 +65,9 @@ static inline struct sk_buff *netdev_all
+@@ -68,9 +68,9 @@ static inline struct sk_buff *netdev_all
return skb;
}
#endif
--- a/config.mk
+++ b/config.mk
-@@ -456,7 +456,7 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+@@ -453,7 +453,7 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
# This activates a threading fix for usb urb.
# this is mainline commit: b3e670443b7fb8a2d29831b62b44a039c283e351
# This fix will be included in some stable releases.
+#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/moduleparam.h>
+ #include <linux/module.h>
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -1,3 +1,4 @@
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
-@@ -844,7 +844,6 @@ static void table_flush_by_iface(struct
+@@ -841,7 +841,6 @@ static void table_flush_by_iface(struct
struct hlist_node *p;
int i;
---- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
-@@ -170,33 +170,104 @@ static bool ar9002_hw_get_isr(struct ath
- return true;
- }
-
--static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
-- bool is_firstseg, bool is_lastseg,
-- const void *ds0, dma_addr_t buf_addr,
-- unsigned int qcu)
-+static void
-+ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
- {
- struct ar5416_desc *ads = AR5416DESC(ds);
-+ u32 ctl1, ctl6;
-
-- ads->ds_data = buf_addr;
--
-- if (is_firstseg) {
-- ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
-- } else if (is_lastseg) {
-- ads->ds_ctl0 = 0;
-- ads->ds_ctl1 = seglen;
-- ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
-- ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
-- } else {
-- ads->ds_ctl0 = 0;
-- ads->ds_ctl1 = seglen | AR_TxMore;
-- ads->ds_ctl2 = 0;
-- ads->ds_ctl3 = 0;
-- }
- ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
- ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
- ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
- ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
- ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-+
-+ ACCESS_ONCE(ads->ds_link) = i->link;
-+ ACCESS_ONCE(ads->ds_data) = i->buf_addr[0];
-+
-+ ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore);
-+ ctl6 = SM(i->keytype, AR_EncrType);
-+
-+ if (AR_SREV_9285(ah)) {
-+ ads->ds_ctl8 = 0;
-+ ads->ds_ctl9 = 0;
-+ ads->ds_ctl10 = 0;
-+ ads->ds_ctl11 = 0;
-+ }
-+
-+ if ((i->is_first || i->is_last) &&
-+ i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) {
-+ ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0)
-+ | set11nTries(i->rates, 1)
-+ | set11nTries(i->rates, 2)
-+ | set11nTries(i->rates, 3)
-+ | (i->dur_update ? AR_DurUpdateEna : 0)
-+ | SM(0, AR_BurstDur);
-+
-+ ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0)
-+ | set11nRate(i->rates, 1)
-+ | set11nRate(i->rates, 2)
-+ | set11nRate(i->rates, 3);
-+ } else {
-+ ACCESS_ONCE(ads->ds_ctl2) = 0;
-+ ACCESS_ONCE(ads->ds_ctl3) = 0;
-+ }
-+
-+ if (!i->is_first) {
-+ ACCESS_ONCE(ads->ds_ctl0) = 0;
-+ ACCESS_ONCE(ads->ds_ctl1) = ctl1;
-+ ACCESS_ONCE(ads->ds_ctl6) = ctl6;
-+ return;
-+ }
-+
-+ ctl1 |= (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0)
-+ | SM(i->type, AR_FrameType)
-+ | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
-+ | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
-+ | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-+
-+ switch (i->aggr) {
-+ case AGGR_BUF_FIRST:
-+ ctl6 |= SM(i->aggr_len, AR_AggrLen);
-+ /* fall through */
-+ case AGGR_BUF_MIDDLE:
-+ ctl1 |= AR_IsAggr | AR_MoreAggr;
-+ ctl6 |= SM(i->ndelim, AR_PadDelim);
-+ break;
-+ case AGGR_BUF_LAST:
-+ ctl1 |= AR_IsAggr;
-+ break;
-+ case AGGR_BUF_NONE:
-+ break;
-+ }
-+
-+ ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
-+ | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-+ | SM(i->txpower, AR_XmitPower)
-+ | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-+ | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
-+ | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
-+ | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
-+ | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
-+ (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
-+
-+ ACCESS_ONCE(ads->ds_ctl1) = ctl1;
-+ ACCESS_ONCE(ads->ds_ctl6) = ctl6;
-+
-+ if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST)
-+ return;
-+
-+ ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0)
-+ | set11nPktDurRTSCTS(i->rates, 1);
-+
-+ ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2)
-+ | set11nPktDurRTSCTS(i->rates, 3);
-+
-+ ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0)
-+ | set11nRateFlags(i->rates, 1)
-+ | set11nRateFlags(i->rates, 2)
-+ | set11nRateFlags(i->rates, 3)
-+ | SM(i->rtscts_rate, AR_RTSCTSRate);
- }
-
- static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
-@@ -271,145 +342,6 @@ static int ar9002_hw_proc_txdesc(struct
- return 0;
- }
-
--static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
-- u32 pktLen, enum ath9k_pkt_type type,
-- u32 txPower, u8 keyIx,
-- enum ath9k_key_type keyType, u32 flags)
--{
-- struct ar5416_desc *ads = AR5416DESC(ds);
--
-- if (txPower > 63)
-- txPower = 63;
--
-- ads->ds_ctl0 = (pktLen & AR_FrameLen)
-- | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-- | SM(txPower, AR_XmitPower)
-- | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-- | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
-- | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
--
-- ads->ds_ctl1 =
-- (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
-- | SM(type, AR_FrameType)
-- | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
-- | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
-- | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
--
-- ads->ds_ctl6 = SM(keyType, AR_EncrType);
--
-- if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
-- ads->ds_ctl8 = 0;
-- ads->ds_ctl9 = 0;
-- ads->ds_ctl10 = 0;
-- ads->ds_ctl11 = 0;
-- }
--}
--
--static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
--{
-- struct ar5416_desc *ads = AR5416DESC(ds);
--
-- if (val)
-- ads->ds_ctl0 |= AR_ClrDestMask;
-- else
-- ads->ds_ctl0 &= ~AR_ClrDestMask;
--}
--
--static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
-- void *lastds,
-- u32 durUpdateEn, u32 rtsctsRate,
-- u32 rtsctsDuration,
-- struct ath9k_11n_rate_series series[],
-- u32 nseries, u32 flags)
--{
-- struct ar5416_desc *ads = AR5416DESC(ds);
-- struct ar5416_desc *last_ads = AR5416DESC(lastds);
-- u32 ds_ctl0;
--
-- if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
-- ds_ctl0 = ads->ds_ctl0;
--
-- if (flags & ATH9K_TXDESC_RTSENA) {
-- ds_ctl0 &= ~AR_CTSEnable;
-- ds_ctl0 |= AR_RTSEnable;
-- } else {
-- ds_ctl0 &= ~AR_RTSEnable;
-- ds_ctl0 |= AR_CTSEnable;
-- }
--
-- ads->ds_ctl0 = ds_ctl0;
-- } else {
-- ads->ds_ctl0 =
-- (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
-- }
--
-- ads->ds_ctl2 = set11nTries(series, 0)
-- | set11nTries(series, 1)
-- | set11nTries(series, 2)
-- | set11nTries(series, 3)
-- | (durUpdateEn ? AR_DurUpdateEna : 0)
-- | SM(0, AR_BurstDur);
--
-- ads->ds_ctl3 = set11nRate(series, 0)
-- | set11nRate(series, 1)
-- | set11nRate(series, 2)
-- | set11nRate(series, 3);
--
-- ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
-- | set11nPktDurRTSCTS(series, 1);
--
-- ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
-- | set11nPktDurRTSCTS(series, 3);
--
-- ads->ds_ctl7 = set11nRateFlags(series, 0)
-- | set11nRateFlags(series, 1)
-- | set11nRateFlags(series, 2)
-- | set11nRateFlags(series, 3)
-- | SM(rtsctsRate, AR_RTSCTSRate);
-- last_ads->ds_ctl2 = ads->ds_ctl2;
-- last_ads->ds_ctl3 = ads->ds_ctl3;
--}
--
--static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
-- u32 aggrLen)
--{
-- struct ar5416_desc *ads = AR5416DESC(ds);
--
-- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-- ads->ds_ctl6 &= ~AR_AggrLen;
-- ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
--}
--
--static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
-- u32 numDelims)
--{
-- struct ar5416_desc *ads = AR5416DESC(ds);
-- unsigned int ctl6;
--
-- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
--
-- ctl6 = ads->ds_ctl6;
-- ctl6 &= ~AR_PadDelim;
-- ctl6 |= SM(numDelims, AR_PadDelim);
-- ads->ds_ctl6 = ctl6;
--}
--
--static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
--{
-- struct ar5416_desc *ads = AR5416DESC(ds);
--
-- ads->ds_ctl1 |= AR_IsAggr;
-- ads->ds_ctl1 &= ~AR_MoreAggr;
-- ads->ds_ctl6 &= ~AR_PadDelim;
--}
--
--static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
--{
-- struct ar5416_desc *ads = AR5416DESC(ds);
--
-- ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
--}
--
- void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
- u32 size, u32 flags)
- {
-@@ -433,13 +365,6 @@ void ar9002_hw_attach_mac_ops(struct ath
- ops->rx_enable = ar9002_hw_rx_enable;
- ops->set_desc_link = ar9002_hw_set_desc_link;
- ops->get_isr = ar9002_hw_get_isr;
-- ops->fill_txdesc = ar9002_hw_fill_txdesc;
-+ ops->set_txdesc = ar9002_set_txdesc;
- ops->proc_txdesc = ar9002_hw_proc_txdesc;
-- ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
-- ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
-- ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
-- ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
-- ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
-- ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
-- ops->set_clrdmask = ar9002_hw_set_clrdmask;
- }
---- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
-@@ -652,8 +652,9 @@ static void ar9003_hw_detect_outlier(int
- outlier_idx = max_idx;
- else
- outlier_idx = min_idx;
-+
-+ mp_coeff[outlier_idx] = mp_avg;
- }
-- mp_coeff[outlier_idx] = mp_avg;
- }
-
- static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
-@@ -884,6 +885,7 @@ static bool ar9003_hw_init_cal(struct at
- if (txiqcal_done)
- ar9003_hw_tx_iq_cal_post_proc(ah);
-
-+ ath9k_hw_loadnf(ah, chan);
- ath9k_hw_start_nfcal(ah, true);
-
- /* Initialize list pointers */
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -21,6 +21,132 @@ static void ar9003_hw_rx_enable(struct a
- REG_WRITE(hw, AR_CR, 0);
- }
-
-+static void
-+ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
-+{
-+ struct ar9003_txc *ads = ds;
-+ int checksum = 0;
-+ u32 val, ctl12, ctl17;
-+
-+ val = (ATHEROS_VENDOR_ID << AR_DescId_S) |
-+ (1 << AR_TxRxDesc_S) |
-+ (1 << AR_CtrlStat_S) |
-+ (i->qcu << AR_TxQcuNum_S) | 0x17;
-+
-+ checksum += val;
-+ ACCESS_ONCE(ads->info) = val;
-+
-+ checksum += i->link;
-+ ACCESS_ONCE(ads->link) = i->link;
-+
-+ checksum += i->buf_addr[0];
-+ ACCESS_ONCE(ads->data0) = i->buf_addr[0];
-+ checksum += i->buf_addr[1];
-+ ACCESS_ONCE(ads->data1) = i->buf_addr[1];
-+ checksum += i->buf_addr[2];
-+ ACCESS_ONCE(ads->data2) = i->buf_addr[2];
-+ checksum += i->buf_addr[3];
-+ ACCESS_ONCE(ads->data3) = i->buf_addr[3];
-+
-+ checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen);
-+ ACCESS_ONCE(ads->ctl3) = val;
-+ checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen);
-+ ACCESS_ONCE(ads->ctl5) = val;
-+ checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen);
-+ ACCESS_ONCE(ads->ctl7) = val;
-+ checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen);
-+ ACCESS_ONCE(ads->ctl9) = val;
-+
-+ checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff);
-+ ACCESS_ONCE(ads->ctl10) = checksum;
-+
-+ if (i->is_first || i->is_last) {
-+ ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0)
-+ | set11nTries(i->rates, 1)
-+ | set11nTries(i->rates, 2)
-+ | set11nTries(i->rates, 3)
-+ | (i->dur_update ? AR_DurUpdateEna : 0)
-+ | SM(0, AR_BurstDur);
-+
-+ ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0)
-+ | set11nRate(i->rates, 1)
-+ | set11nRate(i->rates, 2)
-+ | set11nRate(i->rates, 3);
-+ } else {
-+ ACCESS_ONCE(ads->ctl13) = 0;
-+ ACCESS_ONCE(ads->ctl14) = 0;
-+ }
-+
-+ ads->ctl20 = 0;
-+ ads->ctl21 = 0;
-+ ads->ctl22 = 0;
-+
-+ ctl17 = SM(i->keytype, AR_EncrType);
-+ if (!i->is_first) {
-+ ACCESS_ONCE(ads->ctl11) = 0;
-+ ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore;
-+ ACCESS_ONCE(ads->ctl15) = 0;
-+ ACCESS_ONCE(ads->ctl16) = 0;
-+ ACCESS_ONCE(ads->ctl17) = ctl17;
-+ ACCESS_ONCE(ads->ctl18) = 0;
-+ ACCESS_ONCE(ads->ctl19) = 0;
-+ return;
-+ }
-+
-+ ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
-+ | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-+ | SM(i->txpower, AR_XmitPower)
-+ | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-+ | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
-+ | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
-+ | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
-+ | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable :
-+ (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0));
-+
-+ ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ?
-+ SM(i->keyix, AR_DestIdx) : 0)
-+ | SM(i->type, AR_FrameType)
-+ | (i->flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
-+ | (i->flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
-+ | (i->flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
-+
-+ ctl17 |= (i->flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
-+ switch (i->aggr) {
-+ case AGGR_BUF_FIRST:
-+ ctl17 |= SM(i->aggr_len, AR_AggrLen);
-+ /* fall through */
-+ case AGGR_BUF_MIDDLE:
-+ ctl12 |= AR_IsAggr | AR_MoreAggr;
-+ ctl17 |= SM(i->ndelim, AR_PadDelim);
-+ break;
-+ case AGGR_BUF_LAST:
-+ ctl12 |= AR_IsAggr;
-+ break;
-+ case AGGR_BUF_NONE:
-+ break;
-+ }
-+
-+ val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S;
-+ ctl12 |= SM(val, AR_PAPRDChainMask);
-+
-+ ACCESS_ONCE(ads->ctl12) = ctl12;
-+ ACCESS_ONCE(ads->ctl17) = ctl17;
-+
-+ ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0)
-+ | set11nPktDurRTSCTS(i->rates, 1);
-+
-+ ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2)
-+ | set11nPktDurRTSCTS(i->rates, 3);
-+
-+ ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0)
-+ | set11nRateFlags(i->rates, 1)
-+ | set11nRateFlags(i->rates, 2)
-+ | set11nRateFlags(i->rates, 3)
-+ | SM(i->rtscts_rate, AR_RTSCTSRate);
-+
-+ ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
-+}
-+
- static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
- {
- int checksum;
-@@ -185,47 +311,6 @@ static bool ar9003_hw_get_isr(struct ath
- return true;
- }
-
--static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
-- bool is_firstseg, bool is_lastseg,
-- const void *ds0, dma_addr_t buf_addr,
-- unsigned int qcu)
--{
-- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-- unsigned int descid = 0;
--
-- ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
-- (1 << AR_TxRxDesc_S) |
-- (1 << AR_CtrlStat_S) |
-- (qcu << AR_TxQcuNum_S) | 0x17;
--
-- ads->data0 = buf_addr;
-- ads->data1 = 0;
-- ads->data2 = 0;
-- ads->data3 = 0;
--
-- ads->ctl3 = (seglen << AR_BufLen_S);
-- ads->ctl3 &= AR_BufLen;
--
-- /* Fill in pointer checksum and descriptor id */
-- ads->ctl10 = ar9003_calc_ptr_chksum(ads);
-- ads->ctl10 |= (descid << AR_TxDescId_S);
--
-- if (is_firstseg) {
-- ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
-- } else if (is_lastseg) {
-- ads->ctl11 = 0;
-- ads->ctl12 = 0;
-- ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
-- ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
-- } else {
-- /* XXX Intermediate descriptor in a multi-descriptor frame.*/
-- ads->ctl11 = 0;
-- ads->ctl12 = AR_TxMore;
-- ads->ctl13 = 0;
-- ads->ctl14 = 0;
-- }
--}
--
- static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
- struct ath_tx_status *ts)
- {
-@@ -310,161 +395,6 @@ static int ar9003_hw_proc_txdesc(struct
- return 0;
- }
-
--static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
-- u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
-- u8 keyIx, enum ath9k_key_type keyType, u32 flags)
--{
-- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
--
-- if (txpower > ah->txpower_limit)
-- txpower = ah->txpower_limit;
--
-- if (txpower > 63)
-- txpower = 63;
--
-- ads->ctl11 = (pktlen & AR_FrameLen)
-- | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
-- | SM(txpower, AR_XmitPower)
-- | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
-- | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
-- | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
--
-- ads->ctl12 =
-- (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
-- | SM(type, AR_FrameType)
-- | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
-- | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
-- | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
--
-- ads->ctl17 = SM(keyType, AR_EncrType) |
-- (flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
-- ads->ctl18 = 0;
-- ads->ctl19 = AR_Not_Sounding;
--
-- ads->ctl20 = 0;
-- ads->ctl21 = 0;
-- ads->ctl22 = 0;
--}
--
--static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
--{
-- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
--
-- if (val)
-- ads->ctl11 |= AR_ClrDestMask;
-- else
-- ads->ctl11 &= ~AR_ClrDestMask;
--}
--
--static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
-- void *lastds,
-- u32 durUpdateEn, u32 rtsctsRate,
-- u32 rtsctsDuration,
-- struct ath9k_11n_rate_series series[],
-- u32 nseries, u32 flags)
--{
-- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-- struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
-- u_int32_t ctl11;
--
-- if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
-- ctl11 = ads->ctl11;
--
-- if (flags & ATH9K_TXDESC_RTSENA) {
-- ctl11 &= ~AR_CTSEnable;
-- ctl11 |= AR_RTSEnable;
-- } else {
-- ctl11 &= ~AR_RTSEnable;
-- ctl11 |= AR_CTSEnable;
-- }
--
-- ads->ctl11 = ctl11;
-- } else {
-- ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
-- }
--
-- ads->ctl13 = set11nTries(series, 0)
-- | set11nTries(series, 1)
-- | set11nTries(series, 2)
-- | set11nTries(series, 3)
-- | (durUpdateEn ? AR_DurUpdateEna : 0)
-- | SM(0, AR_BurstDur);
--
-- ads->ctl14 = set11nRate(series, 0)
-- | set11nRate(series, 1)
-- | set11nRate(series, 2)
-- | set11nRate(series, 3);
--
-- ads->ctl15 = set11nPktDurRTSCTS(series, 0)
-- | set11nPktDurRTSCTS(series, 1);
--
-- ads->ctl16 = set11nPktDurRTSCTS(series, 2)
-- | set11nPktDurRTSCTS(series, 3);
--
-- ads->ctl18 = set11nRateFlags(series, 0)
-- | set11nRateFlags(series, 1)
-- | set11nRateFlags(series, 2)
-- | set11nRateFlags(series, 3)
-- | SM(rtsctsRate, AR_RTSCTSRate);
-- ads->ctl19 = AR_Not_Sounding;
--
-- last_ads->ctl13 = ads->ctl13;
-- last_ads->ctl14 = ads->ctl14;
--}
--
--static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
-- u32 aggrLen)
--{
-- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
--
-- ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
--
-- ads->ctl17 &= ~AR_AggrLen;
-- ads->ctl17 |= SM(aggrLen, AR_AggrLen);
--}
--
--static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
-- u32 numDelims)
--{
-- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
-- unsigned int ctl17;
--
-- ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
--
-- /*
-- * We use a stack variable to manipulate ctl6 to reduce uncached
-- * read modify, modfiy, write.
-- */
-- ctl17 = ads->ctl17;
-- ctl17 &= ~AR_PadDelim;
-- ctl17 |= SM(numDelims, AR_PadDelim);
-- ads->ctl17 = ctl17;
--}
--
--static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
--{
-- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
--
-- ads->ctl12 |= AR_IsAggr;
-- ads->ctl12 &= ~AR_MoreAggr;
-- ads->ctl17 &= ~AR_PadDelim;
--}
--
--static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
--{
-- struct ar9003_txc *ads = (struct ar9003_txc *) ds;
--
-- ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
--}
--
--void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains)
--{
-- struct ar9003_txc *ads = ds;
--
-- ads->ctl12 |= SM(chains, AR_PAPRDChainMask);
--}
--EXPORT_SYMBOL(ar9003_hw_set_paprd_txdesc);
--
- void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
- {
- struct ath_hw_ops *ops = ath9k_hw_ops(hw);
-@@ -472,15 +402,8 @@ void ar9003_hw_attach_mac_ops(struct ath
- ops->rx_enable = ar9003_hw_rx_enable;
- ops->set_desc_link = ar9003_hw_set_desc_link;
- ops->get_isr = ar9003_hw_get_isr;
-- ops->fill_txdesc = ar9003_hw_fill_txdesc;
-+ ops->set_txdesc = ar9003_set_txdesc;
- ops->proc_txdesc = ar9003_hw_proc_txdesc;
-- ops->set11n_txdesc = ar9003_hw_set11n_txdesc;
-- ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario;
-- ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first;
-- ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle;
-- ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
-- ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
-- ops->set_clrdmask = ar9003_hw_set_clrdmask;
- }
-
- void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -87,17 +87,14 @@ struct ath_config {
- * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX)
- * @BUF_AGGR: Indicates whether the buffer can be aggregated
- * (used in aggregation scheduling)
-- * @BUF_XRETRY: To denote excessive retries of the buffer
- */
- enum buffer_type {
- BUF_AMPDU = BIT(0),
- BUF_AGGR = BIT(1),
-- BUF_XRETRY = BIT(2),
- };
-
- #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
- #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
--#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
-
- #define ATH_TXSTATUS_RING_SIZE 64
-
-@@ -216,6 +213,7 @@ struct ath_frame_info {
- struct ath_buf_state {
- u8 bf_type;
- u8 bfs_paprd;
-+ u8 ndelim;
- u16 seqno;
- unsigned long bfs_paprd_timestamp;
- };
-@@ -230,7 +228,6 @@ struct ath_buf {
- dma_addr_t bf_daddr; /* physical addr of desc */
- dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */
- bool bf_stale;
-- u16 bf_flags;
- struct ath_buf_state bf_state;
- };
-
-@@ -277,8 +274,7 @@ struct ath_tx_control {
- };
-
- #define ATH_TX_ERROR 0x01
--#define ATH_TX_XRETRY 0x02
--#define ATH_TX_BAR 0x04
-+#define ATH_TX_BAR 0x02
-
- /**
- * @txq_map: Index is mac80211 queue number. This is
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -73,44 +73,39 @@ static void ath_beacon_setup(struct ath_
- struct sk_buff *skb = bf->bf_mpdu;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
-- struct ath_desc *ds;
-- struct ath9k_11n_rate_series series[4];
-- int flags, ctsrate = 0, ctsduration = 0;
-+ struct ath_tx_info info;
- struct ieee80211_supported_band *sband;
-+ u8 chainmask = ah->txchainmask;
- u8 rate = 0;
-
- ath9k_reset_beacon_status(sc);
-
-- ds = bf->bf_desc;
-- flags = ATH9K_TXDESC_NOACK;
--
-- ds->ds_link = 0;
--
- sband = &sc->sbands[common->hw->conf.channel->band];
- rate = sband->bitrates[rateidx].hw_value;
- if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
- rate |= sband->bitrates[rateidx].hw_value_short;
-
-- ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
-- ATH9K_PKT_TYPE_BEACON,
-- MAX_RATE_POWER,
-- ATH9K_TXKEYIX_INVALID,
-- ATH9K_KEY_TYPE_CLEAR,
-- flags);
--
-- /* NB: beacon's BufLen must be a multiple of 4 bytes */
-- ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
-- true, true, ds, bf->bf_buf_addr,
-- sc->beacon.beaconq);
--
-- memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
-- series[0].Tries = 1;
-- series[0].Rate = rate;
-- series[0].ChSel = ath_txchainmask_reduction(sc,
-- ah->txchainmask, series[0].Rate);
-- series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
-- ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
-- series, 4, 0);
-+ memset(&info, 0, sizeof(info));
-+ info.pkt_len = skb->len + FCS_LEN;
-+ info.type = ATH9K_PKT_TYPE_BEACON;
-+ info.txpower = MAX_RATE_POWER;
-+ info.keyix = ATH9K_TXKEYIX_INVALID;
-+ info.keytype = ATH9K_KEY_TYPE_CLEAR;
-+ info.flags = ATH9K_TXDESC_NOACK;
-+
-+ info.buf_addr[0] = bf->bf_buf_addr;
-+ info.buf_len[0] = roundup(skb->len, 4);
-+
-+ info.is_first = true;
-+ info.is_last = true;
-+
-+ info.qcu = sc->beacon.beaconq;
-+
-+ info.rates[0].Tries = 1;
-+ info.rates[0].Rate = rate;
-+ info.rates[0].ChSel = ath_txchainmask_reduction(sc, chainmask, rate);
-+
-+ ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
- }
-
- static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
-@@ -517,6 +512,7 @@ static void ath_beacon_config_ap(struct
- /* Set the computed AP beacon timers */
-
- ath9k_hw_disable_interrupts(ah);
-+ sc->sc_flags |= SC_OP_TSF_RESET;
- ath9k_beacon_init(sc, nexttbtt, intval);
- sc->beacon.bmisscnt = 0;
- ath9k_hw_set_interrupts(ah, ah->imask);
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -826,7 +826,8 @@ static ssize_t read_file_misc(struct fil
- }
-
- void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
-- struct ath_tx_status *ts, struct ath_txq *txq)
-+ struct ath_tx_status *ts, struct ath_txq *txq,
-+ unsigned int flags)
- {
- #define TX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].ts\
- [sc->debug.tsidx].c)
-@@ -836,12 +837,12 @@ void ath_debug_stat_tx(struct ath_softc
- sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
-
- if (bf_isampdu(bf)) {
-- if (bf_isxretried(bf))
-+ if (flags & ATH_TX_BAR)
- TX_STAT_INC(qnum, a_xretries);
- else
- TX_STAT_INC(qnum, a_completed);
- } else {
-- if (bf_isxretried(bf))
-+ if (ts->ts_status & ATH9K_TXERR_XRETRY)
- TX_STAT_INC(qnum, xretries);
- else
- TX_STAT_INC(qnum, completed);
---- a/drivers/net/wireless/ath/ath9k/debug.h
-+++ b/drivers/net/wireless/ath/ath9k/debug.h
-@@ -230,7 +230,8 @@ int ath9k_init_debug(struct ath_hw *ah);
- void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
- void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
- void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
-- struct ath_tx_status *ts, struct ath_txq *txq);
-+ struct ath_tx_status *ts, struct ath_txq *txq,
-+ unsigned int flags);
- void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
-
- #else
-@@ -252,7 +253,8 @@ static inline void ath_debug_stat_interr
- static inline void ath_debug_stat_tx(struct ath_softc *sc,
- struct ath_buf *bf,
- struct ath_tx_status *ts,
-- struct ath_txq *txq)
-+ struct ath_txq *txq,
-+ unsigned int flags)
- {
- }
-
---- a/drivers/net/wireless/ath/ath9k/hw-ops.h
-+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
-@@ -54,13 +54,10 @@ static inline bool ath9k_hw_getisr(struc
- return ath9k_hw_ops(ah)->get_isr(ah, masked);
- }
-
--static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen,
-- bool is_firstseg, bool is_lastseg,
-- const void *ds0, dma_addr_t buf_addr,
-- unsigned int qcu)
-+static inline void ath9k_hw_set_txdesc(struct ath_hw *ah, void *ds,
-+ struct ath_tx_info *i)
- {
-- ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg,
-- ds0, buf_addr, qcu);
-+ return ath9k_hw_ops(ah)->set_txdesc(ah, ds, i);
- }
-
- static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
-@@ -69,55 +66,6 @@ static inline int ath9k_hw_txprocdesc(st
- return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
- }
-
--static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
-- u32 pktLen, enum ath9k_pkt_type type,
-- u32 txPower, u32 keyIx,
-- enum ath9k_key_type keyType,
-- u32 flags)
--{
-- ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx,
-- keyType, flags);
--}
--
--static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
-- void *lastds,
-- u32 durUpdateEn, u32 rtsctsRate,
-- u32 rtsctsDuration,
-- struct ath9k_11n_rate_series series[],
-- u32 nseries, u32 flags)
--{
-- ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn,
-- rtsctsRate, rtsctsDuration, series,
-- nseries, flags);
--}
--
--static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
-- u32 aggrLen)
--{
-- ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen);
--}
--
--static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
-- u32 numDelims)
--{
-- ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims);
--}
--
--static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
--{
-- ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds);
--}
--
--static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
--{
-- ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
--}
--
--static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val)
--{
-- ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val);
--}
--
- static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
- struct ath_hw_antcomb_conf *antconf)
- {
-@@ -233,11 +181,6 @@ static inline void ath9k_hw_restore_chai
- return ath9k_hw_private_ops(ah)->restore_chainmask(ah);
- }
-
--static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value)
--{
-- return ath9k_hw_private_ops(ah)->set_diversity(ah, value);
--}
--
- static inline bool ath9k_hw_ani_control(struct ath_hw *ah,
- enum ath9k_ani_cmd cmd, int param)
- {
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1496,14 +1496,16 @@ int ath9k_hw_reset(struct ath_hw *ah, st
- }
- ah->noise = ath9k_hw_getchan_noise(ah, chan);
-
-+ if ((AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) ||
-+ (AR_SREV_9300_20_OR_LATER(ah) && IS_CHAN_5GHZ(chan)))
-+ bChannelChange = false;
-+
- if (bChannelChange &&
- (ah->chip_fullsleep != true) &&
- (ah->curchan != NULL) &&
- (chan->channel != ah->curchan->channel) &&
- ((chan->channelFlags & CHANNEL_ALL) ==
-- (ah->curchan->channelFlags & CHANNEL_ALL)) &&
-- (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) {
--
-+ (ah->curchan->channelFlags & CHANNEL_ALL))) {
- if (ath9k_hw_channel_change(ah, chan)) {
- ath9k_hw_loadnf(ah, ah->curchan);
- ath9k_hw_start_nfcal(ah, true);
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -583,7 +583,6 @@ struct ath_hw_private_ops {
- bool (*rfbus_req)(struct ath_hw *ah);
- void (*rfbus_done)(struct ath_hw *ah);
- void (*restore_chainmask)(struct ath_hw *ah);
-- void (*set_diversity)(struct ath_hw *ah, bool value);
- u32 (*compute_pll_control)(struct ath_hw *ah,
- struct ath9k_channel *chan);
- bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
-@@ -615,30 +614,10 @@ struct ath_hw_ops {
- u8 rxchainmask,
- bool longcal);
- bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
-- void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen,
-- bool is_firstseg, bool is_is_lastseg,
-- const void *ds0, dma_addr_t buf_addr,
-- unsigned int qcu);
-+ void (*set_txdesc)(struct ath_hw *ah, void *ds,
-+ struct ath_tx_info *i);
- int (*proc_txdesc)(struct ath_hw *ah, void *ds,
- struct ath_tx_status *ts);
-- void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
-- u32 pktLen, enum ath9k_pkt_type type,
-- u32 txPower, u8 keyIx,
-- enum ath9k_key_type keyType,
-- u32 flags);
-- void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
-- void *lastds,
-- u32 durUpdateEn, u32 rtsctsRate,
-- u32 rtsctsDuration,
-- struct ath9k_11n_rate_series series[],
-- u32 nseries, u32 flags);
-- void (*set11n_aggr_first)(struct ath_hw *ah, void *ds,
-- u32 aggrLen);
-- void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds,
-- u32 numDelims);
-- void (*set11n_aggr_last)(struct ath_hw *ah, void *ds);
-- void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
-- void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val);
- void (*antdiv_comb_conf_get)(struct ath_hw *ah,
- struct ath_hw_antcomb_conf *antconf);
- void (*antdiv_comb_conf_set)(struct ath_hw *ah,
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -62,18 +62,6 @@ void ath9k_hw_txstart(struct ath_hw *ah,
- }
- EXPORT_SYMBOL(ath9k_hw_txstart);
-
--void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
--{
-- struct ar5416_desc *ads = AR5416DESC(ds);
--
-- ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
-- ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
-- ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
-- ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
-- ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
--}
--EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
--
- u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
- {
- u32 npend;
-@@ -596,7 +584,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
- else
- rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
-
-- rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
-+ rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);
- rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
-
- rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -17,10 +17,6 @@
- #ifndef MAC_H
- #define MAC_H
-
--#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \
-- MS(ads->ds_rxstatus0, AR_RxRate) : \
-- (ads->ds_rxstatus3 >> 2) & 0xFF)
--
- #define set11nTries(_series, _index) \
- (SM((_series)[_index].Tries, AR_XmitDataTries##_index))
-
-@@ -263,7 +259,11 @@ struct ath_desc {
- #define ATH9K_TXDESC_VMF 0x0100
- #define ATH9K_TXDESC_FRAG_IS_ON 0x0200
- #define ATH9K_TXDESC_LOWRXCHAIN 0x0400
--#define ATH9K_TXDESC_LDPC 0x00010000
-+#define ATH9K_TXDESC_LDPC 0x0800
-+#define ATH9K_TXDESC_CLRDMASK 0x1000
-+
-+#define ATH9K_TXDESC_PAPRD 0x70000
-+#define ATH9K_TXDESC_PAPRD_S 16
-
- #define ATH9K_RXDESC_INTREQ 0x0020
-
-@@ -659,6 +659,13 @@ struct ath9k_11n_rate_series {
- u32 RateFlags;
- };
-
-+enum aggr_type {
-+ AGGR_BUF_NONE,
-+ AGGR_BUF_FIRST,
-+ AGGR_BUF_MIDDLE,
-+ AGGR_BUF_LAST,
-+};
-+
- enum ath9k_key_type {
- ATH9K_KEY_TYPE_CLEAR,
- ATH9K_KEY_TYPE_WEP,
-@@ -666,6 +673,33 @@ enum ath9k_key_type {
- ATH9K_KEY_TYPE_TKIP,
- };
-
-+struct ath_tx_info {
-+ u8 qcu;
-+
-+ bool is_first;
-+ bool is_last;
-+
-+ enum aggr_type aggr;
-+ u8 ndelim;
-+ u16 aggr_len;
-+
-+ dma_addr_t link;
-+ int pkt_len;
-+ u32 flags;
-+
-+ dma_addr_t buf_addr[4];
-+ int buf_len[4];
-+
-+ struct ath9k_11n_rate_series rates[4];
-+ u8 rtscts_rate;
-+ bool dur_update;
-+
-+ enum ath9k_pkt_type type;
-+ enum ath9k_key_type keytype;
-+ u8 keyix;
-+ u8 txpower;
-+};
-+
- struct ath_hw;
- struct ath9k_channel;
- enum ath9k_int;
-@@ -673,7 +707,6 @@ 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);
- void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
--void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
- u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
- bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
- bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -111,24 +111,29 @@ void ath9k_ps_wakeup(struct ath_softc *s
- void ath9k_ps_restore(struct ath_softc *sc)
- {
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+ enum ath9k_power_mode mode;
- unsigned long flags;
-
- spin_lock_irqsave(&sc->sc_pm_lock, flags);
+@@ -118,7 +118,7 @@ void ath9k_ps_restore(struct ath_softc *
if (--sc->ps_usecount != 0)
goto unlock;
-- spin_lock(&common->cc_lock);
-- ath_hw_cycle_counters_update(common);
-- spin_unlock(&common->cc_lock);
--
- if (sc->ps_idle)
-- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
-+ mode = ATH9K_PM_FULL_SLEEP;
+- if (sc->ps_idle)
++ if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
+ mode = ATH9K_PM_FULL_SLEEP;
else if (sc->ps_enabled &&
- !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
- PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA |
- PS_WAIT_FOR_TX_ACK)))
-- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
-+ mode = ATH9K_PM_NETWORK_SLEEP;
-+ else
-+ goto unlock;
-+
-+ spin_lock(&common->cc_lock);
-+ ath_hw_cycle_counters_update(common);
-+ spin_unlock(&common->cc_lock);
-+
-+ ath9k_hw_setpower(sc->sc_ah, mode);
-
- unlock:
- spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
-@@ -247,8 +252,8 @@ static bool ath_prepare_reset(struct ath
-
- if (!flush) {
- if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
-- ath_rx_tasklet(sc, 0, true);
-- ath_rx_tasklet(sc, 0, false);
-+ ath_rx_tasklet(sc, 1, true);
-+ ath_rx_tasklet(sc, 1, false);
- } else {
- ath_flushrecv(sc);
- }
-@@ -669,15 +674,15 @@ void ath9k_tasklet(unsigned long data)
- u32 status = sc->intrstatus;
- u32 rxmask;
-
-+ ath9k_ps_wakeup(sc);
-+ spin_lock(&sc->sc_pcu_lock);
-+
- if ((status & ATH9K_INT_FATAL) ||
- (status & ATH9K_INT_BB_WATCHDOG)) {
- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
-- return;
-+ goto out;
- }
-
-- ath9k_ps_wakeup(sc);
-- spin_lock(&sc->sc_pcu_lock);
--
- /*
- * Only run the baseband hang check if beacons stop working in AP or
- * IBSS mode, because it has a high false positive rate. For station
-@@ -725,6 +730,7 @@ void ath9k_tasklet(unsigned long data)
- if (status & ATH9K_INT_GENTIMER)
- ath_gen_timer_isr(sc->sc_ah);
-
-+out:
- /* re-enable hardware interrupt */
- ath9k_hw_enable_interrupts(ah);
-
-@@ -2015,6 +2021,7 @@ static void ath9k_config_bss(struct ath_
- /* Stop ANI */
- sc->sc_flags &= ~SC_OP_ANI_RUN;
- del_timer_sync(&common->ani.timer);
-+ memset(&sc->caldata, 0, sizeof(sc->caldata));
- }
- }
-
---- a/drivers/net/wireless/ath/ath9k/pci.c
-+++ b/drivers/net/wireless/ath/ath9k/pci.c
-@@ -332,16 +332,16 @@ static int ath_pci_resume(struct device
- if ((val & 0x0000ff00) != 0)
- pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-
-+ ath9k_ps_wakeup(sc);
- /* Enable LED */
- ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
-+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
-
- /*
- * Reset key cache to sane defaults (all entries cleared) instead of
- * semi-random values after suspend/resume.
- */
-- ath9k_ps_wakeup(sc);
- ath9k_cmn_init_crypto(sc->sc_ah);
- ath9k_ps_restore(sc);
-
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -1839,7 +1839,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
- * If we're asked to flush receive queue, directly
- * chain it back at the queue without processing it.
- */
-- if (flush)
-+ if (sc->sc_flags & SC_OP_RXFLUSH)
- goto requeue_drop_frag;
-
- retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
-@@ -1967,7 +1967,8 @@ requeue:
- } else {
- list_move_tail(&bf->list, &sc->rx.rxbuf);
- ath_rx_buf_link(sc, bf);
-- ath9k_hw_rxena(ah);
-+ if (!flush)
-+ ath9k_hw_rxena(ah);
- }
- } while (1);
-
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -56,10 +56,9 @@ static void ath_tx_complete_buf(struct a
- struct ath_tx_status *ts, int txok, int sendbar);
- static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
- struct list_head *head, bool internal);
--static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
- static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_tx_status *ts, int nframes, int nbad,
-- int txok, bool update_rc);
-+ int txok);
- static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
- int seqno);
- static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
-@@ -263,6 +262,7 @@ static void ath_tx_set_retry(struct ath_
- struct sk_buff *skb)
- {
- struct ath_frame_info *fi = get_frame_info(skb);
-+ struct ath_buf *bf = fi->bf;
- struct ieee80211_hdr *hdr;
-
- TX_STAT_INC(txq->axq_qnum, a_retries);
-@@ -271,6 +271,8 @@ static void ath_tx_set_retry(struct ath_
-
- hdr = (struct ieee80211_hdr *)skb->data;
- hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
-+ dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
-+ sizeof(*hdr), DMA_TO_DEVICE);
- }
-
- static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
-@@ -390,11 +392,9 @@ static void ath_tx_complete_aggr(struct
- while (bf) {
- bf_next = bf->bf_next;
-
-- bf->bf_state.bf_type |= BUF_XRETRY;
- if (!bf->bf_stale || bf_next != NULL)
- list_move_tail(&bf->list, &bf_head);
-
-- ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
- ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
- 0, 0);
-
-@@ -470,7 +470,6 @@ static void ath_tx_complete_aggr(struct
- clear_filter = true;
- txpending = 1;
- } else {
-- bf->bf_state.bf_type |= BUF_XRETRY;
- txfail = 1;
- sendbar = 1;
- txfail_cnt++;
-@@ -497,17 +496,14 @@ static void ath_tx_complete_aggr(struct
-
- if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
- memcpy(tx_info->control.rates, rates, sizeof(rates));
-- ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true);
-+ ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok);
- rc_update = false;
-- } else {
-- ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false);
- }
-
- ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
- !txfail, sendbar);
- } else {
- /* retry the un-acked ones */
-- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false);
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
- if (bf->bf_next == NULL && bf_last->bf_stale) {
- struct ath_buf *tbf;
-@@ -523,26 +519,13 @@ static void ath_tx_complete_aggr(struct
- ath_tx_update_baw(sc, tid, seqno);
- spin_unlock_bh(&txq->axq_lock);
-
-- bf->bf_state.bf_type |=
-- BUF_XRETRY;
-- ath_tx_rc_status(sc, bf, ts, nframes,
-- nbad, 0, false);
- ath_tx_complete_buf(sc, bf, txq,
- &bf_head,
-- ts, 0, 0);
-+ ts, 0, 1);
- break;
- }
-
-- ath9k_hw_cleartxdesc(sc->sc_ah,
-- tbf->bf_desc);
- fi->bf = tbf;
-- } else {
-- /*
-- * Clear descriptor status words for
-- * software retry
-- */
-- ath9k_hw_cleartxdesc(sc->sc_ah,
-- bf->bf_desc);
- }
- }
-
-@@ -778,7 +761,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
- if (!bf)
- continue;
-
-- bf->bf_state.bf_type |= BUF_AMPDU;
-+ bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
- seqno = bf->bf_state.seqno;
- if (!bf_first)
- bf_first = bf;
-@@ -805,8 +788,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
- }
-
- tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
-- if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) ||
-- !(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS)))
-+ if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
- break;
-
- /* do not exceed subframe limit */
-@@ -828,20 +810,17 @@ static enum ATH_AGGR_STATUS ath_tx_form_
-
- nframes++;
- bf->bf_next = NULL;
-- ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
-
- /* link buffers of this frame to the aggregate */
- if (!fi->retries)
- ath_tx_addto_baw(sc, tid, seqno);
-- ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
-+ bf->bf_state.ndelim = ndelim;
-
- __skb_unlink(skb, &tid->buf_q);
- list_add_tail(&bf->list, bf_q);
-- if (bf_prev) {
-+ if (bf_prev)
- bf_prev->bf_next = bf;
-- ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
-- bf->bf_daddr);
-- }
-+
- bf_prev = bf;
-
- } while (!skb_queue_empty(&tid->buf_q));
-@@ -852,12 +831,245 @@ static enum ATH_AGGR_STATUS ath_tx_form_
- #undef PADBYTES
- }
-
-+/*
-+ * rix - rate index
-+ * pktlen - total bytes (delims + data + fcs + pads + pad delims)
-+ * width - 0 for 20 MHz, 1 for 40 MHz
-+ * half_gi - to use 4us v/s 3.6 us for symbol time
-+ */
-+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
-+ int width, int half_gi, bool shortPreamble)
-+{
-+ u32 nbits, nsymbits, duration, nsymbols;
-+ int streams;
-+
-+ /* find number of symbols: PLCP + data */
-+ streams = HT_RC_2_STREAMS(rix);
-+ nbits = (pktlen << 3) + OFDM_PLCP_BITS;
-+ nsymbits = bits_per_symbol[rix % 8][width] * streams;
-+ nsymbols = (nbits + nsymbits - 1) / nsymbits;
-+
-+ if (!half_gi)
-+ duration = SYMBOL_TIME(nsymbols);
-+ else
-+ duration = SYMBOL_TIME_HALFGI(nsymbols);
-+
-+ /* addup duration for legacy/ht training and signal fields */
-+ duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
-+
-+ return duration;
-+}
-+
-+static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
-+ struct ath_tx_info *info, int len)
-+{
-+ struct ath_hw *ah = sc->sc_ah;
-+ struct sk_buff *skb;
-+ struct ieee80211_tx_info *tx_info;
-+ struct ieee80211_tx_rate *rates;
-+ const struct ieee80211_rate *rate;
-+ struct ieee80211_hdr *hdr;
-+ int i;
-+ u8 rix = 0;
-+
-+ skb = bf->bf_mpdu;
-+ tx_info = IEEE80211_SKB_CB(skb);
-+ rates = tx_info->control.rates;
-+ hdr = (struct ieee80211_hdr *)skb->data;
-+
-+ /* set dur_update_en for l-sig computation except for PS-Poll frames */
-+ info->dur_update = !ieee80211_is_pspoll(hdr->frame_control);
-+
-+ /*
-+ * We check if Short Preamble is needed for the CTS rate by
-+ * checking the BSS's global flag.
-+ * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
-+ */
-+ rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
-+ info->rtscts_rate = rate->hw_value;
-+ if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
-+ info->rtscts_rate |= rate->hw_value_short;
-+
-+ for (i = 0; i < 4; i++) {
-+ bool is_40, is_sgi, is_sp;
-+ int phy;
-+
-+ if (!rates[i].count || (rates[i].idx < 0))
-+ continue;
-+
-+ rix = rates[i].idx;
-+ info->rates[i].Tries = rates[i].count;
-+
-+ if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-+ info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-+ info->flags |= ATH9K_TXDESC_RTSENA;
-+ } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-+ info->rates[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-+ info->flags |= ATH9K_TXDESC_CTSENA;
-+ }
-+
-+ if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-+ info->rates[i].RateFlags |= ATH9K_RATESERIES_2040;
-+ if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
-+ info->rates[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
-+
-+ is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
-+ is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
-+ is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
-+
-+ if (rates[i].flags & IEEE80211_TX_RC_MCS) {
-+ /* MCS rates */
-+ info->rates[i].Rate = rix | 0x80;
-+ info->rates[i].ChSel = ath_txchainmask_reduction(sc,
-+ ah->txchainmask, info->rates[i].Rate);
-+ info->rates[i].PktDuration = ath_pkt_duration(sc, rix, len,
-+ is_40, is_sgi, is_sp);
-+ if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
-+ info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
-+ continue;
-+ }
-+
-+ /* legacy rates */
-+ if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
-+ !(rate->flags & IEEE80211_RATE_ERP_G))
-+ phy = WLAN_RC_PHY_CCK;
-+ else
-+ phy = WLAN_RC_PHY_OFDM;
-+
-+ rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
-+ info->rates[i].Rate = rate->hw_value;
-+ if (rate->hw_value_short) {
-+ if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-+ info->rates[i].Rate |= rate->hw_value_short;
-+ } else {
-+ is_sp = false;
-+ }
-+
-+ if (bf->bf_state.bfs_paprd)
-+ info->rates[i].ChSel = ah->txchainmask;
-+ else
-+ info->rates[i].ChSel = ath_txchainmask_reduction(sc,
-+ ah->txchainmask, info->rates[i].Rate);
-+
-+ info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
-+ phy, rate->bitrate * 100, len, rix, is_sp);
-+ }
-+
-+ /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
-+ if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
-+ info->flags &= ~ATH9K_TXDESC_RTSENA;
-+
-+ /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
-+ if (info->flags & ATH9K_TXDESC_RTSENA)
-+ info->flags &= ~ATH9K_TXDESC_CTSENA;
-+}
-+
-+static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
-+{
-+ struct ieee80211_hdr *hdr;
-+ enum ath9k_pkt_type htype;
-+ __le16 fc;
-+
-+ hdr = (struct ieee80211_hdr *)skb->data;
-+ fc = hdr->frame_control;
-+
-+ if (ieee80211_is_beacon(fc))
-+ htype = ATH9K_PKT_TYPE_BEACON;
-+ else if (ieee80211_is_probe_resp(fc))
-+ htype = ATH9K_PKT_TYPE_PROBE_RESP;
-+ else if (ieee80211_is_atim(fc))
-+ htype = ATH9K_PKT_TYPE_ATIM;
-+ else if (ieee80211_is_pspoll(fc))
-+ htype = ATH9K_PKT_TYPE_PSPOLL;
-+ else
-+ htype = ATH9K_PKT_TYPE_NORMAL;
-+
-+ return htype;
-+}
-+
-+static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
-+ struct ath_txq *txq, int len)
-+{
-+ struct ath_hw *ah = sc->sc_ah;
-+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
-+ struct ath_buf *bf_first = bf;
-+ struct ath_tx_info info;
-+ bool aggr = !!(bf->bf_state.bf_type & BUF_AGGR);
-+
-+ memset(&info, 0, sizeof(info));
-+ info.is_first = true;
-+ info.is_last = true;
-+ info.txpower = MAX_RATE_POWER;
-+ info.qcu = txq->axq_qnum;
-+
-+ info.flags = ATH9K_TXDESC_INTREQ;
-+ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
-+ info.flags |= ATH9K_TXDESC_NOACK;
-+ if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
-+ info.flags |= ATH9K_TXDESC_LDPC;
-+
-+ ath_buf_set_rate(sc, bf, &info, len);
-+
-+ if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
-+ info.flags |= ATH9K_TXDESC_CLRDMASK;
-+
-+ if (bf->bf_state.bfs_paprd)
-+ info.flags |= (u32) bf->bf_state.bfs_paprd << ATH9K_TXDESC_PAPRD_S;
-+
-+
-+ while (bf) {
-+ struct sk_buff *skb = bf->bf_mpdu;
-+ struct ath_frame_info *fi = get_frame_info(skb);
-+ struct ieee80211_hdr *hdr;
-+ int padpos, padsize;
-+
-+ info.type = get_hw_packet_type(skb);
-+ if (bf->bf_next)
-+ info.link = bf->bf_next->bf_daddr;
-+ else
-+ info.link = 0;
-+
-+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
-+ hdr = (struct ieee80211_hdr *)skb->data;
-+ padpos = ath9k_cmn_padpos(hdr->frame_control);
-+ padsize = padpos & 3;
-+
-+ info.buf_addr[0] = bf->bf_buf_addr;
-+ info.buf_len[0] = padpos + padsize;
-+ info.buf_addr[1] = info.buf_addr[0] + padpos;
-+ info.buf_len[1] = skb->len - padpos;
-+ } else {
-+ info.buf_addr[0] = bf->bf_buf_addr;
-+ info.buf_len[0] = skb->len;
-+ }
-+
-+ info.pkt_len = fi->framelen;
-+ info.keyix = fi->keyix;
-+ info.keytype = fi->keytype;
-+
-+ if (aggr) {
-+ if (bf == bf_first)
-+ info.aggr = AGGR_BUF_FIRST;
-+ else if (!bf->bf_next)
-+ info.aggr = AGGR_BUF_LAST;
-+ else
-+ info.aggr = AGGR_BUF_MIDDLE;
-+
-+ info.ndelim = bf->bf_state.ndelim;
-+ info.aggr_len = len;
-+ }
-+
-+ ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
-+ bf = bf->bf_next;
-+ }
-+}
-+
- static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid)
- {
- struct ath_buf *bf;
- enum ATH_AGGR_STATUS status;
-- struct ath_frame_info *fi;
-+ struct ieee80211_tx_info *tx_info;
- struct list_head bf_q;
- int aggr_len;
-
-@@ -878,34 +1090,25 @@ static void ath_tx_sched_aggr(struct ath
-
- bf = list_first_entry(&bf_q, struct ath_buf, list);
- bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list);
-+ tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
-
- if (tid->ac->clear_ps_filter) {
- tid->ac->clear_ps_filter = false;
-- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
-+ tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
-+ } else {
-+ tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
- }
-
- /* if only one frame, send as non-aggregate */
- if (bf == bf->bf_lastbf) {
-- fi = get_frame_info(bf->bf_mpdu);
--
-- bf->bf_state.bf_type &= ~BUF_AGGR;
-- ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc);
-- ath_buf_set_rate(sc, bf, fi->framelen);
-- ath_tx_txqaddbuf(sc, txq, &bf_q, false);
-- continue;
-+ aggr_len = get_frame_info(bf->bf_mpdu)->framelen;
-+ bf->bf_state.bf_type = BUF_AMPDU;
-+ } else {
-+ TX_STAT_INC(txq->axq_qnum, a_aggr);
- }
-
-- /* setup first desc of aggregate */
-- bf->bf_state.bf_type |= BUF_AGGR;
-- ath_buf_set_rate(sc, bf, aggr_len);
-- ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len);
--
-- /* anchor last desc of aggregate */
-- ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc);
--
-+ ath_tx_fill_desc(sc, bf, txq, aggr_len);
- ath_tx_txqaddbuf(sc, txq, &bf_q, false);
-- TX_STAT_INC(txq->axq_qnum, a_aggr);
--
- } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
- status != ATH_AGGR_BAW_CLOSED);
- }
-@@ -1483,7 +1686,7 @@ static void ath_tx_send_ampdu(struct ath
- if (!bf)
- return;
-
-- bf->bf_state.bf_type |= BUF_AMPDU;
-+ bf->bf_state.bf_type = BUF_AMPDU;
- INIT_LIST_HEAD(&bf_head);
- list_add(&bf->list, &bf_head);
-
-@@ -1493,7 +1696,7 @@ static void ath_tx_send_ampdu(struct ath
- /* Queue to h/w without aggregation */
- TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
- bf->bf_lastbf = bf;
-- ath_buf_set_rate(sc, bf, fi->framelen);
-+ ath_tx_fill_desc(sc, bf, txctl->txq, fi->framelen);
- ath_tx_txqaddbuf(sc, txctl->txq, &bf_head, false);
- }
-
-@@ -1513,41 +1716,18 @@ static void ath_tx_send_normal(struct at
-
- INIT_LIST_HEAD(&bf_head);
- list_add_tail(&bf->list, &bf_head);
-- bf->bf_state.bf_type &= ~BUF_AMPDU;
-+ bf->bf_state.bf_type = 0;
-
- /* update starting sequence number for subsequent ADDBA request */
- if (tid)
- INCR(tid->seq_start, IEEE80211_SEQ_MAX);
-
- bf->bf_lastbf = bf;
-- ath_buf_set_rate(sc, bf, fi->framelen);
-+ ath_tx_fill_desc(sc, bf, txq, fi->framelen);
- ath_tx_txqaddbuf(sc, txq, &bf_head, false);
- TX_STAT_INC(txq->axq_qnum, queued);
- }
-
--static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
--{
-- struct ieee80211_hdr *hdr;
-- enum ath9k_pkt_type htype;
-- __le16 fc;
--
-- hdr = (struct ieee80211_hdr *)skb->data;
-- fc = hdr->frame_control;
--
-- if (ieee80211_is_beacon(fc))
-- htype = ATH9K_PKT_TYPE_BEACON;
-- else if (ieee80211_is_probe_resp(fc))
-- htype = ATH9K_PKT_TYPE_PROBE_RESP;
-- else if (ieee80211_is_atim(fc))
-- htype = ATH9K_PKT_TYPE_ATIM;
-- else if (ieee80211_is_pspoll(fc))
-- htype = ATH9K_PKT_TYPE_PSPOLL;
-- else
-- htype = ATH9K_PKT_TYPE_NORMAL;
--
-- return htype;
--}
--
- static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
- int framelen)
- {
-@@ -1575,51 +1755,6 @@ static void setup_frame_info(struct ieee
- fi->framelen = framelen;
- }
-
--static int setup_tx_flags(struct sk_buff *skb)
--{
-- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-- int flags = 0;
--
-- flags |= ATH9K_TXDESC_INTREQ;
--
-- if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
-- flags |= ATH9K_TXDESC_NOACK;
--
-- if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
-- flags |= ATH9K_TXDESC_LDPC;
--
-- return flags;
--}
--
--/*
-- * rix - rate index
-- * pktlen - total bytes (delims + data + fcs + pads + pad delims)
-- * width - 0 for 20 MHz, 1 for 40 MHz
-- * half_gi - to use 4us v/s 3.6 us for symbol time
-- */
--static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
-- int width, int half_gi, bool shortPreamble)
--{
-- u32 nbits, nsymbits, duration, nsymbols;
-- int streams;
--
-- /* find number of symbols: PLCP + data */
-- streams = HT_RC_2_STREAMS(rix);
-- nbits = (pktlen << 3) + OFDM_PLCP_BITS;
-- nsymbits = bits_per_symbol[rix % 8][width] * streams;
-- nsymbols = (nbits + nsymbits - 1) / nsymbits;
--
-- if (!half_gi)
-- duration = SYMBOL_TIME(nsymbols);
-- else
-- duration = SYMBOL_TIME_HALFGI(nsymbols);
--
-- /* addup duration for legacy/ht training and signal fields */
-- duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
--
-- return duration;
--}
--
- u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
- {
- struct ath_hw *ah = sc->sc_ah;
-@@ -1632,118 +1767,6 @@ u8 ath_txchainmask_reduction(struct ath_
- return chainmask;
+ !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
+@@ -332,7 +332,8 @@ static int ath_reset_internal(struct ath
+ hchan = ah->curchan;
+ }
+
+- if (fastcc && !ath9k_hw_check_alive(ah))
++ if (fastcc && (ah->chip_fullsleep ||
++ !ath9k_hw_check_alive(ah)))
+ fastcc = false;
+
+ if (!ath_prepare_reset(sc, retry_tx, flush))
+@@ -882,82 +883,6 @@ chip_reset:
+ #undef SCHED_INTR
}
--static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
+-static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
-{
- struct ath_hw *ah = sc->sc_ah;
-- struct ath9k_11n_rate_series series[4];
-- struct sk_buff *skb;
-- struct ieee80211_tx_info *tx_info;
-- struct ieee80211_tx_rate *rates;
-- const struct ieee80211_rate *rate;
-- struct ieee80211_hdr *hdr;
-- int i, flags = 0;
-- u8 rix = 0, ctsrate = 0;
-- bool is_pspoll;
+- struct ath_common *common = ath9k_hw_common(ah);
+- struct ieee80211_channel *channel = hw->conf.channel;
+- int r;
-
-- memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
--
-- skb = bf->bf_mpdu;
-- tx_info = IEEE80211_SKB_CB(skb);
-- rates = tx_info->control.rates;
-- hdr = (struct ieee80211_hdr *)skb->data;
-- is_pspoll = ieee80211_is_pspoll(hdr->frame_control);
+- ath9k_ps_wakeup(sc);
+- spin_lock_bh(&sc->sc_pcu_lock);
+- atomic_set(&ah->intr_ref_cnt, -1);
-
-- /*
-- * We check if Short Preamble is needed for the CTS rate by
-- * checking the BSS's global flag.
-- * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
-- */
-- rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
-- ctsrate = rate->hw_value;
-- if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
-- ctsrate |= rate->hw_value_short;
+- ath9k_hw_configpcipowersave(ah, false);
-
-- for (i = 0; i < 4; i++) {
-- bool is_40, is_sgi, is_sp;
-- int phy;
+- if (!ah->curchan)
+- ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);
-
-- if (!rates[i].count || (rates[i].idx < 0))
-- continue;
+- r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+- if (r) {
+- ath_err(common,
+- "Unable to reset channel (%u MHz), reset status %d\n",
+- channel->center_freq, r);
+- }
-
-- rix = rates[i].idx;
-- series[i].Tries = rates[i].count;
+- ath_complete_reset(sc, true);
-
-- if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-- flags |= ATH9K_TXDESC_RTSENA;
-- } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-- flags |= ATH9K_TXDESC_CTSENA;
-- }
+- /* Enable LED */
+- ath9k_hw_cfg_output(ah, ah->led_pin,
+- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+- ath9k_hw_set_gpio(ah, ah->led_pin, 0);
-
-- if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-- series[i].RateFlags |= ATH9K_RATESERIES_2040;
-- if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
-- series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
+- spin_unlock_bh(&sc->sc_pcu_lock);
-
-- is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
-- is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
-- is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
+- ath9k_ps_restore(sc);
+-}
-
-- if (rates[i].flags & IEEE80211_TX_RC_MCS) {
-- /* MCS rates */
-- series[i].Rate = rix | 0x80;
-- series[i].ChSel = ath_txchainmask_reduction(sc,
-- ah->txchainmask, series[i].Rate);
-- series[i].PktDuration = ath_pkt_duration(sc, rix, len,
-- is_40, is_sgi, is_sp);
-- if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
-- series[i].RateFlags |= ATH9K_RATESERIES_STBC;
-- continue;
-- }
+-void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
+-{
+- struct ath_hw *ah = sc->sc_ah;
+- struct ieee80211_channel *channel = hw->conf.channel;
+- int r;
-
-- /* legacy rates */
-- if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
-- !(rate->flags & IEEE80211_RATE_ERP_G))
-- phy = WLAN_RC_PHY_CCK;
-- else
-- phy = WLAN_RC_PHY_OFDM;
+- ath9k_ps_wakeup(sc);
-
-- rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
-- series[i].Rate = rate->hw_value;
-- if (rate->hw_value_short) {
-- if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-- series[i].Rate |= rate->hw_value_short;
-- } else {
-- is_sp = false;
-- }
+- ath_cancel_work(sc);
-
-- if (bf->bf_state.bfs_paprd)
-- series[i].ChSel = ah->txchainmask;
-- else
-- series[i].ChSel = ath_txchainmask_reduction(sc,
-- ah->txchainmask, series[i].Rate);
+- spin_lock_bh(&sc->sc_pcu_lock);
-
-- series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
-- phy, rate->bitrate * 100, len, rix, is_sp);
+- /*
+- * Keep the LED on when the radio is disabled
+- * during idle unassociated state.
+- */
+- if (!sc->ps_idle) {
+- ath9k_hw_set_gpio(ah, ah->led_pin, 1);
+- ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
- }
-
-- /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
-- if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit))
-- flags &= ~ATH9K_TXDESC_RTSENA;
+- ath_prepare_reset(sc, false, true);
+-
+- if (!ah->curchan)
+- ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
-
-- /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */
-- if (flags & ATH9K_TXDESC_RTSENA)
-- flags &= ~ATH9K_TXDESC_CTSENA;
+- r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
+- if (r) {
+- ath_err(ath9k_hw_common(sc->sc_ah),
+- "Unable to reset channel (%u MHz), reset status %d\n",
+- channel->center_freq, r);
+- }
+-
+- ath9k_hw_phy_disable(ah);
-
-- /* set dur_update_en for l-sig computation except for PS-Poll frames */
-- ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc,
-- bf->bf_lastbf->bf_desc,
-- !is_pspoll, ctsrate,
-- 0, series, 4, flags);
+- ath9k_hw_configpcipowersave(ah, true);
-
+- spin_unlock_bh(&sc->sc_pcu_lock);
+- ath9k_ps_restore(sc);
-}
-
- /*
- * Assign a descriptor (and sequence number if necessary,
- * and map buffer for DMA. Frees skb on error
-@@ -1753,13 +1776,10 @@ static struct ath_buf *ath_tx_setup_buff
- struct ath_atx_tid *tid,
- struct sk_buff *skb)
+ static int ath_reset(struct ath_softc *sc, bool retry_tx)
{
-- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_frame_info *fi = get_frame_info(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ath_buf *bf;
-- struct ath_desc *ds;
-- int frm_type;
- u16 seqno;
-
- bf = ath_tx_get_buffer(sc);
-@@ -1777,7 +1797,6 @@ static struct ath_buf *ath_tx_setup_buff
- bf->bf_state.seqno = seqno;
+ int r;
+@@ -1093,6 +1018,9 @@ static int ath9k_start(struct ieee80211_
+ * and then setup of the interrupt mask.
+ */
+ spin_lock_bh(&sc->sc_pcu_lock);
++
++ atomic_set(&ah->intr_ref_cnt, -1);
++
+ r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
+ if (r) {
+ ath_err(common,
+@@ -1131,6 +1059,18 @@ static int ath9k_start(struct ieee80211_
+ goto mutex_unlock;
+ }
+
++ if (ah->led_pin >= 0) {
++ ath9k_hw_cfg_output(ah, ah->led_pin,
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++ ath9k_hw_set_gpio(ah, ah->led_pin, 0);
++ }
++
++ /*
++ * Reset key cache to sane defaults (all entries cleared) instead of
++ * semi-random values after suspend/resume.
++ */
++ ath9k_cmn_init_crypto(sc->sc_ah);
++
+ spin_unlock_bh(&sc->sc_pcu_lock);
+
+ if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
+@@ -1176,6 +1116,13 @@ static void ath9k_tx(struct ieee80211_hw
+ }
}
-- bf->bf_flags = setup_tx_flags(skb);
- bf->bf_mpdu = skb;
++ /*
++ * Cannot tx while the hardware is in full sleep, it first needs a full
++ * chip reset to recover from that
++ */
++ if (unlikely(sc->sc_ah->power_mode == ATH9K_PM_FULL_SLEEP))
++ goto exit;
++
+ if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) {
+ /*
+ * We are using PS-Poll and mac80211 can request TX while in
+@@ -1222,6 +1169,7 @@ static void ath9k_stop(struct ieee80211_
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
++ bool prev_idle;
+
+ mutex_lock(&sc->mutex);
+
+@@ -1252,35 +1200,45 @@ static void ath9k_stop(struct ieee80211_
+ * before setting the invalid flag. */
+ ath9k_hw_disable_interrupts(ah);
+
+- if (!(sc->sc_flags & SC_OP_INVALID)) {
+- ath_drain_all_txq(sc, false);
+- ath_stoprecv(sc);
+- ath9k_hw_phy_disable(ah);
+- } else
+- sc->rx.rxlink = NULL;
++ spin_unlock_bh(&sc->sc_pcu_lock);
++
++ /* we can now sync irq and kill any running tasklets, since we already
++ * disabled interrupts and not holding a spin lock */
++ synchronize_irq(sc->irq);
++ tasklet_kill(&sc->intr_tq);
++ tasklet_kill(&sc->bcon_tasklet);
++
++ prev_idle = sc->ps_idle;
++ sc->ps_idle = true;
++
++ spin_lock_bh(&sc->sc_pcu_lock);
++
++ if (ah->led_pin >= 0) {
++ ath9k_hw_set_gpio(ah, ah->led_pin, 1);
++ ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
++ }
++
++ ath_prepare_reset(sc, false, true);
- bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
-@@ -1791,22 +1810,6 @@ static struct ath_buf *ath_tx_setup_buff
- goto error;
+ if (sc->rx.frag) {
+ dev_kfree_skb_any(sc->rx.frag);
+ sc->rx.frag = NULL;
}
-- frm_type = get_hw_packet_type(skb);
--
-- ds = bf->bf_desc;
-- ath9k_hw_set_desc_link(ah, ds, 0);
--
-- ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER,
-- fi->keyix, fi->keytype, bf->bf_flags);
--
-- ath9k_hw_filltxdesc(ah, ds,
-- skb->len, /* segment length */
-- true, /* first segment */
-- true, /* last segment */
-- ds, /* first descriptor */
-- bf->bf_buf_addr,
-- txq->axq_qnum);
--
- fi->bf = bf;
+- /* disable HAL and put h/w to sleep */
+- ath9k_hw_disable(ah);
++ if (!ah->curchan)
++ ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
- return bf;
-@@ -1849,16 +1852,9 @@ static void ath_tx_start_dma(struct ath_
+- spin_unlock_bh(&sc->sc_pcu_lock);
++ ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
++ ath9k_hw_phy_disable(ah);
- bf->bf_state.bfs_paprd = txctl->paprd;
+- /* we can now sync irq and kill any running tasklets, since we already
+- * disabled interrupts and not holding a spin lock */
+- synchronize_irq(sc->irq);
+- tasklet_kill(&sc->intr_tq);
+- tasklet_kill(&sc->bcon_tasklet);
++ ath9k_hw_configpcipowersave(ah, true);
-- if (bf->bf_state.bfs_paprd)
-- ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
-- bf->bf_state.bfs_paprd);
--
- if (txctl->paprd)
- bf->bf_state.bfs_paprd_timestamp = jiffies;
+- ath9k_ps_restore(sc);
++ spin_unlock_bh(&sc->sc_pcu_lock);
+
+- sc->ps_idle = true;
+- ath_radio_disable(sc, hw);
++ ath9k_ps_restore(sc);
+
+ sc->sc_flags |= SC_OP_INVALID;
++ sc->ps_idle = prev_idle;
+
+ mutex_unlock(&sc->mutex);
+
+@@ -1620,8 +1578,8 @@ static int ath9k_config(struct ieee80211
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_conf *conf = &hw->conf;
+- bool disable_radio = false;
+
++ ath9k_ps_wakeup(sc);
+ mutex_lock(&sc->mutex);
-- if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
-- ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
+ /*
+@@ -1632,13 +1590,8 @@ static int ath9k_config(struct ieee80211
+ */
+ if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+ sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
+- if (!sc->ps_idle) {
+- ath_radio_enable(sc, hw);
+- ath_dbg(common, ATH_DBG_CONFIG,
+- "not-idle: enabling radio\n");
+- } else {
+- disable_radio = true;
+- }
++ if (sc->ps_idle)
++ ath_cancel_work(sc);
+ }
+
+ /*
+@@ -1745,18 +1698,12 @@ static int ath9k_config(struct ieee80211
+ ath_dbg(common, ATH_DBG_CONFIG,
+ "Set power: %d\n", conf->power_level);
+ sc->config.txpowlimit = 2 * conf->power_level;
+- ath9k_ps_wakeup(sc);
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->config.txpowlimit, &sc->curtxpow);
+- ath9k_ps_restore(sc);
+- }
-
- ath_tx_send_normal(sc, txctl->txq, tid, skb);
+- if (disable_radio) {
+- ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
+- ath_radio_disable(sc, hw);
}
-@@ -1899,15 +1895,18 @@ int ath_tx_start(struct ieee80211_hw *hw
- hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
+ mutex_unlock(&sc->mutex);
++ ath9k_ps_restore(sc);
+
+ return 0;
+ }
+@@ -2324,9 +2271,6 @@ static void ath9k_flush(struct ieee80211
+ return;
}
-- /* Add the padding after the header if this is not already done */
-- padpos = ath9k_cmn_padpos(hdr->frame_control);
-- padsize = padpos & 3;
-- if (padsize && skb->len > padpos) {
-- if (skb_headroom(skb) < padsize)
-- return -ENOMEM;
+- if (drop)
+- timeout = 1;
-
-- skb_push(skb, padsize);
-- memmove(skb->data, skb->data + padsize, padpos);
-+ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
-+ /* Add the padding after the header if this is not already done */
-+ padpos = ath9k_cmn_padpos(hdr->frame_control);
-+ padsize = padpos & 3;
-+ if (padsize && skb->len > padpos) {
-+ if (skb_headroom(skb) < padsize)
-+ return -ENOMEM;
-+
-+ skb_push(skb, padsize);
-+ memmove(skb->data, skb->data + padsize, padpos);
-+ hdr = (struct ieee80211_hdr *) skb->data;
-+ }
+ for (j = 0; j < timeout; j++) {
+ bool npend = false;
+
+@@ -2344,21 +2288,22 @@ static void ath9k_flush(struct ieee80211
+ }
+
+ if (!npend)
+- goto out;
++ break;
}
- if ((vif && vif->type != NL80211_IFTYPE_AP &&
-@@ -1953,20 +1952,21 @@ static void ath_tx_complete(struct ath_s
- if (tx_flags & ATH_TX_BAR)
- tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+- ath9k_ps_wakeup(sc);
+- spin_lock_bh(&sc->sc_pcu_lock);
+- drain_txq = ath_drain_all_txq(sc, false);
+- spin_unlock_bh(&sc->sc_pcu_lock);
++ if (drop) {
++ ath9k_ps_wakeup(sc);
++ spin_lock_bh(&sc->sc_pcu_lock);
++ drain_txq = ath_drain_all_txq(sc, false);
++ spin_unlock_bh(&sc->sc_pcu_lock);
+
+- if (!drain_txq)
+- ath_reset(sc, false);
++ if (!drain_txq)
++ ath_reset(sc, false);
+
+- ath9k_ps_restore(sc);
+- ieee80211_wake_queues(hw);
++ ath9k_ps_restore(sc);
++ ieee80211_wake_queues(hw);
++ }
-- if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
-+ if (!(tx_flags & ATH_TX_ERROR))
- /* Frame was ACKed */
- tx_info->flags |= IEEE80211_TX_STAT_ACK;
-- }
+-out:
+ ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
+ mutex_unlock(&sc->mutex);
+ }
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -307,12 +307,11 @@ static int ath_pci_suspend(struct device
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct ath_softc *sc = hw->priv;
-- padpos = ath9k_cmn_padpos(hdr->frame_control);
-- padsize = padpos & 3;
-- if (padsize && skb->len>padpos+padsize) {
-- /*
-- * Remove MAC header padding before giving the frame back to
-- * mac80211.
-- */
-- memmove(skb->data + padsize, skb->data, padpos);
-- skb_pull(skb, padsize);
-+ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
-+ padpos = ath9k_cmn_padpos(hdr->frame_control);
-+ padsize = padpos & 3;
-+ if (padsize && skb->len>padpos+padsize) {
-+ /*
-+ * Remove MAC header padding before giving the frame back to
-+ * mac80211.
-+ */
-+ memmove(skb->data + padsize, skb->data, padpos);
-+ skb_pull(skb, padsize);
-+ }
+- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+-
+ /* The device has to be moved to FULLSLEEP forcibly.
+ * Otherwise the chip never moved to full sleep,
+ * when no interface is up.
+ */
++ ath9k_hw_disable(sc->sc_ah);
+ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
+
+ return 0;
+@@ -334,22 +333,6 @@ static int ath_pci_resume(struct device
+ if ((val & 0x0000ff00) != 0)
+ pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+- ath9k_ps_wakeup(sc);
+- /* Enable LED */
+- ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
+- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
+-
+- /*
+- * Reset key cache to sane defaults (all entries cleared) instead of
+- * semi-random values after suspend/resume.
+- */
+- ath9k_cmn_init_crypto(sc->sc_ah);
+- ath9k_ps_restore(sc);
+-
+- sc->ps_idle = true;
+- ath_radio_disable(sc, hw);
+-
+ return 0;
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -179,6 +179,11 @@ static void ath_tx_flush_tid(struct ath_
+ spin_lock_bh(&txq->axq_lock);
}
- if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
-@@ -2000,18 +2000,18 @@ static void ath_tx_complete_buf(struct a
- struct ath_tx_status *ts, int txok, int sendbar)
- {
- struct sk_buff *skb = bf->bf_mpdu;
-+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- unsigned long flags;
- int tx_flags = 0;
++ if (tid->baw_head == tid->baw_tail) {
++ tid->state &= ~AGGR_ADDBA_COMPLETE;
++ tid->state &= ~AGGR_CLEANUP;
++ }
++
+ spin_unlock_bh(&txq->axq_lock);
+ }
- if (sendbar)
- tx_flags = ATH_TX_BAR;
+@@ -556,15 +561,9 @@ static void ath_tx_complete_aggr(struct
+ spin_unlock_bh(&txq->axq_lock);
+ }
-- if (!txok) {
-+ if (!txok)
- tx_flags |= ATH_TX_ERROR;
+- if (tid->state & AGGR_CLEANUP) {
++ if (tid->state & AGGR_CLEANUP)
+ ath_tx_flush_tid(sc, tid);
-- if (bf_isxretried(bf))
-- tx_flags |= ATH_TX_XRETRY;
+- if (tid->baw_head == tid->baw_tail) {
+- tid->state &= ~AGGR_ADDBA_COMPLETE;
+- tid->state &= ~AGGR_CLEANUP;
+- }
- }
-+ if (ts->ts_status & ATH9K_TXERR_FILT)
-+ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
-
- dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE);
- bf->bf_buf_addr = 0;
-@@ -2024,7 +2024,7 @@ static void ath_tx_complete_buf(struct a
- else
- complete(&sc->paprd_complete);
- } else {
-- ath_debug_stat_tx(sc, bf, ts, txq);
-+ ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
- ath_tx_complete(sc, skb, tx_flags, txq);
- }
- /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
-@@ -2042,7 +2042,7 @@ static void ath_tx_complete_buf(struct a
+-
+ rcu_read_unlock();
- static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_tx_status *ts, int nframes, int nbad,
-- int txok, bool update_rc)
-+ int txok)
- {
- struct sk_buff *skb = bf->bf_mpdu;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-@@ -2057,9 +2057,7 @@ static void ath_tx_rc_status(struct ath_
- tx_rateindex = ts->ts_rateindex;
- WARN_ON(tx_rateindex >= hw->max_rates);
-
-- if (ts->ts_status & ATH9K_TXERR_FILT)
-- tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
-- if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) {
-+ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
- tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
-
- BUG_ON(nbad > nframes);
-@@ -2069,7 +2067,7 @@ static void ath_tx_rc_status(struct ath_
+ if (needreset) {
+@@ -1955,7 +1954,7 @@ static void ath_tx_complete(struct ath_s
+ skb_pull(skb, padsize);
}
- if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
-- (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) {
-+ (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
- /*
- * If an underrun error is seen assume it as an excessive
- * retry only if max frame trigger level has been reached
-@@ -2082,9 +2080,9 @@ static void ath_tx_rc_status(struct ath_
- * successfully by eventually preferring slower rates.
- * This itself should also alleviate congestion on the bus.
- */
-- if (ieee80211_is_data(hdr->frame_control) &&
-- (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
-- ATH9K_TX_DELIM_UNDERRUN)) &&
-+ if (unlikely(ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN |
-+ ATH9K_TX_DELIM_UNDERRUN)) &&
-+ ieee80211_is_data(hdr->frame_control) &&
- ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level)
- tx_info->status.rates[tx_rateindex].count =
- hw->max_rate_tries;
-@@ -2115,13 +2113,7 @@ static void ath_tx_process_buffer(struct
- spin_unlock_bh(&txq->axq_lock);
+- if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
++ if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) {
+ sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
+ ath_dbg(common, ATH_DBG_PS,
+ "Going back to sleep after having received TX status (0x%lx)\n",
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -1130,6 +1130,7 @@ struct cfg80211_ibss_params {
+ u8 *ssid;
+ u8 *bssid;
+ struct ieee80211_channel *channel;
++ enum nl80211_channel_type channel_type;
+ u8 *ie;
+ u8 ssid_len, ie_len;
+ u16 beacon_interval;
+@@ -3292,6 +3293,16 @@ void cfg80211_report_obss_beacon(struct
+ const u8 *frame, size_t len,
+ int freq, gfp_t gfp);
+
++/**
++ * cfg80211_can_use_ext_chan - test if ht40 on extension channel can be used
++ * @wiphy: the wiphy
++ * @chan: main channel
++ * @channel_type: HT mode
++ */
++bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
++ struct ieee80211_channel *chan,
++ enum nl80211_channel_type channel_type);
++
+ /* Logging, debugging and troubleshooting/diagnostic helpers. */
- if (!bf_isampdu(bf)) {
-- /*
-- * This frame is sent out as a single frame.
-- * Use hardware retry status for this frame.
-- */
-- if (ts->ts_status & ATH9K_TXERR_XRETRY)
-- bf->bf_state.bf_type |= BUF_XRETRY;
-- ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok, true);
-+ ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
- ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
- } else
- ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
+ /* wiphy_printk helpers, similar to dev_printk */
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
-@@ -180,6 +180,8 @@ static void ieee80211_send_addba_resp(st
+@@ -182,6 +182,10 @@ static void ieee80211_send_addba_resp(st
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+ else if (sdata->vif.type == NL80211_IFTYPE_WDS)
+ memcpy(mgmt->bssid, da, ETH_ALEN);
++ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
++ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_ACTION);
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
-@@ -77,7 +77,8 @@ static void ieee80211_send_addba_request
- memcpy(mgmt->da, da, ETH_ALEN);
+@@ -79,10 +79,13 @@ static void ieee80211_send_addba_request
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
if (sdata->vif.type == NL80211_IFTYPE_AP ||
-- sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+- sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
++ sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
+ sdata->vif.type == NL80211_IFTYPE_WDS)
memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
else if (sdata->vif.type == NL80211_IFTYPE_STATION)
memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-@@ -397,7 +398,8 @@ int ieee80211_start_tx_ba_session(struct
- */
++ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
++ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
+
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION);
+@@ -394,7 +397,9 @@ int ieee80211_start_tx_ba_session(struct
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
- sdata->vif.type != NL80211_IFTYPE_AP)
+ sdata->vif.type != NL80211_IFTYPE_AP &&
++ sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+ sdata->vif.type != NL80211_IFTYPE_WDS)
return -EINVAL;
- if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
+ if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
-@@ -59,7 +59,7 @@ static ssize_t sta_flags_read(struct fil
- char buf[100];
- struct sta_info *sta = file->private_data;
- u32 staflags = get_sta_flags(sta);
-- int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
-+ int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s",
- staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
- staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
- staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "",
-@@ -67,7 +67,6 @@ static ssize_t sta_flags_read(struct fil
- staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
- staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
- staflags & WLAN_STA_WME ? "WME\n" : "",
-- staflags & WLAN_STA_WDS ? "WDS\n" : "",
- staflags & WLAN_STA_MFP ? "MFP\n" : "");
- return simple_read_from_buffer(userbuf, count, ppos, buf, res);
- }
+@@ -63,11 +63,11 @@ static ssize_t sta_flags_read(struct fil
+ test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
+
+ int res = scnprintf(buf, sizeof(buf),
+- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
++ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
+ TEST(PS_DRIVER), TEST(AUTHORIZED),
+ TEST(SHORT_PREAMBLE), TEST(ASSOC_AP),
+- TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
++ TEST(WME), TEST(CLEAR_PS_FILT),
+ TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
+ TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
+ TEST(TDLS_PEER_AUTH));
+--- a/net/mac80211/ht.c
++++ b/net/mac80211/ht.c
+@@ -201,6 +201,8 @@ void ieee80211_send_delba(struct ieee802
+ memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+ else if (sdata->vif.type == NL80211_IFTYPE_STATION)
+ memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
++ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
++ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
+
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION);
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -77,6 +77,7 @@ static void __ieee80211_sta_join_ibss(st
+ struct cfg80211_bss *bss;
+ u32 bss_change;
+ u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
++ enum nl80211_channel_type channel_type;
+
+ lockdep_assert_held(&ifibss->mtx);
+
+@@ -105,8 +106,16 @@ static void __ieee80211_sta_join_ibss(st
+
+ sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+
+- local->oper_channel = chan;
+- WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
++ channel_type = ifibss->channel_type;
++ if (channel_type > NL80211_CHAN_HT20 &&
++ !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
++ channel_type = NL80211_CHAN_HT20;
++ if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
++ /* can only fail due to HT40+/- mismatch */
++ channel_type = NL80211_CHAN_HT20;
++ WARN_ON(!ieee80211_set_channel_type(local, sdata,
++ NL80211_CHAN_HT20));
++ }
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+ sband = local->hw.wiphy->bands[chan->band];
+@@ -172,6 +181,18 @@ static void __ieee80211_sta_join_ibss(st
+ memcpy(skb_put(skb, ifibss->ie_len),
+ ifibss->ie, ifibss->ie_len);
+
++ /* add HT capability and information IEs */
++ if (channel_type && sband->ht_cap.ht_supported) {
++ pos = skb_put(skb, 4 +
++ sizeof(struct ieee80211_ht_cap) +
++ sizeof(struct ieee80211_ht_info));
++ pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
++ pos = ieee80211_ie_build_ht_info(pos,
++ &sband->ht_cap,
++ chan,
++ channel_type);
++ }
++
+ if (local->hw.queues >= 4) {
+ pos = skb_put(skb, 9);
+ *pos++ = WLAN_EID_VENDOR_SPECIFIC;
+@@ -195,6 +216,7 @@ static void __ieee80211_sta_join_ibss(st
+ bss_change |= BSS_CHANGED_BEACON;
+ bss_change |= BSS_CHANGED_BEACON_ENABLED;
+ bss_change |= BSS_CHANGED_BASIC_RATES;
++ bss_change |= BSS_CHANGED_HT;
+ bss_change |= BSS_CHANGED_IBSS;
+ sdata->vif.bss_conf.ibss_joined = true;
+ ieee80211_bss_info_change_notify(sdata, bss_change);
+@@ -268,6 +290,7 @@ static void ieee80211_rx_bss_info(struct
+ u64 beacon_timestamp, rx_timestamp;
+ u32 supp_rates = 0;
+ enum ieee80211_band band = rx_status->band;
++ struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
+
+ if (elems->ds_params && elems->ds_params_len == 1)
+ freq = ieee80211_channel_to_frequency(elems->ds_params[0],
+@@ -277,7 +300,10 @@ static void ieee80211_rx_bss_info(struct
+
+ channel = ieee80211_get_channel(local->hw.wiphy, freq);
+
+- if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
++ if (!channel ||
++ channel->flags & (IEEE80211_CHAN_DISABLED ||
++ IEEE80211_CHAN_NO_IBSS ||
++ IEEE80211_CHAN_RADAR))
+ return;
+
+ if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
+@@ -315,8 +341,41 @@ static void ieee80211_rx_bss_info(struct
+ GFP_ATOMIC);
+ }
+
+- if (sta && elems->wmm_info)
+- set_sta_flag(sta, WLAN_STA_WME);
++ if (sta) {
++ if (elems->wmm_info)
++ set_sta_flag(sta, WLAN_STA_WME);
++
++ /* we both use HT */
++ if (elems->ht_info_elem && elems->ht_cap_elem &&
++ sdata->u.ibss.channel_type) {
++ enum nl80211_channel_type channel_type =
++ ieee80211_ht_info_to_channel_type(
++ elems->ht_info_elem);
++ struct ieee80211_sta_ht_cap sta_ht_cap_new;
++
++ /*
++ * fall back to HT20 if we don't use or use
++ * the other extension channel
++ */
++ if (channel_type > NL80211_CHAN_HT20 &&
++ channel_type != sdata->u.ibss.channel_type)
++ channel_type = NL80211_CHAN_HT20;
++
++ ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
++ elems->ht_cap_elem,
++ &sta_ht_cap_new);
++ if (memcmp(&sta->sta.ht_cap, &sta_ht_cap_new,
++ sizeof(sta_ht_cap_new))) {
++ memcpy(&sta->sta.ht_cap,
++ &sta_ht_cap_new,
++ sizeof(sta_ht_cap_new));
++ rate_control_rate_update(local, sband,
++ sta,
++ IEEE80211_RC_HT_CHANGED,
++ channel_type);
++ }
++ }
++ }
+
+ rcu_read_unlock();
+ }
+@@ -898,10 +957,15 @@ int ieee80211_ibss_join(struct ieee80211
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
+- 36 /* bitrates */ +
+- 34 /* SSID */ +
+- 3 /* DS params */ +
+- 4 /* IBSS params */ +
++ sizeof(struct ieee80211_hdr_3addr) +
++ 12 /* struct ieee80211_mgmt.u.beacon */ +
++ 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
++ 2 + 8 /* max Supported Rates */ +
++ 3 /* max DS params */ +
++ 4 /* IBSS params */ +
++ 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
++ 2 + sizeof(struct ieee80211_ht_cap) +
++ 2 + sizeof(struct ieee80211_ht_info) +
+ params->ie_len);
+ if (!skb)
+ return -ENOMEM;
+@@ -922,13 +986,15 @@ int ieee80211_ibss_join(struct ieee80211
+ sdata->vif.bss_conf.beacon_int = params->beacon_interval;
+
+ sdata->u.ibss.channel = params->channel;
++ sdata->u.ibss.channel_type = params->channel_type;
+ sdata->u.ibss.fixed_channel = params->channel_fixed;
+
+ /* fix ourselves to that channel now already */
+ if (params->channel_fixed) {
+ sdata->local->oper_channel = params->channel;
+- WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
+- NL80211_CHAN_NO_HT));
++ if (!ieee80211_set_channel_type(sdata->local, sdata,
++ params->channel_type))
++ return -EINVAL;
+ }
+
+ if (params->ie) {
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -470,6 +470,7 @@ struct ieee80211_if_ibss {
+ u8 ssid_len, ie_len;
+ u8 *ie;
+ struct ieee80211_channel *channel;
++ enum nl80211_channel_type channel_type;
+
+ unsigned long ibss_join_req;
+ /* probe response/beacon for IBSS */
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_
u32 changed = 0;
int res;
u32 hw_reconf_flags = 0;
-@@ -290,27 +289,6 @@ static int ieee80211_do_open(struct net_
+@@ -309,27 +308,6 @@ static int ieee80211_do_open(struct net_
set_bit(SDATA_STATE_RUNNING, &sdata->state);
- goto err_del_interface;
- }
-
-- /* no locking required since STA is not live yet */
-- sta->flags |= WLAN_STA_AUTHORIZED;
+- /* no atomic bitop required since STA is not live yet */
+- set_sta_flag(sta, WLAN_STA_AUTHORIZED);
-
- res = sta_info_insert(sta);
- if (res) {
/*
* set_multicast_list will be invoked by the networking core
* which will check whether any increments here were done in
-@@ -344,8 +322,7 @@ static int ieee80211_do_open(struct net_
+@@ -356,8 +334,7 @@ static int ieee80211_do_open(struct net_
netif_tx_start_all_queues(dev);
return 0;
- err_del_interface:
-- drv_remove_interface(local, &sdata->vif);
+- drv_remove_interface(local, sdata);
+
err_stop:
if (!local->open_count)
drv_stop(local);
-@@ -718,6 +695,70 @@ static void ieee80211_if_setup(struct ne
+@@ -732,6 +709,70 @@ static void ieee80211_if_setup(struct ne
dev->destructor = free_netdev;
}
+ elems.ht_cap_elem, &sta->sta.ht_cap);
+
+ if (elems.wmm_param)
-+ set_sta_flags(sta, WLAN_STA_WME);
++ set_sta_flag(sta, WLAN_STA_WME);
+
+ if (new) {
-+ sta->flags = WLAN_STA_AUTHORIZED;
++ set_sta_flag(sta, WLAN_STA_AUTHORIZED);
+ rate_control_rate_init(sta);
+ sta_info_insert_rcu(sta);
+ }
static void ieee80211_iface_work(struct work_struct *work)
{
struct ieee80211_sub_if_data *sdata =
-@@ -822,6 +863,9 @@ static void ieee80211_iface_work(struct
+@@ -836,6 +877,9 @@ static void ieee80211_iface_work(struct
break;
ieee80211_mesh_rx_queued_mgmt(sdata, skb);
break;
default:
WARN(1, "frame for unexpected interface type");
break;
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1359,9 +1359,6 @@ static void __ieee80211_connection_loss(
+ ieee80211_set_disassoc(sdata, true, true);
+ mutex_unlock(&ifmgd->mtx);
+
+- mutex_lock(&local->mtx);
+- ieee80211_recalc_idle(local);
+- mutex_unlock(&local->mtx);
+ /*
+ * must be outside lock due to cfg80211,
+ * but that's not a problem.
+@@ -1370,6 +1367,10 @@ static void __ieee80211_connection_loss(
+ IEEE80211_STYPE_DEAUTH,
+ WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
+ NULL, true);
++
++ mutex_lock(&local->mtx);
++ ieee80211_recalc_idle(local);
++ mutex_unlock(&local->mtx);
+ }
+
+ void ieee80211_beacon_connection_loss_work(struct work_struct *work)
+@@ -2136,9 +2137,6 @@ static void ieee80211_sta_connection_los
+
+ ieee80211_set_disassoc(sdata, true, true);
+ mutex_unlock(&ifmgd->mtx);
+- mutex_lock(&local->mtx);
+- ieee80211_recalc_idle(local);
+- mutex_unlock(&local->mtx);
+ /*
+ * must be outside lock due to cfg80211,
+ * but that's not a problem.
+@@ -2146,6 +2144,11 @@ static void ieee80211_sta_connection_los
+ ieee80211_send_deauth_disassoc(sdata, bssid,
+ IEEE80211_STYPE_DEAUTH, reason,
+ NULL, true);
++
++ mutex_lock(&local->mtx);
++ ieee80211_recalc_idle(local);
++ mutex_unlock(&local->mtx);
++
+ mutex_lock(&ifmgd->mtx);
+ }
+
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -212,8 +212,6 @@ static void ieee80211_hw_roc_start(struc
+ return;
+ }
+
+- ieee80211_recalc_idle(local);
+-
+ if (local->hw_roc_skb) {
+ sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev);
+ ieee80211_tx_skb(sdata, local->hw_roc_skb);
+@@ -227,6 +225,8 @@ static void ieee80211_hw_roc_start(struc
+ GFP_KERNEL);
+ }
+
++ ieee80211_recalc_idle(local);
++
+ mutex_unlock(&local->mtx);
+ }
+
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
-@@ -2163,7 +2163,8 @@ ieee80211_rx_h_action(struct ieee80211_r
- */
+@@ -2250,7 +2250,9 @@ ieee80211_rx_h_action(struct ieee80211_r
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
- sdata->vif.type != NL80211_IFTYPE_AP)
+ sdata->vif.type != NL80211_IFTYPE_AP &&
++ sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+ sdata->vif.type != NL80211_IFTYPE_WDS)
break;
/* verify action_code is present */
-@@ -2378,13 +2379,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+@@ -2465,13 +2467,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
if (!ieee80211_vif_is_mesh(&sdata->vif) &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
break;
case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
-@@ -2727,10 +2729,16 @@ static int prepare_for_handlers(struct i
+@@ -2818,10 +2821,16 @@ static int prepare_for_handlers(struct i
}
break;
case NL80211_IFTYPE_WDS:
/* should never get here */
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
-@@ -31,7 +31,6 @@
+@@ -32,7 +32,6 @@
* frames.
* @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
* @WLAN_STA_WME: Station is a QoS-STA.
* @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
* IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
* frame to this station is transmitted.
-@@ -54,7 +53,6 @@ enum ieee80211_sta_info_flags {
- WLAN_STA_SHORT_PREAMBLE = 1<<4,
- WLAN_STA_ASSOC_AP = 1<<5,
- WLAN_STA_WME = 1<<6,
-- WLAN_STA_WDS = 1<<7,
- WLAN_STA_CLEAR_PS_FILT = 1<<9,
- WLAN_STA_MFP = 1<<10,
- WLAN_STA_BLOCK_BA = 1<<11,
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -278,17 +278,19 @@ void ieee80211_tx_status(struct ieee8021
- }
-
- if (!acked && ieee80211_is_back_req(fc)) {
-+ u16 control;
-+
- /*
-- * BAR failed, let's tear down the BA session as a
-- * last resort as some STAs (Intel 5100 on Windows)
-- * can get stuck when the BA window isn't flushed
-- * correctly.
-+ * BAR failed, store the last SSN and retry sending
-+ * the BAR when the next unicast transmission on the
-+ * same TID succeeds.
- */
- bar = (struct ieee80211_bar *) skb->data;
-- if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
-+ control = le16_to_cpu(bar->control);
-+ if (!(control & IEEE80211_BAR_CTRL_MULTI_TID)) {
- u16 ssn = le16_to_cpu(bar->start_seq_num);
-
-- tid = (bar->control &
-+ tid = (control &
- IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
- IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
-
---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-@@ -704,8 +704,10 @@ static void ar5008_hw_override_ini(struc
- REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
- }
-
-- if (!AR_SREV_5416_20_OR_LATER(ah) ||
-- AR_SREV_9280_20_OR_LATER(ah))
-+ REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
-+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
-+
-+ if (AR_SREV_9280_20_OR_LATER(ah))
- return;
- /*
- * Disable BB clock gating
-@@ -802,7 +804,8 @@ static int ar5008_hw_process_ini(struct
-
- /* Write ADDAC shifts */
- REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
-- ah->eep_ops->set_addac(ah, chan);
-+ if (ah->eep_ops->set_addac)
-+ ah->eep_ops->set_addac(ah, chan);
-
- if (AR_SREV_5416_22_OR_LATER(ah)) {
- REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
-@@ -1007,24 +1010,6 @@ static void ar5008_restore_chainmask(str
- }
- }
-
--static void ar5008_set_diversity(struct ath_hw *ah, bool value)
--{
-- u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
-- if (value)
-- v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-- else
-- v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-- REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
--}
--
--static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah,
-- struct ath9k_channel *chan)
--{
-- if (chan && IS_CHAN_5GHZ(chan))
-- return 0x1450;
-- return 0x1458;
--}
--
- static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah,
- struct ath9k_channel *chan)
- {
-@@ -1654,7 +1639,6 @@ void ar5008_hw_attach_phy_ops(struct ath
- priv_ops->rfbus_req = ar5008_hw_rfbus_req;
- priv_ops->rfbus_done = ar5008_hw_rfbus_done;
- priv_ops->restore_chainmask = ar5008_restore_chainmask;
-- priv_ops->set_diversity = ar5008_set_diversity;
- priv_ops->do_getnf = ar5008_hw_do_getnf;
- priv_ops->set_radar_params = ar5008_hw_set_radar_params;
-
-@@ -1664,9 +1648,7 @@ void ar5008_hw_attach_phy_ops(struct ath
- } else
- priv_ops->ani_control = ar5008_hw_ani_control_old;
-
-- if (AR_SREV_9100(ah))
-- priv_ops->compute_pll_control = ar9100_hw_compute_pll_control;
-- else if (AR_SREV_9160_10_OR_LATER(ah))
-+ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
- priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
- else
- priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -592,6 +592,9 @@ static void ar9003_hw_override_ini(struc
- val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
- REG_WRITE(ah, AR_PCU_MISC_MODE2,
- val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
-+
-+ REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
-+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
- }
-
- static void ar9003_hw_prog_ini(struct ath_hw *ah,
-@@ -785,16 +788,6 @@ static void ar9003_hw_rfbus_done(struct
- REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
- }
-
--static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
--{
-- u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
-- if (value)
-- v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-- else
-- v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
-- REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
--}
--
- static bool ar9003_hw_ani_control(struct ath_hw *ah,
- enum ath9k_ani_cmd cmd, int param)
+@@ -62,7 +61,6 @@ enum ieee80211_sta_info_flags {
+ WLAN_STA_SHORT_PREAMBLE,
+ WLAN_STA_ASSOC_AP,
+ WLAN_STA_WME,
+- WLAN_STA_WDS,
+ WLAN_STA_CLEAR_PS_FILT,
+ WLAN_STA_MFP,
+ WLAN_STA_BLOCK_BA,
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -44,9 +44,9 @@ rdev_freq_to_chan(struct cfg80211_regist
+ return chan;
+ }
+
+-static bool can_beacon_sec_chan(struct wiphy *wiphy,
+- struct ieee80211_channel *chan,
+- enum nl80211_channel_type channel_type)
++bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
++ struct ieee80211_channel *chan,
++ enum nl80211_channel_type channel_type)
{
-@@ -1277,7 +1270,6 @@ void ar9003_hw_attach_phy_ops(struct ath
- priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
- priv_ops->rfbus_req = ar9003_hw_rfbus_req;
- priv_ops->rfbus_done = ar9003_hw_rfbus_done;
-- priv_ops->set_diversity = ar9003_hw_set_diversity;
- priv_ops->ani_control = ar9003_hw_ani_control;
- priv_ops->do_getnf = ar9003_hw_do_getnf;
- priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
---- a/drivers/net/wireless/ath/ath9k/eeprom.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
-@@ -456,12 +456,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs
- pPdGainBoundaries[i] =
- min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
-
-- if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
-- minDelta = pPdGainBoundaries[0] - 23;
-- pPdGainBoundaries[0] = 23;
-- } else {
-- minDelta = 0;
-- }
-+ minDelta = 0;
-
- if (i == 0) {
- if (AR_SREV_9280_20_OR_LATER(ah))
---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-@@ -405,12 +405,7 @@ static void ath9k_hw_set_4k_power_cal_ta
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
-
- for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
-- if (AR_SREV_5416_20_OR_LATER(ah) &&
-- (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
-- (i != 0)) {
-- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
-- } else
-- regChainOffset = i * 0x1000;
-+ regChainOffset = i * 0x1000;
-
- if (pEepData->baseEepHeader.txMask & (1 << i)) {
- pRawDataset = pEepData->calPierData2G[i];
-@@ -423,19 +418,17 @@ static void ath9k_hw_set_4k_power_cal_ta
-
- ENABLE_REGWRITE_BUFFER(ah);
-
-- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
-- REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
-- SM(pdGainOverlap_t2,
-- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
-- | SM(gainBoundaries[0],
-- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
-- | SM(gainBoundaries[1],
-- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
-- | SM(gainBoundaries[2],
-- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
-- | SM(gainBoundaries[3],
-- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
-- }
-+ REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
-+ SM(pdGainOverlap_t2,
-+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
-+ | SM(gainBoundaries[0],
-+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
-+ | SM(gainBoundaries[1],
-+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
-+ | SM(gainBoundaries[2],
-+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
-+ | SM(gainBoundaries[3],
-+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
-
- regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
- for (j = 0; j < 32; j++) {
-@@ -715,10 +708,8 @@ static void ath9k_hw_4k_set_txpower(stru
- if (test)
- return;
-
-- if (AR_SREV_9280_20_OR_LATER(ah)) {
-- for (i = 0; i < Ar5416RateSize; i++)
-- ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
-- }
-+ for (i = 0; i < Ar5416RateSize; i++)
-+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
+ struct ieee80211_channel *sec_chan;
+ int diff;
+@@ -75,6 +75,7 @@ static bool can_beacon_sec_chan(struct w
- ENABLE_REGWRITE_BUFFER(ah);
-
-@@ -788,28 +779,6 @@ static void ath9k_hw_4k_set_txpower(stru
- REGWRITE_BUFFER_FLUSH(ah);
+ return true;
}
-
--static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
-- struct ath9k_channel *chan)
--{
-- struct modal_eep_4k_header *pModal;
-- struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
-- u8 biaslevel;
--
-- if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
-- return;
--
-- if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
-- return;
--
-- pModal = &eep->modalHeader;
--
-- if (pModal->xpaBiasLvl != 0xff) {
-- biaslevel = pModal->xpaBiasLvl;
-- INI_RA(&ah->iniAddac, 7, 1) =
-- (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
-- }
--}
--
- static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
- struct modal_eep_4k_header *pModal,
- struct ar5416_eeprom_4k *eep,
-@@ -877,6 +846,7 @@ static void ath9k_hw_4k_set_board_values
- u8 txRxAttenLocal;
- u8 ob[5], db1[5], db2[5];
- u8 ant_div_control1, ant_div_control2;
-+ u8 bb_desired_scale;
- u32 regVal;
-
- pModal = &eep->modalHeader;
-@@ -1096,30 +1066,29 @@ static void ath9k_hw_4k_set_board_values
- AR_PHY_SETTLING_SWITCH,
- pModal->swSettleHt40);
++EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan);
+
+ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int freq,
+@@ -109,8 +110,8 @@ int cfg80211_set_freq(struct cfg80211_re
+ switch (channel_type) {
+ case NL80211_CHAN_HT40PLUS:
+ case NL80211_CHAN_HT40MINUS:
+- if (!can_beacon_sec_chan(&rdev->wiphy, chan,
+- channel_type)) {
++ if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, chan,
++ channel_type)) {
+ printk(KERN_DEBUG
+ "cfg80211: Secondary channel not "
+ "allowed to initiate communication\n");
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -4604,13 +4604,34 @@ static int nl80211_join_ibss(struct sk_b
+ ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
}
-- if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
-- u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
-- EEP_4K_BB_DESIRED_SCALE_MASK);
-- if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
-- u32 pwrctrl, mask, clr;
--
-- mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
-- pwrctrl = mask * bb_desired_scale;
-- clr = mask * 0x1f;
-- REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
-- REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
-- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
--
-- mask = BIT(0)|BIT(5)|BIT(15);
-- pwrctrl = mask * bb_desired_scale;
-- clr = mask * 0x1f;
-- REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
--
-- mask = BIT(0)|BIT(5);
-- pwrctrl = mask * bb_desired_scale;
-- clr = mask * 0x1f;
-- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
-- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
-- }
-+
-+ bb_desired_scale = (pModal->bb_scale_smrt_antenna &
-+ EEP_4K_BB_DESIRED_SCALE_MASK);
-+ if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
-+ u32 pwrctrl, mask, clr;
-+
-+ mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
-+ pwrctrl = mask * bb_desired_scale;
-+ clr = mask * 0x1f;
-+ REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
-+ REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
-+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
+
+- ibss.channel = ieee80211_get_channel(wiphy,
+- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
++ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
++ enum nl80211_channel_type channel_type;
+
-+ mask = BIT(0)|BIT(5)|BIT(15);
-+ pwrctrl = mask * bb_desired_scale;
-+ clr = mask * 0x1f;
-+ REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
++ channel_type = nla_get_u32(
++ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
++ if (channel_type > NL80211_CHAN_HT40PLUS)
++ return -EINVAL;
++ ibss.channel_type = channel_type;
++ } else {
++ ibss.channel_type = NL80211_CHAN_NO_HT;
++ }
+
-+ mask = BIT(0)|BIT(5);
-+ pwrctrl = mask * bb_desired_scale;
-+ clr = mask * 0x1f;
-+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
-+ REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
- }
- }
-
-@@ -1161,7 +1130,6 @@ const struct eeprom_ops eep_4k_ops = {
- .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
- .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
- .set_board_values = ath9k_hw_4k_set_board_values,
-- .set_addac = ath9k_hw_4k_set_addac,
- .set_txpower = ath9k_hw_4k_set_txpower,
- .get_spur_channel = ath9k_hw_4k_get_spur_channel
- };
---- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-@@ -851,10 +851,8 @@ static void ath9k_hw_ar9287_set_txpower(
- if (test)
- return;
-
-- if (AR_SREV_9280_20_OR_LATER(ah)) {
-- for (i = 0; i < Ar5416RateSize; i++)
-- ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
-- }
-+ for (i = 0; i < Ar5416RateSize; i++)
-+ ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
-
- ENABLE_REGWRITE_BUFFER(ah);
-
-@@ -944,11 +942,6 @@ static void ath9k_hw_ar9287_set_txpower(
- REGWRITE_BUFFER_FLUSH(ah);
- }
-
--static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
-- struct ath9k_channel *chan)
--{
--}
--
- static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
- struct ath9k_channel *chan)
- {
-@@ -1100,7 +1093,6 @@ const struct eeprom_ops eep_ar9287_ops =
- .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver,
- .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev,
- .set_board_values = ath9k_hw_ar9287_set_board_values,
-- .set_addac = ath9k_hw_ar9287_set_addac,
- .set_txpower = ath9k_hw_ar9287_set_txpower,
- .get_spur_channel = ath9k_hw_ar9287_get_spur_channel
- };
---- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
-@@ -547,8 +547,7 @@ static void ath9k_hw_def_set_board_value
- break;
- }
-
-- if (AR_SREV_5416_20_OR_LATER(ah) &&
-- (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
-+ if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
- else
- regChainOffset = i * 0x1000;
-@@ -565,9 +564,8 @@ static void ath9k_hw_def_set_board_value
- SM(pModal->iqCalQCh[i],
- AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
-
-- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
-- ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
-- regChainOffset, i);
-+ ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
-+ regChainOffset, i);
- }
-
- if (AR_SREV_9280_20_OR_LATER(ah)) {
-@@ -893,8 +891,7 @@ static void ath9k_hw_set_def_power_cal_t
- xpdGainValues[2]);
-
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
-- if (AR_SREV_5416_20_OR_LATER(ah) &&
-- (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
-+ if ((ah->rxchainmask == 5 || ah->txchainmask == 5) &&
- (i != 0)) {
- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
- } else
-@@ -935,27 +932,24 @@ static void ath9k_hw_set_def_power_cal_t
-
- ENABLE_REGWRITE_BUFFER(ah);
-
-- if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
-- if (OLC_FOR_AR9280_20_LATER) {
-- REG_WRITE(ah,
-- AR_PHY_TPCRG5 + regChainOffset,
-- SM(0x6,
-- AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
-- SM_PD_GAIN(1) | SM_PD_GAIN(2) |
-- SM_PD_GAIN(3) | SM_PD_GAIN(4));
-- } else {
-- REG_WRITE(ah,
-- AR_PHY_TPCRG5 + regChainOffset,
-- SM(pdGainOverlap_t2,
-- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
-- SM_PDGAIN_B(0, 1) |
-- SM_PDGAIN_B(1, 2) |
-- SM_PDGAIN_B(2, 3) |
-- SM_PDGAIN_B(3, 4));
-- }
-+ if (OLC_FOR_AR9280_20_LATER) {
-+ REG_WRITE(ah,
-+ AR_PHY_TPCRG5 + regChainOffset,
-+ SM(0x6,
-+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
-+ SM_PD_GAIN(1) | SM_PD_GAIN(2) |
-+ SM_PD_GAIN(3) | SM_PD_GAIN(4));
-+ } else {
-+ REG_WRITE(ah,
-+ AR_PHY_TPCRG5 + regChainOffset,
-+ SM(pdGainOverlap_t2,
-+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
-+ SM_PDGAIN_B(0, 1) |
-+ SM_PDGAIN_B(1, 2) |
-+ SM_PDGAIN_B(2, 3) |
-+ SM_PDGAIN_B(3, 4));
- }
-
--
- ath9k_adjust_pdadc_values(ah, pwr_table_offset,
- diff, pdadcValues);
-
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -506,7 +506,6 @@ static void ath9k_init_misc(struct ath_s
- sc->sc_flags |= SC_OP_RXAGGR;
- }
-
-- ath9k_hw_set_diversity(sc->sc_ah, true);
- sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
-
- memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
---- a/drivers/net/wireless/ath/ath9k/reg.h
-+++ b/drivers/net/wireless/ath/ath9k/reg.h
-@@ -800,10 +800,6 @@
- #define AR_SREV_5416(_ah) \
- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
- ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
--#define AR_SREV_5416_20_OR_LATER(_ah) \
-- (((AR_SREV_5416(_ah)) && \
-- ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
-- ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
- #define AR_SREV_5416_22_OR_LATER(_ah) \
- (((AR_SREV_5416(_ah)) && \
- ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
-@@ -869,6 +869,7 @@ static bool ar9002_hw_init_cal(struct at
- ar9002_hw_pa_cal(ah, true);
-
- /* Do NF Calibration after DC offset and other calibrations */
-+ ath9k_hw_loadnf(ah, chan);
- ath9k_hw_start_nfcal(ah, true);
-
- if (ah->caldata)
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -671,7 +671,6 @@ enum queue_stop_reason {
- IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
- IEEE80211_QUEUE_STOP_REASON_SUSPEND,
- IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
-- IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE,
- };
-
- #ifdef CONFIG_MAC80211_LEDS
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -1921,24 +1921,8 @@ static void ieee80211_rx_mgmt_beacon(str
-
- rcu_read_unlock();
-
-- /*
-- * Whenever the AP announces the HT mode change that can be
-- * 40MHz intolerant or etc., it would be safer to stop tx
-- * queues before doing hw config to avoid buffer overflow.
-- */
-- ieee80211_stop_queues_by_reason(&sdata->local->hw,
-- IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE);
--
-- /* flush out all packets */
-- synchronize_net();
--
-- drv_flush(local, false);
--
- changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
- bssid, ap_ht_cap_flags);
--
-- ieee80211_wake_queues_by_reason(&sdata->local->hw,
-- IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE);
- }
-
- /* Note: country IE parsing is done for us by cfg80211 */
---- a/drivers/net/wireless/b43/main.c
-+++ b/drivers/net/wireless/b43/main.c
-@@ -1613,7 +1613,8 @@ static void handle_irq_beacon(struct b43
- u32 cmd, beacon0_valid, beacon1_valid;
++ ibss.channel = rdev_freq_to_chan(rdev,
++ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
++ ibss.channel_type);
+ if (!ibss.channel ||
++ ibss.channel->flags & IEEE80211_CHAN_RADAR ||
+ ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
+ ibss.channel->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
- if (!b43_is_mode(wl, NL80211_IFTYPE_AP) &&
-- !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT))
-+ !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) &&
-+ !b43_is_mode(wl, NL80211_IFTYPE_ADHOC))
- return;
++ /* Both channels should be able to initiate communication */
++ if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
++ ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
++ !cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
++ ibss.channel_type))
++ return -EINVAL;
++
+ ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
+ ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
- /* This is the bottom half of the asynchronous beacon update. */
+++ /dev/null
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -1101,6 +1101,7 @@ struct cfg80211_ibss_params {
- u8 *ssid;
- u8 *bssid;
- struct ieee80211_channel *channel;
-+ enum nl80211_channel_type channel_type;
- u8 *ie;
- u8 ssid_len, ie_len;
- u16 beacon_interval;
-@@ -2612,6 +2613,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
- const u8 *bssid,
- const u8 *ssid, size_t ssid_len,
- u16 capa_mask, u16 capa_val);
-+struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
-+ struct ieee80211_channel *channel,
-+ const u8 *bssid,
-+ const u8 *ssid, size_t ssid_len,
-+ u16 capa_mask, u16 capa_val,
-+ enum nl80211_channel_type channel_type);
- static inline struct cfg80211_bss *
- cfg80211_get_ibss(struct wiphy *wiphy,
- struct ieee80211_channel *channel,
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -4539,13 +4539,41 @@ static int nl80211_join_ibss(struct sk_b
- ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
- }
-
-- ibss.channel = ieee80211_get_channel(wiphy,
-- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
-+ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
-+ enum nl80211_channel_type channel_type;
-+
-+ channel_type = nla_get_u32(
-+ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
-+ if (channel_type != NL80211_CHAN_NO_HT &&
-+ channel_type != NL80211_CHAN_HT20 &&
-+ channel_type != NL80211_CHAN_HT40PLUS &&
-+ channel_type != NL80211_CHAN_HT40MINUS)
-+ return -EINVAL;
-+ ibss.channel_type = channel_type;
-+ } else {
-+ ibss.channel_type = NL80211_CHAN_NO_HT;
-+ }
-+
-+ ibss.channel = rdev_freq_to_chan(rdev,
-+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
-+ ibss.channel_type);
- if (!ibss.channel ||
-+ ibss.channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
- ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
-- ibss.channel->flags & IEEE80211_CHAN_DISABLED)
-+ ibss.channel->flags & IEEE80211_CHAN_RADAR)
- return -EINVAL;
-
-+ /* Both channels should be able to initiate communication */
-+ if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
-+ ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
-+ !can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
-+ ibss.channel_type)) {
-+ printk(KERN_DEBUG
-+ "cfg80211: Secondary channel not "
-+ "allowed to initiate communication\n");
-+ return -EINVAL;
-+ }
-+
- ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
- ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
-
---- a/net/wireless/chan.c
-+++ b/net/wireless/chan.c
-@@ -44,7 +44,7 @@ rdev_freq_to_chan(struct cfg80211_regist
- return chan;
- }
-
--static bool can_beacon_sec_chan(struct wiphy *wiphy,
-+bool can_beacon_sec_chan(struct wiphy *wiphy,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type)
- {
-@@ -75,6 +75,7 @@ static bool can_beacon_sec_chan(struct w
-
- return true;
- }
-+EXPORT_SYMBOL(can_beacon_sec_chan);
-
- int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev, int freq,
---- a/net/wireless/core.h
-+++ b/net/wireless/core.h
-@@ -439,6 +439,9 @@ cfg80211_can_add_interface(struct cfg802
- struct ieee80211_channel *
- rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
- int freq, enum nl80211_channel_type channel_type);
-+bool can_beacon_sec_chan(struct wiphy *wiphy,
-+ struct ieee80211_channel *chan,
-+ enum nl80211_channel_type channel_type);
- int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev, int freq,
- enum nl80211_channel_type channel_type);
---- a/net/wireless/scan.c
-+++ b/net/wireless/scan.c
-@@ -365,6 +365,19 @@ struct cfg80211_bss *cfg80211_get_bss(st
- const u8 *ssid, size_t ssid_len,
- u16 capa_mask, u16 capa_val)
- {
-+ /* call HT version with no HT requirements */
-+ return cfg80211_get_bss_ht(wiphy, channel, bssid, ssid, ssid_len,
-+ capa_mask, capa_val, NL80211_CHAN_NO_HT);
-+}
-+EXPORT_SYMBOL(cfg80211_get_bss);
-+
-+struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
-+ struct ieee80211_channel *channel,
-+ const u8 *bssid,
-+ const u8 *ssid, size_t ssid_len,
-+ u16 capa_mask, u16 capa_val,
-+ enum nl80211_channel_type require_ht)
-+{
- struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
- struct cfg80211_internal_bss *bss, *res = NULL;
- unsigned long now = jiffies;
-@@ -374,8 +387,26 @@ struct cfg80211_bss *cfg80211_get_bss(st
- list_for_each_entry(bss, &dev->bss_list, list) {
- if ((bss->pub.capability & capa_mask) != capa_val)
- continue;
-- if (channel && bss->pub.channel != channel)
-- continue;
-+ if (channel) {
-+ if (bss->pub.channel != channel)
-+ continue;
-+ if (require_ht != NL80211_CHAN_NO_HT) {
-+ struct ieee80211_ht_info *ht_info;
-+ ht_info = (struct ieee80211_ht_info *)
-+ ieee80211_bss_get_ie(&bss->pub,
-+ WLAN_EID_HT_INFORMATION);
-+ if (!ht_info)
-+ continue;
-+ if (require_ht == NL80211_CHAN_HT40MINUS &&
-+ !(ht_info->ht_param &
-+ IEEE80211_HT_PARAM_CHA_SEC_BELOW))
-+ continue;
-+ if (require_ht == NL80211_CHAN_HT40PLUS &&
-+ !(ht_info->ht_param &
-+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE))
-+ continue;
-+ }
-+ }
- /* Don't get expired BSS structs */
- if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
- !atomic_read(&bss->hold))
-@@ -392,7 +423,7 @@ struct cfg80211_bss *cfg80211_get_bss(st
- return NULL;
- return &res->pub;
- }
--EXPORT_SYMBOL(cfg80211_get_bss);
-+EXPORT_SYMBOL(cfg80211_get_bss_ht);
-
- struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
- struct ieee80211_channel *channel,
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -465,6 +465,7 @@ struct ieee80211_if_ibss {
- u8 ssid_len, ie_len;
- u8 *ie;
- struct ieee80211_channel *channel;
-+ enum nl80211_channel_type channel_type;
-
- unsigned long ibss_join_req;
- /* probe response/beacon for IBSS */
-@@ -1090,6 +1091,7 @@ void ieee80211_ibss_notify_scan_complete
- void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
- struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
- u8 *bssid, u8 *addr, u32 supp_rates,
-+ struct ieee80211_ht_cap *ht_cap,
- gfp_t gfp);
- int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
- struct cfg80211_ibss_params *params);
-@@ -1343,6 +1345,12 @@ void ieee80211_recalc_smps(struct ieee80
- size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
- const u8 *ids, int n_ids, size_t offset);
- size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
-+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
-+ u16 cap);
-+u8 *ieee80211_ie_build_ht_info(u8 *pos,
-+ struct ieee80211_sta_ht_cap *ht_cap,
-+ struct ieee80211_channel *channel,
-+ enum nl80211_channel_type channel_type);
-
- /* internal work items */
- void ieee80211_work_init(struct ieee80211_local *local);
-@@ -1371,6 +1379,8 @@ ieee80211_get_channel_mode(struct ieee80
- bool ieee80211_set_channel_type(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- enum nl80211_channel_type chantype);
-+enum nl80211_channel_type ieee80211_ht_info_to_channel_type(
-+ struct ieee80211_ht_info *ht_info);
-
- #ifdef CONFIG_MAC80211_NOINLINE
- #define debug_noinline noinline
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -839,23 +839,8 @@ int ieee80211_build_preq_ies(struct ieee
- offset = noffset;
- }
-
-- if (sband->ht_cap.ht_supported) {
-- u16 cap = sband->ht_cap.cap;
-- __le16 tmp;
--
-- *pos++ = WLAN_EID_HT_CAPABILITY;
-- *pos++ = sizeof(struct ieee80211_ht_cap);
-- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
-- tmp = cpu_to_le16(cap);
-- memcpy(pos, &tmp, sizeof(u16));
-- pos += sizeof(u16);
-- *pos++ = sband->ht_cap.ampdu_factor |
-- (sband->ht_cap.ampdu_density <<
-- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
-- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
-- pos += sizeof(sband->ht_cap.mcs);
-- pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
-- }
-+ if (sband->ht_cap.ht_supported)
-+ pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
-
- /*
- * If adding more here, adjust code in main.c
-@@ -1378,3 +1363,100 @@ void ieee80211_disable_rssi_reports(stru
- _ieee80211_enable_rssi_reports(sdata, 0, 0);
- }
- EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
-+
-+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
-+ u16 cap)
-+{
-+ __le16 tmp;
-+
-+ *pos++ = WLAN_EID_HT_CAPABILITY;
-+ *pos++ = sizeof(struct ieee80211_ht_cap);
-+ memset(pos, 0, sizeof(struct ieee80211_ht_cap));
-+
-+ /* capability flags */
-+ tmp = cpu_to_le16(cap);
-+ memcpy(pos, &tmp, sizeof(u16));
-+ pos += sizeof(u16);
-+
-+ /* AMPDU parameters */
-+ *pos++ = sband->ht_cap.ampdu_factor |
-+ (sband->ht_cap.ampdu_density <<
-+ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
-+
-+ /* MCS set */
-+ memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
-+ pos += sizeof(sband->ht_cap.mcs);
-+
-+ /* extended capabilities */
-+ pos += sizeof(__le16);
-+
-+ /* BF capabilities */
-+ pos += sizeof(__le32);
-+
-+ /* antenna selection */
-+ pos += sizeof(u8);
-+
-+ return pos;
-+}
-+
-+u8 *ieee80211_ie_build_ht_info(u8 *pos,
-+ struct ieee80211_sta_ht_cap *ht_cap,
-+ struct ieee80211_channel *channel,
-+ enum nl80211_channel_type channel_type)
-+{
-+ struct ieee80211_ht_info *ht_info;
-+ /* Build HT Information */
-+ *pos++ = WLAN_EID_HT_INFORMATION;
-+ *pos++ = sizeof(struct ieee80211_ht_info);
-+ ht_info = (struct ieee80211_ht_info *)pos;
-+ ht_info->control_chan =
-+ ieee80211_frequency_to_channel(channel->center_freq);
-+ switch (channel_type) {
-+ case NL80211_CHAN_HT40MINUS:
-+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-+ break;
-+ case NL80211_CHAN_HT40PLUS:
-+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-+ break;
-+ case NL80211_CHAN_HT20:
-+ default:
-+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
-+ break;
-+ }
-+ if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
-+ ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
-+ ht_info->operation_mode = 0x0000;
-+ ht_info->stbc_param = 0x0000;
-+
-+ /* It seems that Basic MCS set and Supported MCS set
-+ are identical for the first 10 bytes */
-+ memset(&ht_info->basic_set, 0, 16);
-+ memcpy(&ht_info->basic_set, &ht_cap->mcs, 10);
-+
-+ return pos + sizeof(struct ieee80211_ht_info);
-+}
-+
-+enum nl80211_channel_type ieee80211_ht_info_to_channel_type(
-+ struct ieee80211_ht_info *ht_info)
-+{
-+ enum nl80211_channel_type channel_type;
-+
-+ if (!ht_info)
-+ return NL80211_CHAN_NO_HT;
-+
-+ switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
-+ case IEEE80211_HT_PARAM_CHA_SEC_NONE:
-+ channel_type = NL80211_CHAN_HT20;
-+ break;
-+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-+ channel_type = NL80211_CHAN_HT40PLUS;
-+ break;
-+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-+ channel_type = NL80211_CHAN_HT40MINUS;
-+ break;
-+ default:
-+ channel_type = NL80211_CHAN_NO_HT;
-+ }
-+
-+ return channel_type;
-+}
---- a/net/mac80211/work.c
-+++ b/net/mac80211/work.c
-@@ -118,7 +118,6 @@ static void ieee80211_add_ht_ie(struct s
- u8 *pos;
- u32 flags = channel->flags;
- u16 cap = sband->ht_cap.cap;
-- __le16 tmp;
-
- if (!sband->ht_cap.ht_supported)
- return;
-@@ -169,34 +168,8 @@ static void ieee80211_add_ht_ie(struct s
- }
-
- /* reserve and fill IE */
--
- pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
-- *pos++ = WLAN_EID_HT_CAPABILITY;
-- *pos++ = sizeof(struct ieee80211_ht_cap);
-- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
--
-- /* capability flags */
-- tmp = cpu_to_le16(cap);
-- memcpy(pos, &tmp, sizeof(u16));
-- pos += sizeof(u16);
--
-- /* AMPDU parameters */
-- *pos++ = sband->ht_cap.ampdu_factor |
-- (sband->ht_cap.ampdu_density <<
-- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
--
-- /* MCS set */
-- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
-- pos += sizeof(sband->ht_cap.mcs);
--
-- /* extended capabilities */
-- pos += sizeof(__le16);
--
-- /* BF capabilities */
-- pos += sizeof(__le32);
--
-- /* antenna selection */
-- pos += sizeof(u8);
-+ ieee80211_ie_build_ht_cap(pos, sband, cap);
- }
-
- static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -82,6 +82,8 @@ static void ieee80211_send_addba_request
- memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
- else if (sdata->vif.type == NL80211_IFTYPE_STATION)
- memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
-
- mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_ACTION);
-@@ -399,7 +401,8 @@ int ieee80211_start_tx_ba_session(struct
- if (sdata->vif.type != NL80211_IFTYPE_STATION &&
- sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
- sdata->vif.type != NL80211_IFTYPE_AP &&
-- sdata->vif.type != NL80211_IFTYPE_WDS)
-+ sdata->vif.type != NL80211_IFTYPE_WDS &&
-+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
- return -EINVAL;
-
- if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
---- a/net/mac80211/ht.c
-+++ b/net/mac80211/ht.c
-@@ -199,6 +199,8 @@ void ieee80211_send_delba(struct ieee802
- memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
- else if (sdata->vif.type == NL80211_IFTYPE_STATION)
- memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
-
- mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_ACTION);
---- a/net/mac80211/ibss.c
-+++ b/net/mac80211/ibss.c
-@@ -35,6 +35,76 @@
-
- #define IEEE80211_IBSS_MAX_STA_ENTRIES 128
-
-+static bool ieee80211_can_use_ext_chan(struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_channel *channel,
-+ enum nl80211_channel_type channel_type)
-+{
-+ /* check if we are legally allowed to use HT extension channel */
-+ if ((channel_type == NL80211_CHAN_HT40PLUS) ||
-+ (channel_type == NL80211_CHAN_HT40MINUS)) {
-+ int sec_freq = channel->center_freq +
-+ (channel_type == NL80211_CHAN_HT40PLUS ? 20 : -20);
-+ struct ieee80211_channel *sec_chan =
-+ ieee80211_get_channel(sdata->wdev.wiphy, sec_freq);
-+ if (!sec_chan || sec_chan->flags & (IEEE80211_CHAN_DISABLED |
-+ IEEE80211_CHAN_PASSIVE_SCAN |
-+ IEEE80211_CHAN_NO_IBSS |
-+ IEEE80211_CHAN_RADAR)) {
-+ return false;
-+ }
-+ }
-+ return true;
-+}
-+
-+static void ieee80211_update_ht_elems(struct ieee80211_sub_if_data *sdata,
-+ struct ieee80211_mgmt *mgmt,
-+ struct ieee80211_ht_info *ht_info)
-+{
-+ struct ieee80211_local *local = sdata->local;
-+ struct ieee80211_supported_band *sband =
-+ local->hw.wiphy->bands[local->oper_channel->band];
-+ enum nl80211_channel_type channel_type =
-+ ieee80211_ht_info_to_channel_type(ht_info);
-+
-+ if (!ieee80211_can_use_ext_chan(sdata, local->oper_channel, channel_type))
-+ channel_type = NL80211_CHAN_HT20;
-+
-+ if (channel_type != local->_oper_channel_type) {
-+ struct sk_buff *skb = rcu_dereference_protected(
-+ sdata->u.ibss.presp,
-+ lockdep_is_held(&ifibss->mtx));
-+ struct sk_buff *nskb;
-+ u8 *ht_ie;
-+
-+ /* update HT IE. If not yet existing, create one */
-+ nskb = skb_copy(skb, GFP_ATOMIC);
-+ ht_ie = (u8 *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
-+ (const u8 *)(nskb->data + 24 +
-+ sizeof(mgmt->u.beacon)),
-+ nskb->len - 24 -
-+ sizeof(mgmt->u.beacon));
-+ if (!ht_ie)
-+ ht_ie = skb_put(nskb, 4 +
-+ sizeof(struct ieee80211_ht_cap) +
-+ sizeof(struct ieee80211_ht_info));
-+
-+ ht_ie = ieee80211_ie_build_ht_cap(ht_ie, sband,
-+ sband->ht_cap.cap);
-+ ht_ie = ieee80211_ie_build_ht_info(ht_ie, &sband->ht_cap,
-+ local->oper_channel, channel_type);
-+ rcu_assign_pointer(sdata->u.ibss.presp, nskb);
-+ kfree_skb(skb);
-+
-+ if(!ieee80211_set_channel_type(local, sdata, channel_type)) {
-+ channel_type = NL80211_CHAN_HT20;
-+ WARN_ON(!ieee80211_set_channel_type(local, sdata,
-+ channel_type));
-+ }
-+
-+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-+ }
-+
-+}
-
- static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt,
-@@ -64,6 +134,7 @@ static void ieee80211_rx_mgmt_auth_ibss(
- static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
- const u8 *bssid, const int beacon_int,
- struct ieee80211_channel *chan,
-+ enum nl80211_channel_type channel_type,
- const u32 basic_rates,
- const u16 capability, u64 tsf)
- {
-@@ -104,8 +175,17 @@ static void __ieee80211_sta_join_ibss(st
-
- sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
-
-+ /* entering a legacy IBSS. Use given HT configuration. */
-+ if (channel_type == NL80211_CHAN_NO_HT)
-+ channel_type = ifibss->channel_type;
- local->oper_channel = chan;
-- WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
-+
-+ /* if phy is on a different extension channel, setting ht40 will fail */
-+ if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
-+ channel_type = NL80211_CHAN_HT20;
-+ WARN_ON(!ieee80211_set_channel_type(local, sdata,
-+ channel_type));
-+ }
- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-
- sband = local->hw.wiphy->bands[chan->band];
-@@ -171,6 +251,18 @@ static void __ieee80211_sta_join_ibss(st
- memcpy(skb_put(skb, ifibss->ie_len),
- ifibss->ie, ifibss->ie_len);
-
-+ /* add HT capability and information IEs */
-+ if (channel_type != NL80211_CHAN_NO_HT && sband->ht_cap.ht_supported) {
-+ pos = skb_put(skb, 4 +
-+ sizeof(struct ieee80211_ht_cap) +
-+ sizeof(struct ieee80211_ht_info));
-+ pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
-+ pos = ieee80211_ie_build_ht_info(pos,
-+ &sband->ht_cap,
-+ chan,
-+ channel_type);
-+ }
-+
- if (local->hw.queues >= 4) {
- pos = skb_put(skb, 9);
- *pos++ = WLAN_EID_VENDOR_SPECIFIC;
-@@ -219,6 +311,8 @@ static void ieee80211_sta_join_ibss(stru
- u32 basic_rates;
- int i, j;
- u16 beacon_int = cbss->beacon_interval;
-+ const u8 *ht_info_ie;
-+ enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
-
- lockdep_assert_held(&sdata->u.ibss.mtx);
-
-@@ -242,9 +336,23 @@ static void ieee80211_sta_join_ibss(stru
- }
- }
-
-+ ht_info_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_INFORMATION);
-+ if (ht_info_ie)
-+ channel_type = ieee80211_ht_info_to_channel_type(
-+ (struct ieee80211_ht_info *) (ht_info_ie + 2));
-+
-+ if (!ieee80211_can_use_ext_chan(sdata, cbss->channel, channel_type)) {
-+ channel_type = NL80211_CHAN_HT20;
-+#ifdef CONFIG_MAC80211_IBSS_DEBUG
-+ printk(KERN_DEBUG "%s: IBSS not allowed on secondary channel\n",
-+ sdata->name);
-+#endif
-+ }
-+
- __ieee80211_sta_join_ibss(sdata, cbss->bssid,
- beacon_int,
- cbss->channel,
-+ channel_type,
- basic_rates,
- cbss->capability,
- cbss->tsf);
-@@ -310,11 +418,24 @@ static void ieee80211_rx_bss_info(struct
- } else
- sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
- mgmt->sa, supp_rates,
-- GFP_ATOMIC);
-+ elems->ht_cap_elem, GFP_ATOMIC);
- }
-
-- if (sta && elems->wmm_info)
-- set_sta_flags(sta, WLAN_STA_WME);
-+ if (sta) {
-+ if (elems->wmm_info)
-+ set_sta_flags(sta, WLAN_STA_WME);
-+
-+ /* remote station uses ht */
-+ if (elems->ht_info_elem) {
-+ ieee80211_update_ht_elems(sdata, mgmt,
-+ elems->ht_info_elem);
-+ ieee80211_ht_cap_ie_to_sta_ht_cap(
-+ local->hw.wiphy->bands[
-+ local->oper_channel->band],
-+ elems->ht_cap_elem,
-+ &sta->sta.ht_cap);
-+ }
-+ }
-
- rcu_read_unlock();
- }
-@@ -404,7 +525,7 @@ static void ieee80211_rx_bss_info(struct
- ieee80211_sta_join_ibss(sdata, bss);
- supp_rates = ieee80211_sta_get_rates(local, elems, band);
- ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
-- supp_rates, GFP_KERNEL);
-+ supp_rates, elems->ht_cap_elem, GFP_KERNEL);
- }
-
- put_bss:
-@@ -417,7 +538,8 @@ static void ieee80211_rx_bss_info(struct
- * must be callable in atomic context.
- */
- struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
-- u8 *bssid,u8 *addr, u32 supp_rates,
-+ u8 *bssid, u8 *addr, u32 supp_rates,
-+ struct ieee80211_ht_cap *ht_cap,
- gfp_t gfp)
- {
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-@@ -458,6 +580,11 @@ struct sta_info *ieee80211_ibss_add_sta(
- sta->sta.supp_rates[band] = supp_rates |
- ieee80211_mandatory_rates(local, band);
-
-+ /* fill in ht rates */
-+ if (ht_cap)
-+ ieee80211_ht_cap_ie_to_sta_ht_cap(local->hw.wiphy->bands[band],
-+ ht_cap, &sta->sta.ht_cap);
-+
- rate_control_rate_init(sta);
-
- /* If it fails, maybe we raced another insertion? */
-@@ -556,8 +683,8 @@ static void ieee80211_sta_create_ibss(st
- sdata->drop_unencrypted = 0;
-
- __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
-- ifibss->channel, ifibss->basic_rates,
-- capability, 0);
-+ ifibss->channel, ifibss->channel_type,
-+ ifibss->basic_rates, capability, 0);
- }
-
- /*
-@@ -594,10 +721,10 @@ static void ieee80211_sta_find_ibss(stru
- chan = ifibss->channel;
- if (!is_zero_ether_addr(ifibss->bssid))
- bssid = ifibss->bssid;
-- cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
-+ cbss = cfg80211_get_bss_ht(local->hw.wiphy, chan, bssid,
- ifibss->ssid, ifibss->ssid_len,
- WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY,
-- capability);
-+ capability, ifibss->channel_type);
-
- if (cbss) {
- struct ieee80211_bss *bss;
-@@ -896,10 +1023,15 @@ int ieee80211_ibss_join(struct ieee80211
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
-- 36 /* bitrates */ +
-- 34 /* SSID */ +
-- 3 /* DS params */ +
-- 4 /* IBSS params */ +
-+ sizeof(struct ieee80211_hdr_3addr) +
-+ 12 /* struct ieee80211_mgmt.u.beacon */ +
-+ 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
-+ 2 + 8 /* max Supported Rates */ +
-+ 3 /* max DS params */ +
-+ 4 /* IBSS params */ +
-+ 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
-+ 2 + sizeof(struct ieee80211_ht_cap) +
-+ 2 + sizeof(struct ieee80211_ht_info) +
- params->ie_len);
- if (!skb)
- return -ENOMEM;
-@@ -920,13 +1052,15 @@ int ieee80211_ibss_join(struct ieee80211
- sdata->vif.bss_conf.beacon_int = params->beacon_interval;
-
- sdata->u.ibss.channel = params->channel;
-+ sdata->u.ibss.channel_type = params->channel_type;
- sdata->u.ibss.fixed_channel = params->channel_fixed;
-
- /* fix ourselves to that channel now already */
- if (params->channel_fixed) {
- sdata->local->oper_channel = params->channel;
-- WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
-- NL80211_CHAN_NO_HT));
-+ if(!ieee80211_set_channel_type(sdata->local, sdata,
-+ params->channel_type))
-+ return -EINVAL;
- }
-
- if (params->ie) {
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2164,7 +2164,8 @@ ieee80211_rx_h_action(struct ieee80211_r
- if (sdata->vif.type != NL80211_IFTYPE_STATION &&
- sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
- sdata->vif.type != NL80211_IFTYPE_AP &&
-- sdata->vif.type != NL80211_IFTYPE_WDS)
-+ sdata->vif.type != NL80211_IFTYPE_WDS &&
-+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
- break;
-
- /* verify action_code is present */
-@@ -2699,7 +2700,8 @@ static int prepare_for_handlers(struct i
- else
- rate_idx = status->rate_idx;
- rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
-- hdr->addr2, BIT(rate_idx), GFP_ATOMIC);
-+ hdr->addr2, BIT(rate_idx), NULL,
-+ GFP_ATOMIC);
- }
- break;
- case NL80211_IFTYPE_MESH_POINT:
---- a/net/mac80211/agg-rx.c
-+++ b/net/mac80211/agg-rx.c
-@@ -182,6 +182,8 @@ static void ieee80211_send_addba_resp(st
- memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
- else if (sdata->vif.type == NL80211_IFTYPE_WDS)
- memcpy(mgmt->bssid, da, ETH_ALEN);
-+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
-
- mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_ACTION);
+ debug.o
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
-@@ -274,13 +274,6 @@ void ath_dbg(struct ath_common *common,
+@@ -272,13 +272,6 @@ void ath_dbg(struct ath_common *common,
#endif /* CONFIG_ATH_DEBUG */
/** Returns string describing opmode, or NULL if unknown mode. */
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -35,7 +35,7 @@ int ath9k_modparam_nohwcrypt;
+@@ -36,7 +36,7 @@ int ath9k_modparam_nohwcrypt;
module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -16,6 +16,7 @@
-
+@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/slab.h>
+ #include <linux/module.h>
+#include <linux/etherdevice.h>
#include <asm/unaligned.h>
#include "hw.h"
-@@ -460,8 +461,16 @@ static int ath9k_hw_init_macaddr(struct
+@@ -465,8 +466,16 @@ static int ath9k_hw_init_macaddr(struct
common->macaddr[2 * i] = eeval >> 8;
common->macaddr[2 * i + 1] = eeval & 0xff;
}
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
-@@ -193,6 +193,10 @@ ath_reg_apply_beaconing_flags(struct wip
+@@ -194,6 +194,10 @@ ath_reg_apply_beaconing_flags(struct wip
u32 bandwidth = 0;
int r;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (!wiphy->bands[band])
-@@ -252,6 +256,10 @@ ath_reg_apply_active_scan_flags(struct w
+@@ -253,6 +257,10 @@ ath_reg_apply_active_scan_flags(struct w
u32 bandwidth = 0;
int r;
+#endif
+
sband = wiphy->bands[IEEE80211_BAND_2GHZ];
-
- /*
-@@ -299,6 +307,10 @@ static void ath_reg_apply_radar_flags(st
+ if (!sband)
+ return;
+@@ -302,6 +310,10 @@ static void ath_reg_apply_radar_flags(st
struct ieee80211_channel *ch;
unsigned int i;
if (!wiphy->bands[IEEE80211_BAND_5GHZ])
return;
-@@ -466,6 +478,10 @@ ath_regd_init_wiphy(struct ath_regulator
+@@ -469,6 +481,10 @@ ath_regd_init_wiphy(struct ath_regulator
{
const struct ieee80211_regdomain *regd;
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
-@@ -37,7 +37,8 @@
+@@ -38,7 +38,8 @@
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
/* We allow IBSS on these on a case by case basis by regulatory domain */
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\
NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
-@@ -55,57 +56,56 @@
+@@ -56,57 +57,56 @@
#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
ATH9K_5GHZ_5725_5850
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
-@@ -1653,6 +1653,8 @@ void regulatory_hint_11d(struct wiphy *w
+@@ -1656,6 +1656,8 @@ void regulatory_hint_11d(struct wiphy *w
enum environment_cap env = ENVIRON_ANY;
struct regulatory_request *request;
mutex_lock(®_mutex);
if (unlikely(!last_request))
-@@ -1859,6 +1861,8 @@ static void restore_regulatory_settings(
+@@ -1862,6 +1864,8 @@ static void restore_regulatory_settings(
void regulatory_hint_disconnect(void)
{
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1473,15 +1473,6 @@ static int ath9k_add_interface(struct ie
+@@ -1448,15 +1448,6 @@ static int ath9k_add_interface(struct ie
}
}
ath_dbg(common, ATH_DBG_CONFIG,
"Attach a VIF of type: %d\n", vif->type);
-@@ -1507,15 +1498,6 @@ static int ath9k_change_interface(struct
+@@ -1482,15 +1473,6 @@ static int ath9k_change_interface(struct
mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);
goto end;
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1866,7 +1866,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+@@ -1860,7 +1860,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
ah->bmisscount = 0;
}
ah->opmode == NL80211_IFTYPE_MESH_POINT) {
u64 tsf = ath5k_hw_get_tsf64(ah);
u32 tsftu = TSF_TO_TU(tsf);
-@@ -1951,7 +1951,7 @@ ath5k_beacon_update_timers(struct ath5k_
+@@ -1945,7 +1945,7 @@ ath5k_beacon_update_timers(struct ath5k_
u64 hw_tsf;
intval = ah->bintval & AR5K_BEACON_PERIOD;
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1585,6 +1585,53 @@ static const struct file_operations fops
+@@ -1616,6 +1616,53 @@ static const struct file_operations fops
};
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
-@@ -1643,6 +1690,9 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1674,6 +1721,9 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1674,8 +1674,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1715,8 +1715,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
REG_WRITE(ah, AR_OBS, 8);
if (ah->config.rx_intr_mitigation) {
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -363,7 +363,7 @@ struct ath_vif {
+@@ -366,7 +366,7 @@ struct ath_vif {
* number of beacon intervals, the game's up.
*/
#define BSTUCK_THRESH 9
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -382,8 +382,8 @@ static void ath9k_hw_init_config(struct
+@@ -388,8 +388,8 @@ static void ath9k_hw_init_config(struct
{
int i;
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -120,7 +120,7 @@ void ath_descdma_cleanup(struct ath_soft
+@@ -121,7 +121,7 @@ void ath_descdma_cleanup(struct ath_soft
/* RX / TX */
/***********/
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -585,6 +585,7 @@ struct ath_softc {
+@@ -591,6 +591,7 @@ struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
int chan_idx;
int chan_is_ht;
struct survey_info *cur_survey;
+@@ -654,6 +655,7 @@ struct ath_softc {
+ u8 ant_tx, ant_rx;
+ };
+
++int ath9k_config(struct ieee80211_hw *hw, u32 changed);
+ void ath9k_tasklet(unsigned long data);
+ int ath_cabq_update(struct ath_softc *);
+
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1693,6 +1693,9 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1663,6 +1663,50 @@ static const struct file_operations fops
+ .owner = THIS_MODULE
+ };
+
++
++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ char buf[32];
++ unsigned int len;
++
++ len = sprintf(buf, "0x%08x\n", sc->chan_bw);
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ unsigned long chan_bw;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (strict_strtoul(buf, 0, &chan_bw))
++ return -EINVAL;
++
++ sc->chan_bw = chan_bw;
++ if (!sc->ps_idle)
++ ath9k_config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL);
++
++ return count;
++}
++
++static const struct file_operations fops_chanbw = {
++ .read = read_file_chan_bw,
++ .write = write_file_chan_bw,
++ .open = ath9k_debugfs_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1724,6 +1768,9 @@ int ath9k_init_debug(struct ath_hw *ah)
debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_eeprom);
-+ debugfs_create_u32("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-+ &sc->chan_bw);
++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++ sc, &fops_chanbw);
+
sc->debug.regidx = 0;
memset(&sc->debug.bb_mac_samp, 0, sizeof(sc->debug.bb_mac_samp));
sc->debug.sampidx = 0;
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1636,9 +1636,10 @@ static int ath9k_config(struct ieee80211
+@@ -1554,7 +1554,7 @@ static void ath9k_disable_ps(struct ath_
+
+ }
+
+-static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
++int ath9k_config(struct ieee80211_hw *hw, u32 changed)
+ {
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+@@ -1606,9 +1606,10 @@ static int ath9k_config(struct ieee80211
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
unsigned long flags;
if (ah->curchan)
-@@ -1691,7 +1692,23 @@ static int ath9k_config(struct ieee80211
+@@ -1661,7 +1662,23 @@ static int ath9k_config(struct ieee80211
memset(&sc->survey[pos], 0, sizeof(struct survey_info));
}
return -EINVAL;
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1509,6 +1509,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
- (AR_SREV_9300_20_OR_LATER(ah) && IS_CHAN_5GHZ(chan)))
- bChannelChange = false;
+@@ -1549,6 +1549,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ caldata->rtt_hist.num_readings)
+ allow_fbs = true;
+ if (!ah->curchan || ((ah->curchan->channelFlags ^ chan->channelFlags) &
+ (CHANNEL_HALF | CHANNEL_QUARTER)))
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -355,10 +355,12 @@ minstrel_downgrade_rate(struct minstrel_
+@@ -357,10 +357,12 @@ minstrel_downgrade_rate(struct minstrel_
}
static void
u16 tid;
if (unlikely(!ieee80211_is_data_qos(hdr->frame_control)))
-@@ -374,6 +376,12 @@ minstrel_aggr_check(struct minstrel_priv
+@@ -376,6 +378,12 @@ minstrel_aggr_check(struct minstrel_priv
if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
return;
ieee80211_start_tx_ba_session(pubsta, tid, 5000);
}
-@@ -453,7 +461,7 @@ minstrel_ht_tx_status(void *priv, struct
+@@ -455,7 +463,7 @@ minstrel_ht_tx_status(void *priv, struct
if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
minstrel_ht_update_stats(mp, mi);
if (!(info->flags & IEEE80211_TX_CTL_AMPDU))
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -239,7 +239,9 @@ void ieee80211_bss_info_change_notify(st
+@@ -237,7 +237,9 @@ void ieee80211_bss_info_change_notify(st
u32 changed)
{
struct ieee80211_local *local = sdata->local;
if (!changed)
return;
-@@ -269,6 +271,22 @@ void ieee80211_bss_info_change_notify(st
+@@ -267,6 +269,22 @@ void ieee80211_bss_info_change_notify(st
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
-@@ -685,6 +685,7 @@ static const struct net_device_ops ieee8
+@@ -699,6 +699,7 @@ static const struct net_device_ops ieee8
static void ieee80211_if_setup(struct net_device *dev)
{
ether_setup(dev);
--- /dev/null
+--- a/net/mac80211/rc80211_minstrel_ht.h
++++ b/net/mac80211/rc80211_minstrel_ht.h
+@@ -70,6 +70,8 @@ struct minstrel_mcs_group_data {
+ };
+
+ struct minstrel_ht_sta {
++ struct ieee80211_tx_rate tx_rates[3];
++
+ /* ampdu length (average, per sampling interval) */
+ unsigned int ampdu_len;
+ unsigned int ampdu_packets;
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -87,6 +87,10 @@ const struct mcs_group minstrel_mcs_grou
+
+ static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
+
++static void
++minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
++ struct ieee80211_tx_rate *rate, int index,
++ bool sample, bool rtscts);
+ /*
+ * Perform EWMA (Exponentially Weighted Moving Average) calculation
+ */
+@@ -174,6 +178,17 @@ minstrel_ht_calc_tp(struct minstrel_priv
+ mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);
+ }
+
++static void
++minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
++{
++ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[0], mi->max_tp_rate,
++ false, false);
++ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[1], mi->max_tp_rate2,
++ false, true);
++ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[2], mi->max_prob_rate,
++ false, true);
++}
++
+ /*
+ * Update rate statistics and select new primary rates
+ *
+@@ -294,6 +309,7 @@ minstrel_ht_update_stats(struct minstrel
+ }
+ }
+
++ minstrel_ht_update_rates(mp, mi);
+ mi->stats_update = jiffies;
+ }
+
+@@ -332,8 +348,8 @@ minstrel_next_sample_idx(struct minstrel
+ }
+
+ static void
+-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
+- bool primary)
++minstrel_downgrade_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
++ unsigned int *idx, bool primary)
+ {
+ int group, orig_group;
+
+@@ -352,6 +368,7 @@ minstrel_downgrade_rate(struct minstrel_
+ *idx = mi->groups[group].max_tp_rate;
+ else
+ *idx = mi->groups[group].max_tp_rate2;
++ minstrel_ht_update_rates(mp, mi);
+ break;
+ }
+ }
+@@ -452,13 +469,13 @@ minstrel_ht_tx_status(void *priv, struct
+ if (rate->attempts > 30 &&
+ MINSTREL_FRAC(rate->success, rate->attempts) <
+ MINSTREL_FRAC(20, 100))
+- minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
++ minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate, true);
+
+ rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
+ if (rate2->attempts > 30 &&
+ MINSTREL_FRAC(rate2->success, rate2->attempts) <
+ MINSTREL_FRAC(20, 100))
+- minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
++ minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate2, false);
+
+ if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
+ minstrel_ht_update_stats(mp, mi);
+@@ -523,7 +540,6 @@ minstrel_calc_retransmit(struct minstrel
+ static void
+ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ struct ieee80211_tx_rate *rate, int index,
+- struct ieee80211_tx_rate_control *txrc,
+ bool sample, bool rtscts)
+ {
+ const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
+@@ -611,6 +627,7 @@ minstrel_ht_get_rate(void *priv, struct
+ struct minstrel_priv *mp = priv;
+ int sample_idx;
+ bool sample = false;
++ int last = 0;
+
+ if (rate_control_send_low(sta, priv_sta, txrc))
+ return;
+@@ -636,11 +653,10 @@ minstrel_ht_get_rate(void *priv, struct
+ if (sample_idx >= 0) {
+ sample = true;
+ minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
+- txrc, true, false);
++ true, false);
+ info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+ } else {
+- minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
+- txrc, false, false);
++ ar[0] = mi->tx_rates[0];
+ }
+
+ if (mp->hw->max_rates >= 3) {
+@@ -650,33 +666,27 @@ minstrel_ht_get_rate(void *priv, struct
+ * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
+ */
+ if (sample_idx >= 0)
+- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
+- txrc, false, false);
++ ar[1] = mi->tx_rates[0];
+ else
+- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
+- txrc, false, true);
+-
+- minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
+- txrc, false, !sample);
++ ar[1] = mi->tx_rates[1];
+
+- ar[3].count = 0;
+- ar[3].idx = -1;
++ ar[2] = mi->tx_rates[2];
++ last = 3;
+ } else if (mp->hw->max_rates == 2) {
+ /*
+ * Only 2 tx rates supported, use
+ * sample_rate -> max_prob_rate for sampling and
+ * max_tp_rate -> max_prob_rate by default.
+ */
+- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
+- txrc, false, !sample);
+-
+- ar[2].count = 0;
+- ar[2].idx = -1;
++ ar[1] = mi->tx_rates[2];
++ last = 2;
+ } else {
+ /* Not using MRR, only use the first rate */
+- ar[1].count = 0;
+- ar[1].idx = -1;
++ last = 1;
++
+ }
++ ar[last].count = 0;
++ ar[last].idx = -1;
+
+ mi->total_packets++;
+
+@@ -768,6 +778,7 @@ minstrel_ht_update_caps(void *priv, stru
+ if (!n_supported)
+ goto use_legacy;
+
++ minstrel_ht_update_rates(mp, mi);
+ return;
+
+ use_legacy:
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
-@@ -798,7 +798,7 @@ enum ieee80211_smps_mode {
+@@ -816,7 +816,7 @@ enum ieee80211_smps_mode {
*/
struct ieee80211_conf {
u32 flags;
u16 listen_interval;
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
-@@ -1568,7 +1568,7 @@ static int ieee80211_get_tx_power(struct
+@@ -1677,7 +1677,7 @@ static int ieee80211_get_tx_power(struct
{
struct ieee80211_local *local = wiphy_priv(wiphy);
}
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
-@@ -210,6 +210,7 @@ int ieee80211_hw_config(struct ieee80211
+@@ -208,6 +208,7 @@ int ieee80211_hw_config(struct ieee80211
if (local->hw.conf.power_level != power) {
changed |= IEEE80211_CONF_CHANGE_POWER;
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1714,6 +1714,8 @@ static int ath9k_config(struct ieee80211
+@@ -1684,6 +1684,8 @@ int ath9k_config(struct ieee80211_hw *hw
return -EINVAL;
}
/*
* The most recent snapshot of channel->noisefloor for the old
* channel is only available after the hardware reset. Copy it to
-@@ -1731,6 +1733,7 @@ static int ath9k_config(struct ieee80211
+@@ -1699,6 +1701,7 @@ int ath9k_config(struct ieee80211_hw *hw
+ sc->config.txpowlimit = 2 * conf->power_level;
ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow);
- ath9k_ps_restore(sc);
+ conf->cur_power_level = sc->curtxpow / 2;
}
- if (disable_radio) {
+ mutex_unlock(&sc->mutex);
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -237,6 +237,7 @@ struct ath_atx_tid {
+@@ -238,6 +238,7 @@ struct ath_atx_tid {
struct ath_node *an;
struct ath_atx_ac *ac;
unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
u16 seq_start;
u16 seq_next;
u16 baw_size;
-@@ -282,6 +283,9 @@ struct ath_tx_control {
+@@ -284,6 +285,9 @@ struct ath_tx_control {
* (axq_qnum).
*/
struct ath_tx {
spinlock_t txbuflock;
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1654,6 +1654,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1729,6 +1729,10 @@ int ath9k_init_debug(struct ath_hw *ah)
sc, &fops_wiphy);
debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_xmit);
debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -350,6 +350,14 @@ static void ath_tx_count_frames(struct a
+@@ -355,6 +355,14 @@ static void ath_tx_count_frames(struct a
}
}
static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
struct ath_buf *bf, struct list_head *bf_q,
-@@ -438,6 +446,8 @@ static void ath_tx_complete_aggr(struct
+@@ -443,6 +451,8 @@ static void ath_tx_complete_aggr(struct
__skb_queue_head_init(&bf_pending);
ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
while (bf) {
u16 seqno = bf->bf_state.seqno;
-@@ -816,6 +826,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+@@ -823,6 +833,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
ath_tx_addto_baw(sc, tid, seqno);
bf->bf_state.ndelim = ndelim;
__skb_unlink(skb, &tid->buf_q);
list_add_tail(&bf->list, bf_q);
if (bf_prev)
-@@ -1693,6 +1704,8 @@ static void ath_tx_send_ampdu(struct ath
+@@ -1682,6 +1693,8 @@ static void ath_tx_send_ampdu(struct ath
/* Add sub-frame to BAW */
ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
/* Queue to h/w without aggregation */
TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
bf->bf_lastbf = bf;
-@@ -1821,23 +1834,13 @@ error:
+@@ -1810,23 +1823,13 @@ error:
/* FIXME: tx power */
static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
/*
-@@ -1872,6 +1875,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -1861,6 +1864,7 @@ int ath_tx_start(struct ieee80211_hw *hw
struct ieee80211_vif *vif = info->control.vif;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
int padpos, padsize;
int frmlen = skb->len + FCS_LEN;
int q;
-@@ -1916,6 +1920,24 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -1903,6 +1907,24 @@ int ath_tx_start(struct ieee80211_hw *hw
setup_frame_info(hw, skb, frmlen);
/*
* At this point, the vif, hw_key and sta pointers in the tx control
* info are no longer valid (overwritten by the ath_frame_info data.
-@@ -1930,7 +1952,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+@@ -1917,7 +1939,7 @@ int ath_tx_start(struct ieee80211_hw *hw
}
spin_unlock_bh(&txq->axq_lock);
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -259,14 +259,17 @@ static void ath_tid_drain(struct ath_sof
+@@ -264,14 +264,17 @@ static void ath_tid_drain(struct ath_sof
}
static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
return;
hdr = (struct ieee80211_hdr *)skb->data;
-@@ -382,6 +385,7 @@ static void ath_tx_complete_aggr(struct
+@@ -387,6 +390,7 @@ static void ath_tx_complete_aggr(struct
int nframes;
u8 tidno;
- bool clear_filter;
+ bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
+ int i, retries;
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
-@@ -390,6 +394,10 @@ static void ath_tx_complete_aggr(struct
+@@ -395,6 +399,10 @@ static void ath_tx_complete_aggr(struct
memcpy(rates, tx_info->control.rates, sizeof(rates));
rcu_read_lock();
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
-@@ -475,7 +483,8 @@ static void ath_tx_complete_aggr(struct
+@@ -481,7 +489,8 @@ static void ath_tx_complete_aggr(struct
+ txpending = 1;
} else if (fi->retries < ATH_MAX_SW_RETRIES) {
- if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
- !an->sleeping)
+ if (txok || !an->sleeping)
- ath_tx_set_retry(sc, txq, bf->bf_mpdu);
+ ath_tx_set_retry(sc, txq, bf->bf_mpdu,
+ retries);
- clear_filter = true;
txpending = 1;
+ } else {
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -540,7 +540,7 @@ struct ath_ant_comb {
+@@ -546,7 +546,7 @@ struct ath_ant_comb {
#define DEFAULT_CACHELINE 32
#define ATH_REGCLASSIDS_MAX 10
#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1382,10 +1382,16 @@ static bool ath9k_hw_set_reset_reg(struc
+ static bool ath9k_hw_chip_reset(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+ {
+- if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
+- if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
+- return false;
+- } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
++ int reset_type = ATH9K_RESET_WARM;
++
++ if (AR_SREV_9280(ah)) {
++ if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
++ reset_type = ATH9K_RESET_POWER_ON;
++ else
++ reset_type = ATH9K_RESET_COLD;
++ }
++
++ if (!ath9k_hw_set_reset_reg(ah, reset_type))
+ return false;
+
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1371,10 +1371,16 @@ static bool ath9k_hw_set_reset_reg(struc
- static bool ath9k_hw_chip_reset(struct ath_hw *ah,
- struct ath9k_channel *chan)
- {
-- if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
-- if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
-- return false;
-- } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
-+ int reset_type = ATH9K_RESET_WARM;
-+
-+ if (AR_SREV_9280(ah)) {
-+ if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
-+ reset_type = ATH9K_RESET_POWER_ON;
-+ else
-+ reset_type = ATH9K_RESET_COLD;
-+ }
-+
-+ if (!ath9k_hw_set_reset_reg(ah, reset_type))
- return false;
-
- if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -969,34 +969,6 @@ static ssize_t read_file_recv(struct fil
+ "%18s : %10u\n", "DECRYPT BUSY ERR",
+ sc->debug.stats.rxstats.decrypt_busy_err);
+
+- len += snprintf(buf + len, size - len,
+- "%18s : %10d\n", "RSSI-CTL0",
+- sc->debug.stats.rxstats.rs_rssi_ctl0);
+-
+- len += snprintf(buf + len, size - len,
+- "%18s : %10d\n", "RSSI-CTL1",
+- sc->debug.stats.rxstats.rs_rssi_ctl1);
+-
+- len += snprintf(buf + len, size - len,
+- "%18s : %10d\n", "RSSI-CTL2",
+- sc->debug.stats.rxstats.rs_rssi_ctl2);
+-
+- len += snprintf(buf + len, size - len,
+- "%18s : %10d\n", "RSSI-EXT0",
+- sc->debug.stats.rxstats.rs_rssi_ext0);
+-
+- len += snprintf(buf + len, size - len,
+- "%18s : %10d\n", "RSSI-EXT1",
+- sc->debug.stats.rxstats.rs_rssi_ext1);
+-
+- len += snprintf(buf + len, size - len,
+- "%18s : %10d\n", "RSSI-EXT2",
+- sc->debug.stats.rxstats.rs_rssi_ext2);
+-
+- len += snprintf(buf + len, size - len,
+- "%18s : %10d\n", "Rx Antenna",
+- sc->debug.stats.rxstats.rs_antenna);
+-
+ PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
+ PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
+ PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
+@@ -1073,16 +1045,6 @@ void ath_debug_stat_rx(struct ath_softc
+ RX_PHY_ERR_INC(phyerr);
+ }
+
+- sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0;
+- sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1;
+- sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2;
+-
+- sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0;
+- sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1;
+- sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2;
+-
+- sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna;
+-
+ spin_lock(&sc->debug.samp_lock);
+ RX_SAMP_DBG(jiffies) = jiffies;
+ RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
+--- a/drivers/net/wireless/ath/ath9k/debug.h
++++ b/drivers/net/wireless/ath/ath9k/debug.h
+@@ -164,13 +164,6 @@ struct ath_rx_stats {
+ u32 post_delim_crc_err;
+ u32 decrypt_busy_err;
+ u32 phy_err_stats[ATH9K_PHYERR_MAX];
+- int8_t rs_rssi_ctl0;
+- int8_t rs_rssi_ctl1;
+- int8_t rs_rssi_ctl2;
+- int8_t rs_rssi_ext0;
+- int8_t rs_rssi_ext1;
+- int8_t rs_rssi_ext2;
+- u8 rs_antenna;
+ };
+
+ enum ath_reset_type {
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -525,8 +525,8 @@ int ath9k_hw_process_rxdesc_edma(struct
- rxs->rs_status |= ATH9K_RXERR_DECRYPT;
- else if (rxsp->status11 & AR_MichaelErr)
- rxs->rs_status |= ATH9K_RXERR_MIC;
-- else if (rxsp->status11 & AR_KeyMiss)
-- rxs->rs_status |= ATH9K_RXERR_DECRYPT;
-+ if (rxsp->status11 & AR_KeyMiss)
-+ rxs->rs_status |= ATH9K_RXERR_KEYMISS;
- }
-
- return 0;
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -620,8 +620,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
- rs->rs_status |= ATH9K_RXERR_DECRYPT;
- else if (ads.ds_rxstatus8 & AR_MichaelErr)
- rs->rs_status |= ATH9K_RXERR_MIC;
-- else if (ads.ds_rxstatus8 & AR_KeyMiss)
-- rs->rs_status |= ATH9K_RXERR_DECRYPT;
-+ if (ads.ds_rxstatus8 & AR_KeyMiss)
-+ rs->rs_status |= ATH9K_RXERR_KEYMISS;
- }
-
- return 0;
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -181,6 +181,7 @@ struct ath_htc_rx_status {
- #define ATH9K_RXERR_FIFO 0x04
- #define ATH9K_RXERR_DECRYPT 0x08
- #define ATH9K_RXERR_MIC 0x10
-+#define ATH9K_RXERR_KEYMISS 0x20
-
- #define ATH9K_RX_MORE 0x01
- #define ATH9K_RX_MORE_AGGR 0x02
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -826,7 +826,8 @@ static bool ath9k_rx_accept(struct ath_c
- test_bit(rx_stats->rs_keyix, common->tkip_keymap);
- strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
- !(rx_stats->rs_status &
-- (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));
-+ (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
-+ ATH9K_RXERR_KEYMISS));
-
- if (!rx_stats->rs_datalen)
- return false;
-@@ -854,6 +855,8 @@ static bool ath9k_rx_accept(struct ath_c
- * descriptors.
- */
- if (rx_stats->rs_status != 0) {
-+ u8 status_mask;
-+
- if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
- rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
- mic_error = false;
-@@ -861,7 +864,8 @@ static bool ath9k_rx_accept(struct ath_c
- if (rx_stats->rs_status & ATH9K_RXERR_PHY)
- return false;
-
-- if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
-+ if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
-+ (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
- *decrypt_error = true;
- mic_error = false;
- }
-@@ -871,17 +875,14 @@ static bool ath9k_rx_accept(struct ath_c
- * decryption and MIC failures. For monitor mode,
- * we also ignore the CRC error.
- */
-- if (ah->is_monitoring) {
-- if (rx_stats->rs_status &
-- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
-- ATH9K_RXERR_CRC))
-- return false;
-- } else {
-- if (rx_stats->rs_status &
-- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
-- return false;
-- }
-- }
-+ status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
-+ ATH9K_RXERR_KEYMISS;
-+
-+ if (ah->is_monitoring)
-+ status_mask |= ATH9K_RXERR_CRC;
-+
-+ if (rx_stats->rs_status & ~status_mask)
-+ return false;
- }
-
- /*
--- /dev/null
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -684,6 +684,9 @@ enum mac80211_rx_flags {
+ * @mactime: value in microseconds of the 64-bit Time Synchronization Function
+ * (TSF) timer when the first data symbol (MPDU) arrived at the hardware.
+ * @band: the active band when this frame was received
++ * @chains: bitmask of receive chains for which separate signal strength
++ * values were filled.
++ * @chain_signal: per-chain signal strength, same format as @signal
+ * @freq: frequency the radio was tuned to when receiving this frame, in MHz
+ * @signal: signal strength when receiving this frame, either in dBm, in dB or
+ * unspecified depending on the hardware capabilities flags
+@@ -697,6 +700,10 @@ enum mac80211_rx_flags {
+ struct ieee80211_rx_status {
+ u64 mactime;
+ enum ieee80211_band band;
++
++ u8 chains;
++ s8 chain_signal[4];
++
+ int freq;
+ int signal;
+ int antenna;
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -302,6 +302,11 @@ struct sta_info {
+ unsigned long rx_dropped;
+ int last_signal;
+ struct ewma avg_signal;
++
++ u8 chains;
++ s8 chain_signal_last[4];
++ struct ewma chain_signal_avg[4];
++
+ /* Plus 1 for non-QoS frames */
+ __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES + 1];
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1267,6 +1267,7 @@ ieee80211_rx_h_sta_process(struct ieee80
+ struct sk_buff *skb = rx->skb;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++ int i;
+
+ if (!sta)
+ return RX_CONTINUE;
+@@ -1309,6 +1310,19 @@ ieee80211_rx_h_sta_process(struct ieee80
+ sta->last_signal = status->signal;
+ ewma_add(&sta->avg_signal, -status->signal);
+
++ if (status->chains) {
++ sta->chains = status->chains;
++ for (i = 0; i < 4; i++) {
++ int signal = status->chain_signal[i];
++
++ if (!(status->chains & BIT(i)))
++ continue;
++
++ sta->chain_signal_last[i] = signal;
++ ewma_add(&sta->chain_signal_avg[i], -signal);
++ }
++ }
++
+ /*
+ * Change STA power saving mode only at the end of a frame
+ * exchange sequence.
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -304,6 +304,8 @@ struct sta_info *sta_info_alloc(struct i
+ do_posix_clock_monotonic_gettime(&uptime);
+ sta->last_connected = uptime.tv_sec;
+ ewma_init(&sta->avg_signal, 1024, 8);
++ for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
++ ewma_init(&sta->chain_signal_avg[i], 1024, 8);
+
+ if (sta_prepare_rate_control(local, sta, gfp)) {
+ kfree(sta);
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -505,6 +505,8 @@ struct station_parameters {
+ * @STATION_INFO_CONNECTED_TIME: @connected_time filled
+ * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled
+ * @STATION_INFO_STA_FLAGS: @sta_flags filled
++ * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled
++ * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled
+ */
+ enum station_info_flags {
+ STATION_INFO_INACTIVE_TIME = 1<<0,
+@@ -525,7 +527,9 @@ enum station_info_flags {
+ STATION_INFO_BSS_PARAM = 1<<15,
+ STATION_INFO_CONNECTED_TIME = 1<<16,
+ STATION_INFO_ASSOC_REQ_IES = 1<<17,
+- STATION_INFO_STA_FLAGS = 1<<18
++ STATION_INFO_STA_FLAGS = 1<<18,
++ STATION_INFO_CHAIN_SIGNAL = 1<<19,
++ STATION_INFO_CHAIN_SIGNAL_AVG = 1<<20,
+ };
+
+ /**
+@@ -605,6 +609,9 @@ struct sta_bss_parameters {
+ * @plink_state: mesh peer link state
+ * @signal: signal strength of last received packet in dBm
+ * @signal_avg: signal strength average in dBm
++ * @chains: bitmask for filled values in @chain_signal, @chain_signal_avg
++ * @chain_signal: per-chain signal strength of last received packet in dBm
++ * @chain_signal_avg: per-chain signal strength average in dBm
+ * @txrate: current unicast bitrate from this station
+ * @rxrate: current unicast bitrate to this station
+ * @rx_packets: packets received from this station
+@@ -635,6 +642,11 @@ struct station_info {
+ u8 plink_state;
+ s8 signal;
+ s8 signal_avg;
++
++ u8 chains;
++ s8 chain_signal[4];
++ s8 chain_signal_avg[4];
++
+ struct rate_info txrate;
+ struct rate_info rxrate;
+ u32 rx_packets;
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -133,12 +133,8 @@ struct ath_rx_status {
+ u8 rs_rate;
+ u8 rs_antenna;
+ u8 rs_more;
+- int8_t rs_rssi_ctl0;
+- int8_t rs_rssi_ctl1;
+- int8_t rs_rssi_ctl2;
+- int8_t rs_rssi_ext0;
+- int8_t rs_rssi_ext1;
+- int8_t rs_rssi_ext2;
++ int8_t rs_rssi_ctl[3];
++ int8_t rs_rssi_ext[3];
+ u8 rs_isaggr;
+ u8 rs_moreaggr;
+ u8 rs_num_delims;
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -981,6 +981,7 @@ static int ath9k_rx_skb_preprocess(struc
+ bool *decrypt_error)
+ {
+ struct ath_hw *ah = common->ah;
++ int i, j;
+
+ memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
+
+@@ -1006,6 +1007,20 @@ static int ath9k_rx_skb_preprocess(struc
+ rx_status->antenna = rx_stats->rs_antenna;
+ rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+
++ for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
++ s8 rssi;
++
++ if (!(ah->rxchainmask & BIT(i)))
++ continue;
++
++ rssi = rx_stats->rs_rssi_ctl[i];
++ if (rssi != ATH9K_RSSI_BAD) {
++ rx_status->chains |= BIT(j);
++ rx_status->chain_signal[j] = ah->noise + rssi;
++ }
++ j++;
++ }
++
+ return 0;
+ }
+
+@@ -1536,14 +1551,14 @@ static void ath_ant_comb_scan(struct ath
+ struct ath_ant_comb *antcomb = &sc->ant_comb;
+ int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
+ int curr_main_set;
+- int main_rssi = rs->rs_rssi_ctl0;
+- int alt_rssi = rs->rs_rssi_ctl1;
++ int main_rssi = rs->rs_rssi_ctl[0];
++ int alt_rssi = rs->rs_rssi_ctl[1];
+ int rx_ant_conf, main_ant_conf;
+ bool short_scan = false;
+
+- rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
++ rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
+ ATH_ANT_RX_MASK;
+- main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
++ main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
+ ATH_ANT_RX_MASK;
+
+ /* Record packet only when both main_rssi and alt_rssi is positive */
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -452,12 +452,12 @@ int ath9k_hw_process_rxdesc_edma(struct
+
+ /* XXX: Keycache */
+ rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
+- rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
+- rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
+- rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
+- rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
+- rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
+- rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
++ rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
++ rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
++ rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
++ rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
++ rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
++ rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
+
+ if (rxsp->status11 & AR_RxKeyIdxValid)
+ rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -559,25 +559,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
+
+ if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
+ rs->rs_rssi = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
+- rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
++ rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
+ } else {
+ rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+- rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
++ rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt00);
+- rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
++ rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt01);
+- rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
++ rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
+ AR_RxRSSIAnt02);
+- rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
++ rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt10);
+- rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
++ rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt11);
+- rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
++ rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
+ AR_RxRSSIAnt12);
+ }
+ if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1047,12 +1047,12 @@ void ath_debug_stat_rx(struct ath_softc
+
+ spin_lock(&sc->debug.samp_lock);
+ RX_SAMP_DBG(jiffies) = jiffies;
+- RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
+- RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl1;
+- RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl2;
+- RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext0;
+- RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext1;
+- RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext2;
++ RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl[0];
++ RX_SAMP_DBG(rssi_ctl1) = rs->rs_rssi_ctl[1];
++ RX_SAMP_DBG(rssi_ctl2) = rs->rs_rssi_ctl[2];
++ RX_SAMP_DBG(rssi_ext0) = rs->rs_rssi_ext[0];
++ RX_SAMP_DBG(rssi_ext1) = rs->rs_rssi_ext[1];
++ RX_SAMP_DBG(rssi_ext2) = rs->rs_rssi_ext[2];
+ RX_SAMP_DBG(antenna) = rs->rs_antenna;
+ RX_SAMP_DBG(rssi) = rs->rs_rssi;
+ RX_SAMP_DBG(rate) = rs->rs_rate;
+--- a/include/linux/nl80211.h
++++ b/include/linux/nl80211.h
+@@ -1621,6 +1621,8 @@ enum nl80211_sta_bss_param {
+ * containing info as possible, see &enum nl80211_sta_bss_param
+ * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected
+ * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
++ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
++ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
+ * @__NL80211_STA_INFO_AFTER_LAST: internal
+ * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ */
+@@ -1643,6 +1645,8 @@ enum nl80211_sta_info {
+ NL80211_STA_INFO_BSS_PARAM,
+ NL80211_STA_INFO_CONNECTED_TIME,
+ NL80211_STA_INFO_STA_FLAGS,
++ NL80211_STA_INFO_CHAIN_SIGNAL,
++ NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
+
+ /* keep last */
+ __NL80211_STA_INFO_AFTER_LAST,
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -2287,6 +2287,33 @@ nla_put_failure:
+ return false;
+ }
+
++static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
++ int id)
++{
++ void *attr;
++ int i = 0;
++
++ if (!mask)
++ return true;
++
++ attr = nla_nest_start(msg, id);
++ if (!attr)
++ goto nla_put_failure;
++
++ for (i = 0; i < 4; i++) {
++ if (!(mask & BIT(i)))
++ continue;
++
++ NLA_PUT_U8(msg, i, signal[i]);
++ }
++
++ nla_nest_end(msg, attr);
++
++ return true;
++nla_put_failure:
++ return false;
++}
++
+ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
+ int flags, struct net_device *dev,
+ const u8 *mac_addr, struct station_info *sinfo)
+@@ -2333,6 +2360,18 @@ static int nl80211_send_station(struct s
+ if (sinfo->filled & STATION_INFO_SIGNAL_AVG)
+ NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
+ sinfo->signal_avg);
++ if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) {
++ if (!nl80211_put_signal(msg, sinfo->chains,
++ sinfo->chain_signal,
++ NL80211_STA_INFO_CHAIN_SIGNAL))
++ goto nla_put_failure;
++ }
++ if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) {
++ if (!nl80211_put_signal(msg, sinfo->chains,
++ sinfo->chain_signal_avg,
++ NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
++ goto nla_put_failure;
++ }
+ if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+ if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
+ NL80211_STA_INFO_TX_BITRATE))
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -330,6 +330,7 @@ static void sta_set_sinfo(struct sta_inf
+ {
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+ struct timespec uptime;
++ int i;
+
+ sinfo->generation = sdata->local->sta_generation;
+
+@@ -365,6 +366,17 @@ static void sta_set_sinfo(struct sta_inf
+ sinfo->signal = (s8)sta->last_signal;
+ sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
+ }
++ if (sta->chains) {
++ sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
++ STATION_INFO_CHAIN_SIGNAL_AVG;
++
++ sinfo->chains = sta->chains;
++ for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
++ sinfo->chain_signal[i] = sta->chain_signal_last[i];
++ sinfo->chain_signal_avg[i] =
++ (s8) -ewma_read(&sta->chain_signal_avg[i]);
++ }
++ }
+
+ sinfo->txrate.flags = 0;
+ if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -425,12 +425,9 @@ void ath_rx_cleanup(struct ath_softc *sc
-
- u32 ath_calcrxfilter(struct ath_softc *sc)
- {
--#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
--
- u32 rfilt;
-
-- rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE)
-- | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
-+ rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
- | ATH9K_RX_FILTER_MCAST;
-
- if (sc->rx.rxfilter & FIF_PROBE_REQ)
---- a/drivers/net/wireless/ath/ath9k/ani.c
-+++ b/drivers/net/wireless/ath/ath9k/ani.c
-@@ -502,9 +502,6 @@ static void ath9k_ani_reset_old(struct a
- ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
- ATH9K_ANI_CCK_WEAK_SIG_THR);
-
-- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
-- ATH9K_RX_FILTER_PHYERR);
--
- ath9k_ani_restart(ah);
- return;
- }
-@@ -525,8 +522,6 @@ static void ath9k_ani_reset_old(struct a
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel);
-
-- ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
-- ~ATH9K_RX_FILTER_PHYERR);
- ath9k_ani_restart(ah);
-
- ENABLE_REGWRITE_BUFFER(ah);
+++ /dev/null
---- a/net/mac80211/rc80211_minstrel_ht.h
-+++ b/net/mac80211/rc80211_minstrel_ht.h
-@@ -70,6 +70,8 @@ struct minstrel_mcs_group_data {
- };
-
- struct minstrel_ht_sta {
-+ struct ieee80211_tx_rate tx_rates[3];
-+
- /* ampdu length (average, per sampling interval) */
- unsigned int ampdu_len;
- unsigned int ampdu_packets;
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -87,6 +87,10 @@ const struct mcs_group minstrel_mcs_grou
-
- static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
-
-+static void
-+minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+ struct ieee80211_tx_rate *rate, int index,
-+ bool sample, bool rtscts);
- /*
- * Perform EWMA (Exponentially Weighted Moving Average) calculation
- */
-@@ -174,6 +178,17 @@ minstrel_ht_calc_tp(struct minstrel_priv
- mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);
- }
-
-+static void
-+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
-+{
-+ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[0], mi->max_tp_rate,
-+ false, false);
-+ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[1], mi->max_tp_rate2,
-+ false, true);
-+ minstrel_ht_set_rate(mp, mi, &mi->tx_rates[2], mi->max_prob_rate,
-+ false, true);
-+}
-+
- /*
- * Update rate statistics and select new primary rates
- *
-@@ -292,6 +307,7 @@ minstrel_ht_update_stats(struct minstrel
- }
- }
-
-+ minstrel_ht_update_rates(mp, mi);
- mi->stats_update = jiffies;
- }
-
-@@ -330,8 +346,8 @@ minstrel_next_sample_idx(struct minstrel
- }
-
- static void
--minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
-- bool primary)
-+minstrel_downgrade_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+ unsigned int *idx, bool primary)
- {
- int group, orig_group;
-
-@@ -350,6 +366,7 @@ minstrel_downgrade_rate(struct minstrel_
- *idx = mi->groups[group].max_tp_rate;
- else
- *idx = mi->groups[group].max_tp_rate2;
-+ minstrel_ht_update_rates(mp, mi);
- break;
- }
- }
-@@ -450,13 +467,13 @@ minstrel_ht_tx_status(void *priv, struct
- if (rate->attempts > 30 &&
- MINSTREL_FRAC(rate->success, rate->attempts) <
- MINSTREL_FRAC(20, 100))
-- minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
-+ minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate, true);
-
- rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
- if (rate2->attempts > 30 &&
- MINSTREL_FRAC(rate2->success, rate2->attempts) <
- MINSTREL_FRAC(20, 100))
-- minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
-+ minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate2, false);
-
- if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
- minstrel_ht_update_stats(mp, mi);
-@@ -521,7 +538,6 @@ minstrel_calc_retransmit(struct minstrel
- static void
- minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
- struct ieee80211_tx_rate *rate, int index,
-- struct ieee80211_tx_rate_control *txrc,
- bool sample, bool rtscts)
- {
- const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
-@@ -609,6 +625,7 @@ minstrel_ht_get_rate(void *priv, struct
- struct minstrel_priv *mp = priv;
- int sample_idx;
- bool sample = false;
-+ int last = 0;
-
- if (rate_control_send_low(sta, priv_sta, txrc))
- return;
-@@ -634,11 +651,10 @@ minstrel_ht_get_rate(void *priv, struct
- if (sample_idx >= 0) {
- sample = true;
- minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
-- txrc, true, false);
-+ true, false);
- info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
- } else {
-- minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
-- txrc, false, false);
-+ ar[0] = mi->tx_rates[0];
- }
-
- if (mp->hw->max_rates >= 3) {
-@@ -648,33 +664,27 @@ minstrel_ht_get_rate(void *priv, struct
- * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
- */
- if (sample_idx >= 0)
-- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
-- txrc, false, false);
-+ ar[1] = mi->tx_rates[0];
- else
-- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
-- txrc, false, true);
--
-- minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
-- txrc, false, !sample);
-+ ar[1] = mi->tx_rates[1];
-
-- ar[3].count = 0;
-- ar[3].idx = -1;
-+ ar[2] = mi->tx_rates[2];
-+ last = 3;
- } else if (mp->hw->max_rates == 2) {
- /*
- * Only 2 tx rates supported, use
- * sample_rate -> max_prob_rate for sampling and
- * max_tp_rate -> max_prob_rate by default.
- */
-- minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
-- txrc, false, !sample);
--
-- ar[2].count = 0;
-- ar[2].idx = -1;
-+ ar[1] = mi->tx_rates[2];
-+ last = 2;
- } else {
- /* Not using MRR, only use the first rate */
-- ar[1].count = 0;
-- ar[1].idx = -1;
-+ last = 1;
-+
- }
-+ ar[last].count = 0;
-+ ar[last].idx = -1;
-
- mi->total_packets++;
-
-@@ -766,6 +776,7 @@ minstrel_ht_update_caps(void *priv, stru
- if (!n_supported)
- goto use_legacy;
-
-+ minstrel_ht_update_rates(mp, mi);
- return;
-
- use_legacy:
+++ /dev/null
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -2370,6 +2370,25 @@ static inline int ieee80211_sta_ps_trans
- void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
-
- /**
-+ * ieee80211_tx_status_sta - transmit status callback
-+ *
-+ * Call this function for all transmitted frames after they have been
-+ * transmitted. It is permissible to not call this function for
-+ * multicast frames but this can affect statistics.
-+ *
-+ * This function may not be called in IRQ context. Calls to this function
-+ * for a single hardware must be synchronized against each other. Calls
-+ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
-+ * may not be mixed for a single hardware.
-+ *
-+ * @hw: the hardware the frame was transmitted by
-+ * @skb: the frame that was transmitted, owned by mac80211 after this call
-+ * @sta: station for which the tx status is provided
-+ */
-+void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
-+ struct ieee80211_sta *sta);
-+
-+/**
- * ieee80211_tx_status - transmit status callback
- *
- * Call this function for all transmitted frames after they have been
-@@ -2384,8 +2403,11 @@ void ieee80211_sta_set_tim(struct ieee80
- * @hw: the hardware the frame was transmitted by
- * @skb: the frame that was transmitted, owned by mac80211 after this call
- */
--void ieee80211_tx_status(struct ieee80211_hw *hw,
-- struct sk_buff *skb);
-+static inline void ieee80211_tx_status(struct ieee80211_hw *hw,
-+ struct sk_buff *skb)
-+{
-+ ieee80211_tx_status_sta(hw, skb, NULL);
-+}
-
- /**
- * ieee80211_tx_status_ni - transmit status callback (in process context)
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -202,7 +202,8 @@ static void ieee80211_set_bar_pending(st
- */
- #define STA_LOST_PKT_THRESHOLD 50
-
--void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
-+void ieee80211_tx_status_sta(struct ieee80211_hw *hw, struct sk_buff *skb,
-+ struct ieee80211_sta *pubsta)
- {
- struct sk_buff *skb2;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-@@ -214,7 +215,7 @@ void ieee80211_tx_status(struct ieee8021
- struct ieee80211_tx_status_rtap_hdr *rthdr;
- struct ieee80211_sub_if_data *sdata;
- struct net_device *prev_dev = NULL;
-- struct sta_info *sta, *tmp;
-+ struct sta_info *sta = NULL, *tmp, *tmp2;
- int retry_count = -1, i;
- int rates_idx = -1;
- bool send_to_cooked;
-@@ -244,11 +245,19 @@ void ieee80211_tx_status(struct ieee8021
- sband = local->hw.wiphy->bands[info->band];
- fc = hdr->frame_control;
-
-- for_each_sta_info(local, hdr->addr1, sta, tmp) {
-- /* skip wrong virtual interface */
-- if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
-- continue;
-+ if (!pubsta) {
-+ for_each_sta_info(local, hdr->addr1, tmp, tmp2) {
-+ /* skip wrong virtual interface */
-+ if (memcmp(hdr->addr2, tmp->sdata->vif.addr, ETH_ALEN))
-+ continue;
-+
-+ sta = tmp;
-+ }
-+ } else {
-+ sta = container_of(pubsta, struct sta_info, sta);
-+ }
-
-+ if (sta) {
- acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
- if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) {
- /*
-@@ -497,7 +506,7 @@ void ieee80211_tx_status(struct ieee8021
- rcu_read_unlock();
- dev_kfree_skb(skb);
- }
--EXPORT_SYMBOL(ieee80211_tx_status);
-+EXPORT_SYMBOL(ieee80211_tx_status_sta);
-
- void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets)
- {
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -50,10 +50,12 @@ static u16 bits_per_symbol[][2] = {
- static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_atx_tid *tid, struct sk_buff *skb);
- static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-- int tx_flags, struct ath_txq *txq);
-+ int tx_flags, struct ath_txq *txq,
-+ struct ieee80211_sta *sta);
- static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_txq *txq, struct list_head *bf_q,
-- struct ath_tx_status *ts, int txok, int sendbar);
-+ struct ath_tx_status *ts, int txok, int sendbar,
-+ struct ieee80211_sta *sta);
- static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
- struct list_head *head, bool internal);
- static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
-@@ -172,7 +174,8 @@ static void ath_tx_flush_tid(struct ath_
- if (bf && fi->retries) {
- list_add_tail(&bf->list, &bf_head);
- ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
-- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
-+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0,
-+ 1, NULL);
- } else {
- ath_tx_send_normal(sc, txq, NULL, skb);
- }
-@@ -239,7 +242,7 @@ static void ath_tid_drain(struct ath_sof
-
- if (!bf) {
- spin_unlock(&txq->axq_lock);
-- ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
-+ ath_tx_complete(sc, skb, ATH_TX_ERROR, txq, NULL);
- spin_lock(&txq->axq_lock);
- continue;
- }
-@@ -250,7 +253,7 @@ static void ath_tid_drain(struct ath_sof
- ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
-
- spin_unlock(&txq->axq_lock);
-- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0, NULL);
- spin_lock(&txq->axq_lock);
- }
-
-@@ -412,7 +415,7 @@ static void ath_tx_complete_aggr(struct
- list_move_tail(&bf->list, &bf_head);
-
- ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
-- 0, 0);
-+ 0, 0, NULL);
-
- bf = bf_next;
- }
-@@ -520,7 +523,7 @@ static void ath_tx_complete_aggr(struct
- }
-
- ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
-- !txfail, sendbar);
-+ !txfail, sendbar, sta);
- } else {
- /* retry the un-acked ones */
- if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
-@@ -540,7 +543,8 @@ static void ath_tx_complete_aggr(struct
-
- ath_tx_complete_buf(sc, bf, txq,
- &bf_head,
-- ts, 0, 1);
-+ ts, 0, 1,
-+ sta);
- break;
- }
-
-@@ -1465,7 +1469,8 @@ static void ath_drain_txq_list(struct at
- ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
- retry_tx);
- else
-- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
-+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0,
-+ NULL);
- spin_lock_bh(&txq->axq_lock);
- }
- }
-@@ -1970,7 +1975,8 @@ int ath_tx_start(struct ieee80211_hw *hw
- /*****************/
-
- static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-- int tx_flags, struct ath_txq *txq)
-+ int tx_flags, struct ath_txq *txq,
-+ struct ieee80211_sta *sta)
- {
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-@@ -2028,7 +2034,8 @@ static void ath_tx_complete(struct ath_s
-
- static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
- struct ath_txq *txq, struct list_head *bf_q,
-- struct ath_tx_status *ts, int txok, int sendbar)
-+ struct ath_tx_status *ts, int txok, int sendbar,
-+ struct ieee80211_sta *sta)
- {
- struct sk_buff *skb = bf->bf_mpdu;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-@@ -2056,7 +2063,7 @@ static void ath_tx_complete_buf(struct a
- complete(&sc->paprd_complete);
- } else {
- ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
-- ath_tx_complete(sc, skb, tx_flags, txq);
-+ ath_tx_complete(sc, skb, tx_flags, txq, sta);
- }
- /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
- * accidentally reference it later.
-@@ -2145,7 +2152,7 @@ static void ath_tx_process_buffer(struct
-
- if (!bf_isampdu(bf)) {
- ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
-- ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
-+ ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0, NULL);
- } else
- ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -1512,7 +1512,8 @@ bool ath_drain_all_txq(struct ath_softc
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_txq *txq;
-- int i, npend = 0;
-+ int i;
-+ u32 npend = 0;
-
- if (sc->sc_flags & SC_OP_INVALID)
- return true;
-@@ -1524,11 +1525,12 @@ bool ath_drain_all_txq(struct ath_softc
- if (!ATH_TXQ_SETUP(sc, i))
- continue;
-
-- npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
-+ if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
-+ npend |= BIT(i);
- }
-
- if (npend)
-- ath_err(common, "Failed to stop TX DMA!\n");
-+ ath_err(common, "Failed to stop TX DMA, queues=%08x!\n", npend);
-
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (!ATH_TXQ_SETUP(sc, i))
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/debug.h
-+++ b/drivers/net/wireless/ath/ath9k/debug.h
-@@ -25,8 +25,10 @@ struct ath_buf;
-
- #ifdef CONFIG_ATH9K_DEBUGFS
- #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
-+#define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++
- #else
- #define TX_STAT_INC(q, c) do { } while (0)
-+#define RESET_STAT_INC(sc, type) do { } while (0)
- #endif
-
- #ifdef CONFIG_ATH9K_DEBUGFS
-@@ -171,10 +173,21 @@ struct ath_rx_stats {
- u8 rs_antenna;
- };
-
-+enum ath_reset_type {
-+ RESET_TYPE_BB_HANG,
-+ RESET_TYPE_BB_WATCHDOG,
-+ RESET_TYPE_FATAL_INT,
-+ RESET_TYPE_TX_ERROR,
-+ RESET_TYPE_TX_HANG,
-+ RESET_TYPE_PLL_HANG,
-+ __RESET_TYPE_MAX
-+};
-+
- struct ath_stats {
- struct ath_interrupt_stats istats;
- struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
- struct ath_rx_stats rxstats;
-+ u32 reset[__RESET_TYPE_MAX];
- };
-
- #define ATH_DBG_MAX_SAMPLES 10
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -679,6 +679,16 @@ void ath9k_tasklet(unsigned long data)
-
- if ((status & ATH9K_INT_FATAL) ||
- (status & ATH9K_INT_BB_WATCHDOG)) {
-+#ifdef CONFIG_ATH9K_DEBUGFS
-+ enum ath_reset_type type;
-+
-+ if (status & ATH9K_INT_FATAL)
-+ type = RESET_TYPE_FATAL_INT;
-+ else
-+ type = RESET_TYPE_BB_WATCHDOG;
-+
-+ RESET_STAT_INC(sc, type);
-+#endif
- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
- goto out;
- }
-@@ -995,8 +1005,10 @@ void ath_hw_check(struct work_struct *wo
- ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
- "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
- if (busy >= 99) {
-- if (++sc->hw_busy_count >= 3)
-+ if (++sc->hw_busy_count >= 3) {
-+ RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);
- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
-+ }
-
- } else if (busy >= 0)
- sc->hw_busy_count = 0;
-@@ -1016,6 +1028,7 @@ static void ath_hw_pll_rx_hang_check(str
- /* Rx is hung for more than 500ms. Reset it */
- ath_dbg(common, ATH_DBG_RESET,
- "Possible RX hang, resetting");
-+ RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
- count = 0;
- }
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -587,8 +587,10 @@ static void ath_tx_complete_aggr(struct
-
- rcu_read_unlock();
-
-- if (needreset)
-+ if (needreset) {
-+ RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
-+ }
- }
-
- static bool ath_lookup_legacy(struct ath_buf *bf)
-@@ -2270,6 +2272,7 @@ static void ath_tx_complete_poll_work(st
- if (needreset) {
- ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
- "tx hung, resetting the chip\n");
-+ RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
- ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
- }
-
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -523,9 +523,22 @@ static ssize_t read_file_wiphy(struct fi
- if (tmp & ATH9K_RX_FILTER_PHYRADAR)
- len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
- if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
-- len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n");
-- else
-- len += snprintf(buf + len, sizeof(buf) - len, "\n");
-+ len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
-+
-+ len += snprintf(buf + len, sizeof(buf) - len,
-+ "\n\nReset causes:\n"
-+ " baseband hang: %d\n"
-+ " baseband watchdog: %d\n"
-+ " fatal hardware error interrupt: %d\n"
-+ " tx hardware error: %d\n"
-+ " tx path hang: %d\n"
-+ " pll rx hang: %d\n",
-+ sc->debug.stats.reset[RESET_TYPE_BB_HANG],
-+ sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG],
-+ sc->debug.stats.reset[RESET_TYPE_FATAL_INT],
-+ sc->debug.stats.reset[RESET_TYPE_TX_ERROR],
-+ sc->debug.stats.reset[RESET_TYPE_TX_HANG],
-+ sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
-
- if (len > sizeof(buf))
- len = sizeof(buf);
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -387,7 +387,6 @@ static void ath_tx_complete_aggr(struct
- struct ath_frame_info *fi;
- int nframes;
- u8 tidno;
-- bool clear_filter;
- int i, retries;
-
- skb = bf->bf_mpdu;
-@@ -484,12 +483,10 @@ static void ath_tx_complete_aggr(struct
- */
- txfail = 1;
- } else if (fi->retries < ATH_MAX_SW_RETRIES) {
-- if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
-- !an->sleeping)
-+ if (txok || !an->sleeping)
- ath_tx_set_retry(sc, txq, bf->bf_mpdu,
- retries);
-
-- clear_filter = true;
- txpending = 1;
- } else {
- txfail = 1;
-@@ -568,11 +565,13 @@ static void ath_tx_complete_aggr(struct
- ieee80211_sta_set_tim(sta);
-
- spin_lock_bh(&txq->axq_lock);
-- if (clear_filter)
-- tid->ac->clear_ps_filter = true;
- skb_queue_splice(&bf_pending, &tid->buf_q);
-- if (!an->sleeping)
-+ if (!an->sleeping) {
- ath_tx_queue_tid(txq, tid);
-+
-+ if (ts->ts_status & ATH9K_TXERR_FILT)
-+ tid->ac->clear_ps_filter = true;
-+ }
- spin_unlock_bh(&txq->axq_lock);
- }
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -75,9 +75,10 @@
- #define ATH9K_TXERR_XTXOP 0x08
- #define ATH9K_TXERR_TIMER_EXPIRED 0x10
- #define ATH9K_TX_ACKED 0x20
-+#define ATH9K_TX_FLUSH 0x40
- #define ATH9K_TXERR_MASK \
- (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \
-- ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED)
-+ ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED | ATH9K_TX_FLUSH)
-
- #define ATH9K_TX_BA 0x01
- #define ATH9K_TX_PWRMGMT 0x02
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -388,6 +388,7 @@ static void ath_tx_complete_aggr(struct
- int nframes;
- u8 tidno;
- int i, retries;
-+ bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
-
- skb = bf->bf_mpdu;
- hdr = (struct ieee80211_hdr *)skb->data;
-@@ -482,6 +483,8 @@ static void ath_tx_complete_aggr(struct
- * the un-acked sub-frames
- */
- txfail = 1;
-+ } else if (flush) {
-+ txpending = 1;
- } else if (fi->retries < ATH_MAX_SW_RETRIES) {
- if (txok || !an->sleeping)
- ath_tx_set_retry(sc, txq, bf->bf_mpdu,
-@@ -540,7 +543,8 @@ static void ath_tx_complete_aggr(struct
-
- ath_tx_complete_buf(sc, bf, txq,
- &bf_head,
-- ts, 0, 1,
-+ ts, 0,
-+ !flush,
- sta);
- break;
- }
-@@ -1446,6 +1450,7 @@ static void ath_drain_txq_list(struct at
- struct ath_tx_status ts;
-
- memset(&ts, 0, sizeof(ts));
-+ ts.ts_status = ATH9K_TX_FLUSH;
- INIT_LIST_HEAD(&bf_head);
-
- while (!list_empty(list)) {
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -515,7 +515,7 @@ static void ath_beacon_config_ap(struct
- sc->sc_flags |= SC_OP_TSF_RESET;
- ath9k_beacon_init(sc, nexttbtt, intval);
- sc->beacon.bmisscnt = 0;
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- ath9k_hw_enable_interrupts(ah);
- }
-
-@@ -643,7 +643,7 @@ static void ath_beacon_config_sta(struct
- ath9k_hw_set_sta_beacon_timers(ah, &bs);
- ah->imask |= ATH9K_INT_BMISS;
-
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- ath9k_hw_enable_interrupts(ah);
- }
-
-@@ -679,7 +679,7 @@ static void ath_beacon_config_adhoc(stru
- ath9k_beacon_init(sc, nexttbtt, intval);
- sc->beacon.bmisscnt = 0;
-
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- ath9k_hw_enable_interrupts(ah);
- }
-
-@@ -821,11 +821,11 @@ void ath9k_set_beaconing_status(struct a
- if (status) {
- /* Re-enable beaconing */
- ah->imask |= ATH9K_INT_SWBA;
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- } else {
- /* Disable SWBA interrupt */
- ah->imask &= ~ATH9K_INT_SWBA;
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- tasklet_kill(&sc->bcon_tasklet);
- ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
- }
---- a/drivers/net/wireless/ath/ath9k/gpio.c
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -151,7 +151,7 @@ static void ath9k_gen_timer_start(struct
- if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
- ath9k_hw_disable_interrupts(ah);
- ah->imask |= ATH9K_INT_GENTIMER;
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- ath9k_hw_enable_interrupts(ah);
- }
- }
-@@ -166,7 +166,7 @@ static void ath9k_gen_timer_stop(struct
- if (timer_table->timer_mask.val == 0) {
- ath9k_hw_disable_interrupts(ah);
- ah->imask &= ~ATH9K_INT_GENTIMER;
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- ath9k_hw_enable_interrupts(ah);
- }
- }
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -273,7 +273,7 @@ static bool ath_complete_reset(struct at
-
- ath9k_cmn_update_txpow(ah, sc->curtxpow,
- sc->config.txpowlimit, &sc->curtxpow);
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- ath9k_hw_enable_interrupts(ah);
-
- if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
-@@ -833,7 +833,7 @@ irqreturn_t ath_isr(int irq, void *dev)
-
- if (status & ATH9K_INT_RXEOL) {
- ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- }
-
- if (status & ATH9K_INT_MIB) {
-@@ -1409,7 +1409,7 @@ static void ath9k_calculate_summary_stat
- ah->imask &= ~ATH9K_INT_TSFOOR;
- }
-
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
-
- /* Set up ANI */
- if (iter_data.naps > 0) {
-@@ -1566,7 +1566,7 @@ static void ath9k_enable_ps(struct ath_s
- if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
- if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) {
- ah->imask |= ATH9K_INT_TIM_TIMER;
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- }
- ath9k_hw_setrxabort(ah, 1);
- }
-@@ -1586,7 +1586,7 @@ static void ath9k_disable_ps(struct ath_
- PS_WAIT_FOR_TX_ACK);
- if (ah->imask & ATH9K_INT_TIM_TIMER) {
- ah->imask &= ~ATH9K_INT_TIM_TIMER;
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- }
- }
-
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -1974,7 +1974,7 @@ requeue:
-
- if (!(ah->imask & ATH9K_INT_RXEOL)) {
- ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
-- ath9k_hw_set_interrupts(ah, ah->imask);
-+ ath9k_hw_set_interrupts(ah);
- }
-
- return 0;
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -827,9 +827,9 @@ void ath9k_hw_enable_interrupts(struct a
- }
- EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
-
--void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
-+void ath9k_hw_set_interrupts(struct ath_hw *ah)
- {
-- enum ath9k_int omask = ah->imask;
-+ enum ath9k_int ints = ah->imask;
- u32 mask, mask2;
- struct ath9k_hw_capabilities *pCap = &ah->caps;
- struct ath_common *common = ath9k_hw_common(ah);
-@@ -837,7 +837,7 @@ void ath9k_hw_set_interrupts(struct ath_
- if (!(ints & ATH9K_INT_GLOBAL))
- ath9k_hw_disable_interrupts(ah);
-
-- ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
-+ ath_dbg(common, ATH_DBG_INTERRUPT, "New interrupt mask 0x%x\n", ints);
-
- mask = ints & ATH9K_INT_COMMON;
- mask2 = 0;
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -735,7 +735,7 @@ int ath9k_hw_beaconq_setup(struct ath_hw
-
- /* Interrupt Handling */
- bool ath9k_hw_intrpend(struct ath_hw *ah);
--void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
-+void ath9k_hw_set_interrupts(struct ath_hw *ah);
- void ath9k_hw_enable_interrupts(struct ath_hw *ah);
- void ath9k_hw_disable_interrupts(struct ath_hw *ah);
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath.h
-+++ b/drivers/net/wireless/ath/ath.h
-@@ -71,7 +71,6 @@ struct ath_regulatory {
- char alpha2[2];
- u16 country_code;
- u16 max_power_level;
-- u32 tp_scale;
- u16 current_rd;
- u16 current_rd_ext;
- int16_t power_limit;
---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-@@ -3040,6 +3040,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(st
- return (pBase->miscConfiguration >> 0x3) & 0x1;
- case EEP_ANT_DIV_CTL1:
- return eep->base_ext1.ant_div_control;
-+ case EEP_ANTENNA_GAIN_5G:
-+ return eep->modalHeader5G.antennaGain;
-+ case EEP_ANTENNA_GAIN_2G:
-+ return eep->modalHeader2G.antennaGain;
- default:
- return 0;
- }
-@@ -4727,20 +4731,14 @@ static u16 ar9003_hw_get_max_edge_power(
- static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
- struct ath9k_channel *chan,
- u8 *pPwrArray, u16 cfgCtl,
-- u8 twiceAntennaReduction,
-- u8 twiceMaxRegulatoryPower,
-+ u8 antenna_reduction,
- u16 powerLimit)
- {
-- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- struct ath_common *common = ath9k_hw_common(ah);
- struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
- u16 twiceMaxEdgePower = MAX_RATE_POWER;
-- static const u16 tpScaleReductionTable[5] = {
-- 0, 3, 6, 9, MAX_RATE_POWER
-- };
- int i;
-- int16_t twiceLargestAntenna;
-- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-+ u16 scaledPower = 0, minCtlPower;
- static const u16 ctlModesFor11a[] = {
- CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
- };
-@@ -4758,28 +4756,7 @@ static void ar9003_hw_set_power_per_rate
- bool is2ghz = IS_CHAN_2GHZ(chan);
-
- ath9k_hw_get_channel_centers(ah, chan, ¢ers);
--
-- /* Compute TxPower reduction due to Antenna Gain */
-- if (is2ghz)
-- twiceLargestAntenna = pEepData->modalHeader2G.antennaGain;
-- else
-- twiceLargestAntenna = pEepData->modalHeader5G.antennaGain;
--
-- twiceLargestAntenna = (int16_t)min((twiceAntennaReduction) -
-- twiceLargestAntenna, 0);
--
-- /*
-- * scaledPower is the minimum of the user input power level
-- * and the regulatory allowed power level
-- */
-- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
--
-- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
-- maxRegAllowedPower -=
-- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
-- }
--
-- scaledPower = min(powerLimit, maxRegAllowedPower);
-+ scaledPower = powerLimit - antenna_reduction;
-
- /*
- * Reduce scaled Power by number of chains active to get
-@@ -4966,7 +4943,6 @@ static inline u8 mcsidx_to_tgtpwridx(uns
- static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
- struct ath9k_channel *chan, u16 cfgCtl,
- u8 twiceAntennaReduction,
-- u8 twiceMaxRegulatoryPower,
- u8 powerLimit, bool test)
- {
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
-@@ -5019,7 +4995,6 @@ static void ath9k_hw_ar9300_set_txpower(
- ar9003_hw_set_power_per_rate_table(ah, chan,
- targetPowerValT2, cfgCtl,
- twiceAntennaReduction,
-- twiceMaxRegulatoryPower,
- powerLimit);
-
- if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -429,7 +429,6 @@ static void ath9k_hw_init_defaults(struc
-
- regulatory->country_code = CTRY_DEFAULT;
- regulatory->power_limit = MAX_RATE_POWER;
-- regulatory->tp_scale = ATH9K_TP_SCALE_MAX;
-
- ah->hw_version.magic = AR5416_MAGIC;
- ah->hw_version.subvendorid = 0;
-@@ -1396,9 +1395,7 @@ static bool ath9k_hw_chip_reset(struct a
- static bool ath9k_hw_channel_change(struct ath_hw *ah,
- struct ath9k_channel *chan)
- {
-- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- struct ath_common *common = ath9k_hw_common(ah);
-- struct ieee80211_channel *channel = chan->chan;
- u32 qnum;
- int r;
-
-@@ -1423,14 +1420,7 @@ static bool ath9k_hw_channel_change(stru
- return false;
- }
- ath9k_hw_set_clockrate(ah);
--
-- ah->eep_ops->set_txpower(ah, chan,
-- ath9k_regd_get_ctl(regulatory, chan),
-- channel->max_antenna_gain * 2,
-- channel->max_power * 2,
-- min((u32) MAX_RATE_POWER,
-- (u32) regulatory->power_limit), false);
--
-+ ath9k_hw_apply_txpower(ah, chan);
- ath9k_hw_rfbus_done(ah);
-
- if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
-@@ -2466,23 +2456,56 @@ bool ath9k_hw_disable(struct ath_hw *ah)
- }
- EXPORT_SYMBOL(ath9k_hw_disable);
-
-+static int get_antenna_gain(struct ath_hw *ah, struct ath9k_channel *chan)
-+{
-+ enum eeprom_param gain_param;
-+
-+ if (IS_CHAN_2GHZ(chan))
-+ gain_param = EEP_ANTENNA_GAIN_2G;
-+ else
-+ gain_param = EEP_ANTENNA_GAIN_5G;
-+
-+ return ah->eep_ops->get_eeprom(ah, gain_param);
-+}
-+
-+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
-+{
-+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
-+ struct ieee80211_channel *channel;
-+ int chan_pwr, new_pwr, max_gain;
-+ int ant_gain, ant_reduction = 0;
-+
-+ if (!chan)
-+ return;
-+
-+ channel = chan->chan;
-+ chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
-+ new_pwr = min_t(int, chan_pwr, reg->power_limit);
-+ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
-+
-+ ant_gain = get_antenna_gain(ah, chan);
-+ if (ant_gain > max_gain)
-+ ant_reduction = ant_gain - max_gain;
-+
-+ ah->eep_ops->set_txpower(ah, chan,
-+ ath9k_regd_get_ctl(reg, chan),
-+ ant_reduction, new_pwr, false);
-+}
-+
- void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
- {
-- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
-+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
- struct ath9k_channel *chan = ah->curchan;
- struct ieee80211_channel *channel = chan->chan;
-- int reg_pwr = min_t(int, MAX_RATE_POWER, limit);
-- int chan_pwr = channel->max_power * 2;
-
-+ reg->power_limit = min_t(int, limit, MAX_RATE_POWER);
- if (test)
-- reg_pwr = chan_pwr = MAX_RATE_POWER;
-+ channel->max_power = MAX_RATE_POWER / 2;
-
-- regulatory->power_limit = reg_pwr;
-+ ath9k_hw_apply_txpower(ah, chan);
-
-- ah->eep_ops->set_txpower(ah, chan,
-- ath9k_regd_get_ctl(regulatory, chan),
-- channel->max_antenna_gain * 2,
-- chan_pwr, reg_pwr, test);
-+ if (test)
-+ channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
- }
- EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
-
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -389,14 +389,6 @@ enum ath9k_power_mode {
- ATH9K_PM_UNDEFINED
- };
-
--enum ath9k_tp_scale {
-- ATH9K_TP_SCALE_MAX = 0,
-- ATH9K_TP_SCALE_50,
-- ATH9K_TP_SCALE_25,
-- ATH9K_TP_SCALE_12,
-- ATH9K_TP_SCALE_MIN
--};
--
- enum ser_reg_mode {
- SER_REG_MODE_OFF = 0,
- SER_REG_MODE_ON = 1,
-@@ -964,6 +956,7 @@ void ath9k_hw_htc_resetinit(struct ath_h
- /* PHY */
- void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
- u32 *coef_mantissa, u32 *coef_exponent);
-+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
-
- /*
- * Code Specific to AR5008, AR9001 or AR9002,
---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-@@ -350,6 +350,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct
- return pModal->antdiv_ctl1;
- case EEP_TXGAIN_TYPE:
- return pBase->txGainType;
-+ case EEP_ANTENNA_GAIN_2G:
-+ return pModal->antennaGainCh[0];
- default:
- return 0;
- }
-@@ -462,8 +464,7 @@ static void ath9k_hw_set_4k_power_per_ra
- struct ath9k_channel *chan,
- int16_t *ratesArray,
- u16 cfgCtl,
-- u16 AntennaReduction,
-- u16 twiceMaxRegulatoryPower,
-+ u16 antenna_reduction,
- u16 powerLimit)
- {
- #define CMP_TEST_GRP \
-@@ -472,20 +473,16 @@ static void ath9k_hw_set_4k_power_per_ra
- || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
- ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
-
-- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- int i;
-- int16_t twiceLargestAntenna;
- u16 twiceMinEdgePower;
- u16 twiceMaxEdgePower = MAX_RATE_POWER;
-- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-+ u16 scaledPower = 0, minCtlPower;
- u16 numCtlModes;
- const u16 *pCtlMode;
- u16 ctlMode, freq;
- struct chan_centers centers;
- struct cal_ctl_data_4k *rep;
- struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
-- static const u16 tpScaleReductionTable[5] =
-- { 0, 3, 6, 9, MAX_RATE_POWER };
- struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
- 0, { 0, 0, 0, 0}
- };
-@@ -503,19 +500,7 @@ static void ath9k_hw_set_4k_power_per_ra
-
- ath9k_hw_get_channel_centers(ah, chan, ¢ers);
-
-- twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
-- twiceLargestAntenna = (int16_t)min(AntennaReduction -
-- twiceLargestAntenna, 0);
--
-- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
-- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
-- maxRegAllowedPower -=
-- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
-- }
--
-- scaledPower = min(powerLimit, maxRegAllowedPower);
-- scaledPower = max((u16)0, scaledPower);
--
-+ scaledPower = powerLimit - antenna_reduction;
- numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
- pCtlMode = ctlModesFor11g;
-
-@@ -671,7 +656,6 @@ static void ath9k_hw_4k_set_txpower(stru
- struct ath9k_channel *chan,
- u16 cfgCtl,
- u8 twiceAntennaReduction,
-- u8 twiceMaxRegulatoryPower,
- u8 powerLimit, bool test)
- {
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
-@@ -691,7 +675,6 @@ static void ath9k_hw_4k_set_txpower(stru
- ath9k_hw_set_4k_power_per_rate_table(ah, chan,
- &ratesArray[0], cfgCtl,
- twiceAntennaReduction,
-- twiceMaxRegulatoryPower,
- powerLimit);
-
- ath9k_hw_set_4k_power_cal_table(ah, chan);
---- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-@@ -336,6 +336,9 @@ static u32 ath9k_hw_ar9287_get_eeprom(st
- return pBase->tempSensSlopePalOn;
- else
- return 0;
-+ case EEP_ANTENNA_GAIN_2G:
-+ return max_t(u8, pModal->antennaGainCh[0],
-+ pModal->antennaGainCh[1]);
- default:
- return 0;
- }
-@@ -554,8 +557,7 @@ static void ath9k_hw_set_ar9287_power_pe
- struct ath9k_channel *chan,
- int16_t *ratesArray,
- u16 cfgCtl,
-- u16 AntennaReduction,
-- u16 twiceMaxRegulatoryPower,
-+ u16 antenna_reduction,
- u16 powerLimit)
- {
- #define CMP_CTL \
-@@ -569,12 +571,8 @@ static void ath9k_hw_set_ar9287_power_pe
- #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
- #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
-
-- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- u16 twiceMaxEdgePower = MAX_RATE_POWER;
-- static const u16 tpScaleReductionTable[5] =
-- { 0, 3, 6, 9, MAX_RATE_POWER };
- int i;
-- int16_t twiceLargestAntenna;
- struct cal_ctl_data_ar9287 *rep;
- struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
- targetPowerCck = {0, {0, 0, 0, 0} };
-@@ -582,7 +580,7 @@ static void ath9k_hw_set_ar9287_power_pe
- targetPowerCckExt = {0, {0, 0, 0, 0} };
- struct cal_target_power_ht targetPowerHt20,
- targetPowerHt40 = {0, {0, 0, 0, 0} };
-- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-+ u16 scaledPower = 0, minCtlPower;
- static const u16 ctlModesFor11g[] = {
- CTL_11B, CTL_11G, CTL_2GHT20,
- CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40
-@@ -597,24 +595,7 @@ static void ath9k_hw_set_ar9287_power_pe
- tx_chainmask = ah->txchainmask;
-
- ath9k_hw_get_channel_centers(ah, chan, ¢ers);
--
-- /* Compute TxPower reduction due to Antenna Gain */
-- twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
-- pEepData->modalHeader.antennaGainCh[1]);
-- twiceLargestAntenna = (int16_t)min((AntennaReduction) -
-- twiceLargestAntenna, 0);
--
-- /*
-- * scaledPower is the minimum of the user input power level
-- * and the regulatory allowed power level.
-- */
-- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
--
-- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX)
-- maxRegAllowedPower -=
-- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
--
-- scaledPower = min(powerLimit, maxRegAllowedPower);
-+ scaledPower = powerLimit - antenna_reduction;
-
- /*
- * Reduce scaled Power by number of chains active
-@@ -815,7 +796,6 @@ static void ath9k_hw_set_ar9287_power_pe
- static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
- struct ath9k_channel *chan, u16 cfgCtl,
- u8 twiceAntennaReduction,
-- u8 twiceMaxRegulatoryPower,
- u8 powerLimit, bool test)
- {
- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
-@@ -834,7 +814,6 @@ static void ath9k_hw_ar9287_set_txpower(
- ath9k_hw_set_ar9287_power_per_rate_table(ah, chan,
- &ratesArray[0], cfgCtl,
- twiceAntennaReduction,
-- twiceMaxRegulatoryPower,
- powerLimit);
-
- ath9k_hw_set_ar9287_power_cal_table(ah, chan);
---- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
-@@ -400,6 +400,7 @@ static u32 ath9k_hw_def_get_eeprom(struc
- struct ar5416_eeprom_def *eep = &ah->eeprom.def;
- struct modal_eep_header *pModal = eep->modalHeader;
- struct base_eep_header *pBase = &eep->baseEepHeader;
-+ int band = 0;
-
- switch (param) {
- case EEP_NFTHRESH_5:
-@@ -467,6 +468,14 @@ static u32 ath9k_hw_def_get_eeprom(struc
- return pBase->pwr_table_offset;
- else
- return AR5416_PWR_TABLE_OFFSET_DB;
-+ case EEP_ANTENNA_GAIN_2G:
-+ band = 1;
-+ /* fall through */
-+ case EEP_ANTENNA_GAIN_5G:
-+ return max_t(u8, max_t(u8,
-+ pModal[band].antennaGainCh[0],
-+ pModal[band].antennaGainCh[1]),
-+ pModal[band].antennaGainCh[2]);
- default:
- return 0;
- }
-@@ -986,21 +995,15 @@ static void ath9k_hw_set_def_power_per_r
- struct ath9k_channel *chan,
- int16_t *ratesArray,
- u16 cfgCtl,
-- u16 AntennaReduction,
-- u16 twiceMaxRegulatoryPower,
-+ u16 antenna_reduction,
- u16 powerLimit)
- {
- #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
- #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */
-
-- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
- u16 twiceMaxEdgePower = MAX_RATE_POWER;
-- static const u16 tpScaleReductionTable[5] =
-- { 0, 3, 6, 9, MAX_RATE_POWER };
--
- int i;
-- int16_t twiceLargestAntenna;
- struct cal_ctl_data *rep;
- struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
- 0, { 0, 0, 0, 0}
-@@ -1012,7 +1015,7 @@ static void ath9k_hw_set_def_power_per_r
- struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
- 0, {0, 0, 0, 0}
- };
-- u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
-+ u16 scaledPower = 0, minCtlPower;
- static const u16 ctlModesFor11a[] = {
- CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40
- };
-@@ -1031,27 +1034,7 @@ static void ath9k_hw_set_def_power_per_r
-
- ath9k_hw_get_channel_centers(ah, chan, ¢ers);
-
-- twiceLargestAntenna = max(
-- pEepData->modalHeader
-- [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
-- pEepData->modalHeader
-- [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
--
-- twiceLargestAntenna = max((u8)twiceLargestAntenna,
-- pEepData->modalHeader
-- [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
--
-- twiceLargestAntenna = (int16_t)min(AntennaReduction -
-- twiceLargestAntenna, 0);
--
-- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
--
-- if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) {
-- maxRegAllowedPower -=
-- (tpScaleReductionTable[(regulatory->tp_scale)] * 2);
-- }
--
-- scaledPower = min(powerLimit, maxRegAllowedPower);
-+ scaledPower = powerLimit - antenna_reduction;
-
- switch (ar5416_get_ntxchains(tx_chainmask)) {
- case 1:
-@@ -1256,7 +1239,6 @@ static void ath9k_hw_def_set_txpower(str
- struct ath9k_channel *chan,
- u16 cfgCtl,
- u8 twiceAntennaReduction,
-- u8 twiceMaxRegulatoryPower,
- u8 powerLimit, bool test)
- {
- #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
-@@ -1278,7 +1260,6 @@ static void ath9k_hw_def_set_txpower(str
- ath9k_hw_set_def_power_per_rate_table(ah, chan,
- &ratesArray[0], cfgCtl,
- twiceAntennaReduction,
-- twiceMaxRegulatoryPower,
- powerLimit);
-
- ath9k_hw_set_def_power_cal_table(ah, chan);
---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-@@ -763,10 +763,8 @@ static void ar5008_hw_set_channel_regs(s
- static int ar5008_hw_process_ini(struct ath_hw *ah,
- struct ath9k_channel *chan)
- {
-- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- struct ath_common *common = ath9k_hw_common(ah);
- int i, regWrites = 0;
-- struct ieee80211_channel *channel = chan->chan;
- u32 modesIndex, freqIndex;
-
- switch (chan->chanmode) {
-@@ -903,14 +901,7 @@ static int ar5008_hw_process_ini(struct
- ar5008_hw_set_channel_regs(ah, chan);
- ar5008_hw_init_chain_masks(ah);
- ath9k_olc_init(ah);
--
-- /* Set TX power */
-- ah->eep_ops->set_txpower(ah, chan,
-- ath9k_regd_get_ctl(regulatory, chan),
-- channel->max_antenna_gain * 2,
-- channel->max_power * 2,
-- min((u32) MAX_RATE_POWER,
-- (u32) regulatory->power_limit), false);
-+ ath9k_hw_apply_txpower(ah, chan);
-
- /* Write analog registers */
- if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
---- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-@@ -19,7 +19,6 @@
-
- void ar9003_paprd_enable(struct ath_hw *ah, bool val)
- {
-- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- struct ath9k_channel *chan = ah->curchan;
- struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
-
-@@ -54,13 +53,7 @@ void ar9003_paprd_enable(struct ath_hw *
-
- if (val) {
- ah->paprd_table_write_done = true;
--
-- ah->eep_ops->set_txpower(ah, chan,
-- ath9k_regd_get_ctl(regulatory, chan),
-- chan->chan->max_antenna_gain * 2,
-- chan->chan->max_power * 2,
-- min((u32) MAX_RATE_POWER,
-- (u32) regulatory->power_limit), false);
-+ ath9k_hw_apply_txpower(ah, chan);
- }
-
- REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -628,9 +628,7 @@ static void ar9003_hw_prog_ini(struct at
- static int ar9003_hw_process_ini(struct ath_hw *ah,
- struct ath9k_channel *chan)
- {
-- struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
- unsigned int regWrites = 0, i;
-- struct ieee80211_channel *channel = chan->chan;
- u32 modesIndex;
-
- switch (chan->chanmode) {
-@@ -683,14 +681,7 @@ static int ar9003_hw_process_ini(struct
- ar9003_hw_override_ini(ah);
- ar9003_hw_set_channel_regs(ah, chan);
- ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
--
-- /* Set TX power */
-- ah->eep_ops->set_txpower(ah, chan,
-- ath9k_regd_get_ctl(regulatory, chan),
-- channel->max_antenna_gain * 2,
-- channel->max_power * 2,
-- min((u32) MAX_RATE_POWER,
-- (u32) regulatory->power_limit), false);
-+ ath9k_hw_apply_txpower(ah, chan);
-
- return 0;
- }
---- a/drivers/net/wireless/ath/ath9k/common.c
-+++ b/drivers/net/wireless/ath/ath9k/common.c
-@@ -161,10 +161,12 @@ EXPORT_SYMBOL(ath9k_cmn_count_streams);
- void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
- u16 new_txpow, u16 *txpower)
- {
-- if (cur_txpow != new_txpow) {
-+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
-+
-+ if (reg->power_limit != new_txpow) {
- ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
- /* read back in case value is clamped */
-- *txpower = ath9k_hw_regulatory(ah)->power_limit;
-+ *txpower = reg->max_power_level;
- }
- }
- EXPORT_SYMBOL(ath9k_cmn_update_txpow);
---- a/drivers/net/wireless/ath/ath9k/eeprom.h
-+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
-@@ -253,7 +253,9 @@ enum eeprom_param {
- EEP_PAPRD,
- EEP_MODAL_VER,
- EEP_ANT_DIV_CTL1,
-- EEP_CHAIN_MASK_REDUCE
-+ EEP_CHAIN_MASK_REDUCE,
-+ EEP_ANTENNA_GAIN_2G,
-+ EEP_ANTENNA_GAIN_5G
- };
-
- enum ar5416_rates {
-@@ -657,8 +659,7 @@ struct eeprom_ops {
- void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
- void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
- u16 cfgCtl, u8 twiceAntennaReduction,
-- u8 twiceMaxRegulatoryPower, u8 powerLimit,
-- bool test);
-+ u8 powerLimit, bool test);
- u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
- };
-
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -626,7 +626,6 @@ static void ath9k_init_band_txpower(stru
- struct ieee80211_supported_band *sband;
- struct ieee80211_channel *chan;
- struct ath_hw *ah = sc->sc_ah;
-- struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
- int i;
-
- sband = &sc->sbands[band];
-@@ -635,7 +634,6 @@ static void ath9k_init_band_txpower(stru
- ah->curchan = &ah->channels[chan->hw_value];
- ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
- ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
-- chan->max_power = reg->max_power_level / 2;
- }
- }
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath.h
-+++ b/drivers/net/wireless/ath/ath.h
-@@ -72,7 +72,6 @@ struct ath_regulatory {
- u16 country_code;
- u16 max_power_level;
- u16 current_rd;
-- u16 current_rd_ext;
- int16_t power_limit;
- struct reg_dmn_pair_mapping *regpair;
- };
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2047,11 +2047,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw
- eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0);
- regulatory->current_rd = eeval;
-
-- eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1);
-- if (AR_SREV_9285_12_OR_LATER(ah))
-- eeval |= AR9285_RDEXT_DEFAULT;
-- regulatory->current_rd_ext = eeval;
--
- if (ah->opmode != NL80211_IFTYPE_AP &&
- ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) {
- if (regulatory->current_rd == 0x64 ||
---- a/drivers/net/wireless/ath/carl9170/main.c
-+++ b/drivers/net/wireless/ath/carl9170/main.c
-@@ -1912,7 +1912,6 @@ static int carl9170_parse_eeprom(struct
- ar->hw->channel_change_time = 80 * 1000;
-
- regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
-- regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
-
- /* second part of wiphy init */
- SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
-@@ -415,8 +415,6 @@ static u32 ath9k_hw_def_get_eeprom(struc
- return get_unaligned_be16(pBase->macAddr + 4);
- case EEP_REG_0:
- return pBase->regDmn[0];
-- case EEP_REG_1:
-- return pBase->regDmn[1];
- case EEP_OP_CAP:
- return pBase->deviceCap;
- case EEP_OP_MODE:
---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-@@ -322,8 +322,6 @@ static u32 ath9k_hw_4k_get_eeprom(struct
- return get_unaligned_be16(pBase->macAddr + 4);
- case EEP_REG_0:
- return pBase->regDmn[0];
-- case EEP_REG_1:
-- return pBase->regDmn[1];
- case EEP_OP_CAP:
- return pBase->deviceCap;
- case EEP_OP_MODE:
---- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-@@ -308,8 +308,6 @@ static u32 ath9k_hw_ar9287_get_eeprom(st
- return get_unaligned_be16(pBase->macAddr + 4);
- case EEP_REG_0:
- return pBase->regDmn[0];
-- case EEP_REG_1:
-- return pBase->regDmn[1];
- case EEP_OP_CAP:
- return pBase->deviceCap;
- case EEP_OP_MODE:
---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-@@ -3014,8 +3014,6 @@ static u32 ath9k_hw_ar9300_get_eeprom(st
- return get_unaligned_be16(eep->macAddr + 4);
- case EEP_REG_0:
- return le16_to_cpu(pBase->regDmn[0]);
-- case EEP_REG_1:
-- return le16_to_cpu(pBase->regDmn[1]);
- case EEP_OP_CAP:
- return pBase->deviceCap;
- case EEP_OP_MODE:
---- a/drivers/net/wireless/ath/ath9k/eeprom.h
-+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
-@@ -225,7 +225,6 @@ enum eeprom_param {
- EEP_MAC_MID,
- EEP_MAC_LSW,
- EEP_REG_0,
-- EEP_REG_1,
- EEP_OP_CAP,
- EEP_OP_MODE,
- EEP_RF_SILENT,
/*
* Capabilities
-@@ -960,6 +962,11 @@ struct rt2x00_dev {
+@@ -961,6 +963,11 @@ struct rt2x00_dev {
const struct firmware *fw;
/*
.get_entry_state = rt2800pci_get_entry_state,
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -1142,6 +1142,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
- INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
- INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
+@@ -1145,6 +1145,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ BIT(NL80211_IFTYPE_WDS);
+ retval = rt2x00lib_load_eeprom_file(rt2x00dev);
+ if (retval)
+ goto exit;
+
/*
- * Let the driver probe the device to detect the capabilities.
+ * Initialize work.
*/
-@@ -1243,6 +1247,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
+@@ -1261,6 +1265,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
* Free queue structures.
*/
rt2x00queue_free(rt2x00dev);
--- a/config.mk
+++ b/config.mk
-@@ -574,6 +574,7 @@ CONFIG_RT2X00=y
+@@ -567,6 +567,7 @@ CONFIG_RT2X00=y
CONFIG_RT2X00_LIB=m
CONFIG_RT2800_LIB=m
CONFIG_RT2X00_LIB_FIRMWARE=y
--- /dev/null
+--- a/drivers/net/wireless/rt2x00/rt2800pci.c
++++ b/drivers/net/wireless/rt2x00/rt2800pci.c
+@@ -84,7 +84,7 @@ static void rt2800pci_mcu_status(struct
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ }
+
+-static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
++static void rt2800pci_read_eeprom_file(struct rt2x00_dev *rt2x00dev)
+ {
+ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, EEPROM_SIZE);
+ }
+@@ -938,8 +938,9 @@ static int rt2800pci_validate_eeprom(str
+ /*
+ * Read EEPROM into buffer
+ */
+- if (rt2x00_is_soc(rt2x00dev))
+- rt2800pci_read_eeprom_soc(rt2x00dev);
++ if (rt2x00_is_soc(rt2x00dev) ||
++ test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags))
++ rt2800pci_read_eeprom_file(rt2x00dev);
+ else if (rt2800pci_efuse_detect(rt2x00dev))
+ rt2800pci_read_eeprom_efuse(rt2x00dev);
+ else
+--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
++++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
+@@ -255,6 +255,7 @@ exit:
+ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
+ {
+ struct ieee80211_hw *hw;
++ struct rt2x00_platform_data *pdata;
+ struct rt2x00_dev *rt2x00dev;
+ int retval;
+
+@@ -299,6 +300,12 @@ int rt2x00pci_probe(struct pci_dev *pci_
+ rt2x00dev->irq = pci_dev->irq;
+ rt2x00dev->name = pci_name(pci_dev);
+
++ /* if we get passed the name of a eeprom_file_name, then use this in
++ favour of the eeprom */
++ pdata = rt2x00dev->dev->platform_data;
++ if (pdata && pdata->eeprom_file_name)
++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
++
+ if (pci_is_pcie(pci_dev))
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
+ else
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
-@@ -5192,6 +5192,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+@@ -5193,6 +5193,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
-@@ -753,6 +753,7 @@ struct b43_wldev {
+@@ -791,6 +791,7 @@ struct b43_wldev {
bool qos_enabled; /* TRUE, if QoS is used. */
bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
bool use_pio; /* TRUE if next init should use PIO */
static int modparam_bad_frames_preempt;
module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
MODULE_PARM_DESC(bad_frames_preempt,
-@@ -2679,10 +2684,10 @@ static int b43_gpio_init(struct b43_wlde
+@@ -2686,10 +2691,10 @@ static int b43_gpio_init(struct b43_wlde
& ~B43_MACCTL_GPOUTSMSK);
b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK)
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
-@@ -1886,9 +1886,11 @@ static void b43_do_interrupt_thread(stru
+@@ -1893,9 +1893,11 @@ static void b43_do_interrupt_thread(stru
dma_reason[4], dma_reason[5]);
b43err(dev->wl, "This device does not support DMA "
"on your system. It will now be switched to PIO.\n");
--- /dev/null
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -1535,7 +1535,7 @@ static void b43_write_beacon_template(st
+ len, ram_offset, shm_size_offset, rate);
+
+ /* Write the PHY TX control parameters. */
+- antenna = B43_ANTENNA_DEFAULT;
++ antenna = dev->tx_antenna;
+ antenna = b43_antenna_to_phyctl(antenna);
+ ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
+ /* We can't send beacons with short preamble. Would get PHY errors. */
+@@ -3052,8 +3052,8 @@ static int b43_chip_init(struct b43_wlde
+
+ /* Select the antennae */
+ if (phy->ops->set_rx_antenna)
+- phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
+- b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
++ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
++ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+
+ if (phy->type == B43_PHYTYPE_B) {
+ value16 = b43_read16(dev, 0x005E);
+@@ -3782,7 +3782,6 @@ static int b43_op_config(struct ieee8021
+ struct b43_wldev *dev;
+ struct b43_phy *phy;
+ struct ieee80211_conf *conf = &hw->conf;
+- int antenna;
+ int err = 0;
+ bool reload_bss = false;
+
+@@ -3836,11 +3835,9 @@ static int b43_op_config(struct ieee8021
+ }
+
+ /* Antennas for RX and management frame TX. */
+- antenna = B43_ANTENNA_DEFAULT;
+- b43_mgmtframe_txantenna(dev, antenna);
+- antenna = B43_ANTENNA_DEFAULT;
++ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+ if (phy->ops->set_rx_antenna)
+- phy->ops->set_rx_antenna(dev, antenna);
++ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
+
+ if (wl->radio_enabled != phy->radio_on) {
+ if (wl->radio_enabled) {
+@@ -4910,6 +4907,47 @@ static int b43_op_get_survey(struct ieee
+ return 0;
+ }
+
++static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
++{
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++ struct b43_wldev *dev = wl->current_dev;
++
++ if (tx_ant == 1 && rx_ant == 1) {
++ dev->tx_antenna = B43_ANTENNA0;
++ dev->rx_antenna = B43_ANTENNA0;
++ }
++ else if (tx_ant == 2 && rx_ant == 2) {
++ dev->tx_antenna = B43_ANTENNA1;
++ dev->rx_antenna = B43_ANTENNA1;
++ }
++ else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) {
++ dev->tx_antenna = B43_ANTENNA_DEFAULT;
++ dev->rx_antenna = B43_ANTENNA_DEFAULT;
++ }
++ else {
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++
++static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
++{
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++ struct b43_wldev *dev = wl->current_dev;
++
++ switch (dev->tx_antenna) {
++ case B43_ANTENNA0:
++ *tx_ant = 1; *rx_ant = 1; break;
++ case B43_ANTENNA1:
++ *tx_ant = 2; *rx_ant = 2; break;
++ case B43_ANTENNA_DEFAULT:
++ *tx_ant = 3; *rx_ant = 3; break;
++ }
++ return 0;
++}
++
+ static const struct ieee80211_ops b43_hw_ops = {
+ .tx = b43_op_tx,
+ .conf_tx = b43_op_conf_tx,
+@@ -4931,6 +4969,8 @@ static const struct ieee80211_ops b43_hw
+ .sw_scan_complete = b43_op_sw_scan_complete_notifier,
+ .get_survey = b43_op_get_survey,
+ .rfkill_poll = b43_rfkill_poll,
++ .set_antenna = b43_op_set_antenna,
++ .get_antenna = b43_op_get_antenna,
+ };
+
+ /* Hard-reset the chip. Do not call this directly.
+@@ -5177,6 +5217,8 @@ static int b43_one_core_attach(struct b4
+ if (!wldev)
+ goto out;
+
++ wldev->rx_antenna = B43_ANTENNA_DEFAULT;
++ wldev->tx_antenna = B43_ANTENNA_DEFAULT;
+ wldev->use_pio = b43_modparam_pio;
+ wldev->dev = dev;
+ wldev->wl = wl;
+@@ -5264,6 +5306,9 @@ static struct b43_wl *b43_wireless_init(
+ BIT(NL80211_IFTYPE_WDS) |
+ BIT(NL80211_IFTYPE_ADHOC);
+
++ hw->wiphy->available_antennas_rx = 0x3;
++ hw->wiphy->available_antennas_tx = 0x3;
++
+ hw->queues = modparam_qos ? 4 : 1;
+ wl->mac80211_initially_registered_queues = hw->queues;
+ hw->max_rates = 2;
+--- a/drivers/net/wireless/b43/b43.h
++++ b/drivers/net/wireless/b43/b43.h
+@@ -792,6 +792,8 @@ struct b43_wldev {
+ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
+ bool use_pio; /* TRUE if next init should use PIO */
+ int gpiomask; /* GPIO LED mask as a module parameter */
++ int rx_antenna; /* Used RX antenna (B43_ANTENNAxxx) */
++ int tx_antenna; /* Used TX antenna (B43_ANTENNAxxx) */
+
+ /* PHY/Radio device. */
+ struct b43_phy phy;
--- /dev/null
+--- a/drivers/net/wireless/p54/p54spi.c
++++ b/drivers/net/wireless/p54/p54spi.c
+@@ -656,6 +656,7 @@ static int __devinit p54spi_probe(struct
+ init_completion(&priv->fw_comp);
+ INIT_LIST_HEAD(&priv->tx_pending);
+ mutex_init(&priv->mutex);
++ spin_lock_init(&priv->tx_lock);
+ SET_IEEE80211_DEV(hw, &spi->dev);
+ priv->common.open = p54spi_op_start;
+ priv->common.stop = p54spi_op_stop;
--- /dev/null
+--- a/drivers/net/wireless/p54/p54spi.c
++++ b/drivers/net/wireless/p54/p54spi.c
+@@ -581,11 +581,7 @@ static void p54spi_op_stop(struct ieee80
+ struct p54s_priv *priv = dev->priv;
+ unsigned long flags;
+
+- if (mutex_lock_interruptible(&priv->mutex)) {
+- /* FIXME: how to handle this error? */
+- return;
+- }
+-
++ mutex_lock(&priv->mutex);
+ WARN_ON(priv->fw_state != FW_STATE_READY);
+
+ cancel_work_sync(&priv->work);
--- /dev/null
+--- a/drivers/net/wireless/p54/p54spi.c
++++ b/drivers/net/wireless/p54/p54spi.c
+@@ -584,8 +584,6 @@ static void p54spi_op_stop(struct ieee80
+ mutex_lock(&priv->mutex);
+ WARN_ON(priv->fw_state != FW_STATE_READY);
+
+- cancel_work_sync(&priv->work);
+-
+ p54spi_power_off(priv);
+ spin_lock_irqsave(&priv->tx_lock, flags);
+ INIT_LIST_HEAD(&priv->tx_pending);
+@@ -593,6 +591,8 @@ static void p54spi_op_stop(struct ieee80
+
+ priv->fw_state = FW_STATE_OFF;
+ mutex_unlock(&priv->mutex);
++
++ cancel_work_sync(&priv->work);
+ }
+
+ static int __devinit p54spi_probe(struct spi_device *spi)