mac80211: backport latest version from trunk (as of r28137)
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Wed, 31 Aug 2011 09:44:02 +0000 (09:44 +0000)
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Wed, 31 Aug 2011 09:44:02 +0000 (09:44 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@28138 3c298f89-4303-0410-b956-a3cf2f4a3e73

79 files changed:
package/hostapd/files/hostapd.sh
package/mac80211/Makefile
package/mac80211/files/b43-fwcutter-fw-dirname.patch [new file with mode: 0644]
package/mac80211/files/lib/wifi/mac80211.sh
package/mac80211/patches/000-disable_ethernet.patch [new file with mode: 0644]
package/mac80211/patches/001-disable_b44.patch
package/mac80211/patches/002-disable_rfkill.patch
package/mac80211/patches/005-disable_ssb_build.patch
package/mac80211/patches/006-disable_bcma_build.patch
package/mac80211/patches/007-remove_misc_drivers.patch
package/mac80211/patches/010-no_pcmcia.patch
package/mac80211/patches/011-no_sdio.patch
package/mac80211/patches/013-disable_b43_nphy.patch
package/mac80211/patches/015-remove-rt2x00-options.patch
package/mac80211/patches/017-remove_ath9k_rc.patch
package/mac80211/patches/018-revert_printk_va_format.patch
package/mac80211/patches/019-remove_ath5k_pci_option.patch
package/mac80211/patches/020-netlink_seq.patch [deleted file]
package/mac80211/patches/022-atomic64_backport.patch
package/mac80211/patches/110-disable_usb_compat.patch
package/mac80211/patches/120-pr_fmt_warnings.patch
package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch
package/mac80211/patches/300-pending_work.patch
package/mac80211/patches/310-ibss_ht.patch
package/mac80211/patches/400-ath_move_debug_code.patch [new file with mode: 0644]
package/mac80211/patches/402-ath9k_blink_default.patch
package/mac80211/patches/403-ath9k-fix-invalid-mac-address-handling.patch
package/mac80211/patches/406-regd_no_assoc_hints.patch
package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch
package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch
package/mac80211/patches/430-ath5k_disable_fast_cc.patch
package/mac80211/patches/440-ath5k_calibrate_srev_checks.patch [deleted file]
package/mac80211/patches/441-ath5k_synth_voltage_srev_check.patch [deleted file]
package/mac80211/patches/442-ath5k_spur_channel_srev_check.patch [deleted file]
package/mac80211/patches/443-ath5k_initialize_clockrate.patch [deleted file]
package/mac80211/patches/444-ath5k_delay_calibration.patch [deleted file]
package/mac80211/patches/445-ath5k_fix_mac_clock_restore.patch [deleted file]
package/mac80211/patches/446-ath5k_disable_32khz_clock.patch [deleted file]
package/mac80211/patches/447-ath5k_fix_queue_stop_warning.patch [deleted file]
package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
package/mac80211/patches/511-ath9k_increase_bcbuf.patch
package/mac80211/patches/512-ath9k_reduce_rxbuf.patch
package/mac80211/patches/513-ath9k_channelbw_debugfs.patch
package/mac80211/patches/530-ath9k_noise_dbm_fixup.patch [deleted file]
package/mac80211/patches/530-mac80211_cur_txpower.patch [moved from package/mac80211/patches/550-mac80211_cur_txpower.patch with 87% similarity]
package/mac80211/patches/531-ath9k_cur_txpower.patch [moved from package/mac80211/patches/555-ath9k_cur_txpower.patch with 89% similarity]
package/mac80211/patches/540-ath9k_rx_stop.patch [deleted file]
package/mac80211/patches/540-ath9k_txkeyidx_u8.patch [new file with mode: 0644]
package/mac80211/patches/541-ath9k_aggr_queue_cleanup.patch [new file with mode: 0644]
package/mac80211/patches/542-ath9k_move_seqno.patch [new file with mode: 0644]
package/mac80211/patches/543-ath9k_move_seqno_alloc.patch [new file with mode: 0644]
package/mac80211/patches/544-ath9k_defer_buffer_setup.patch [new file with mode: 0644]
package/mac80211/patches/545-ath9k_aggr_padding_fix.patch [new file with mode: 0644]
package/mac80211/patches/546-ath9k_retry_cache_sync.patch [new file with mode: 0644]
package/mac80211/patches/550-ath9k_limit_qlen.patch [new file with mode: 0644]
package/mac80211/patches/551-ath9k_initialize_chainmask.patch [deleted file]
package/mac80211/patches/551-ath9k_sw_retry_reduce.patch [new file with mode: 0644]
package/mac80211/patches/552-ath9k_remove_tx_indexoffset.patch [deleted file]
package/mac80211/patches/553-ath9k_fix_rate_power.patch [deleted file]
package/mac80211/patches/554-ath9k_test_txpower.patch [deleted file]
package/mac80211/patches/560-ath9k_ps_tx_aggr_fix.patch [deleted file]
package/mac80211/patches/560-mac80211_defer_bar_tx.patch [new file with mode: 0644]
package/mac80211/patches/570-ath9k_fix_ack_cts_timeout.patch [new file with mode: 0644]
package/mac80211/patches/580-ath9k_remove_common_chainmask.patch [new file with mode: 0644]
package/mac80211/patches/581-ath9k_use_reset_work.patch [new file with mode: 0644]
package/mac80211/patches/582-ath9k_merge_reset_functions.patch [new file with mode: 0644]
package/mac80211/patches/583-ath9k_antenna_control.patch [new file with mode: 0644]
package/mac80211/patches/590-ath9k_fix_5ghz_adc_cal.patch [new file with mode: 0644]
package/mac80211/patches/591-ath9k_cleanup_rx_status_rate.patch [new file with mode: 0644]
package/mac80211/patches/592-ath9k_strip_initvals.patch [new file with mode: 0644]
package/mac80211/patches/593-ath9k_ar9280_cold_reset.patch [new file with mode: 0644]
package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch
package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
package/mac80211/patches/604-rt2x00-add-CONFIG_RT2X00_LIB_EEPROM-option.patch
package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
package/mac80211/patches/800-b43-gpio-mask-module-option.patch
package/mac80211/patches/810-b43_no_pio.patch
package/mac80211/patches/860-b43_restart_config.patch [deleted file]

index 29d8c72..3fbe734 100644 (file)
@@ -192,16 +192,52 @@ hostapd_set_bss_options() {
        fi
 }
 
+hostapd_set_log_options() {
+       local var="$1"
+       local cfg="$2"
+       local log_level log_80211 log_8021x log_radius log_wpa log_driver log_iapp log_mlme
+
+       config_get log_level "$cfg" log_level 2
+
+       config_get_bool log_80211  "$cfg" log_80211  1
+       config_get_bool log_8021x  "$cfg" log_8021x  1
+       config_get_bool log_radius "$cfg" log_radius 1
+       config_get_bool log_wpa    "$cfg" log_wpa    1
+       config_get_bool log_driver "$cfg" log_driver 1
+       config_get_bool log_iapp   "$cfg" log_iapp   1
+       config_get_bool log_mlme   "$cfg" log_mlme   1
+
+       local log_mask=$((       \
+               ($log_80211  << 0) | \
+               ($log_8021x  << 1) | \
+               ($log_radius << 2) | \
+               ($log_wpa    << 3) | \
+               ($log_driver << 4) | \
+               ($log_iapp   << 5) | \
+               ($log_mlme   << 6)   \
+       ))
+
+       append "$var" "logger_syslog=$log_mask" "$N"
+       append "$var" "logger_syslog_level=$log_level" "$N"
+       append "$var" "logger_stdout=$log_mask" "$N"
+       append "$var" "logger_stdout_level=$log_level" "$N"
+}
+
 hostapd_setup_vif() {
        local vif="$1"
        local driver="$2"
+       local ifname device channel hwmode
+
        hostapd_cfg=
 
-       hostapd_set_bss_options hostapd_cfg "$vif"
        config_get ifname "$vif" ifname
        config_get device "$vif" device
        config_get channel "$device" channel
        config_get hwmode "$device" hwmode
+
+       hostapd_set_log_options hostapd_cfg "$device"
+       hostapd_set_bss_options hostapd_cfg "$vif"
+
        case "$hwmode" in
                *bg|*gdt|*gst|*fh) hwmode=g;;
                *adt|*ast) hwmode=a;;
index 1043504..1a04695 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2007-2010 OpenWrt.org
+# Copyright (C) 2007-2011 OpenWrt.org
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
@@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=mac80211
 
-PKG_VERSION:=2011-06-22
-PKG_RELEASE:=2
+PKG_VERSION:=2011-08-26
+PKG_RELEASE:=1
 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
-PKG_MD5SUM:=3ffdd5cecedcf4236f599bdbc55ba10d
+PKG_MD5SUM:=37218b56e8a30b351662087d68948825
 
 PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
@@ -856,7 +856,7 @@ define KernelPackage/b43/config
 
        choice
                prompt "b43 firmware version"
-               default B43_FW_4_150
+               default B43_FW_5_10
                help
                  This option allows you to select the version of the b43 firmware.
 
@@ -914,8 +914,7 @@ define KernelPackage/b43/config
        config B43_FW_SQUASH_COREREVS
                string "Core revisions to include"
                depends on B43_FW_SQUASH
-               default "5,6,7,8,9,10,11,13,14,15,16" if PACKAGE_B43_PHY_N
-               default "5,6,7,8,9,10,13,14,15" if !PACKAGE_B43_PHY_N
+               default "5,6,7,8,9,10,13,14,15"
                help
                  This is a comma seperated list of core revision numbers.
 
@@ -928,8 +927,7 @@ define KernelPackage/b43/config
        config B43_FW_SQUASH_PHYTYPES
                string "PHY types to include"
                depends on B43_FW_SQUASH
-               default "G,LP,N" if PACKAGE_B43_PHY_N
-               default "G,LP" if !PACKAGE_B43_PHY_N
+               default "G,LP"
                help
                  This is a comma seperated list of PHY types:
                    A  => A-PHY
@@ -1040,6 +1038,7 @@ BUILDFLAGS:= \
        $(if $(CONFIG_PACKAGE_B43_DEBUG),-DCONFIG_B43_DEBUG) \
        $(if $(CONFIG_PACKAGE_B43_PIO),-DCONFIG_B43_PIO) \
        $(if $(CONFIG_PACKAGE_B43_PHY_N),-DCONFIG_B43_PHY_N) \
+       -DCONFIG_B43_SSB \
        $(if $(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS),-DCONFIG_RT2X00_LIB_DEBUGFS) \
        $(if $(CONFIG_PACKAGE_RT2X00_DEBUG),-DCONFIG_RT2X00_DEBUG) \
        $(if $(NEED_RT2X00_LIB_HT),-DCONFIG_RT2X00_LIB_HT) \
@@ -1076,6 +1075,7 @@ MAKE_OPTS:= \
        CONFIG_B43_DEBUG=$(if $(CONFIG_PACKAGE_B43_DEBUG),y) \
        CONFIG_B43_PIO=$(if $(CONFIG_PACKAGE_B43_PIO),y) \
        CONFIG_B43_PHY_N=$(if $(CONFIG_PACKAGE_B43_PHY_N),y) \
+       CONFIG_B43_SSB=y \
        CONFIG_ATH_COMMON=$(if $(CONFIG_PACKAGE_kmod-ath),m) \
        CONFIG_ATH_DEBUG=$(if $(CONFIG_PACKAGE_ATH_DEBUG),y) \
        CONFIG_ATH9K_PKTLOG=$(if $(CONFIG_PACKAGE_ATH_DEBUG),y) \
@@ -1128,7 +1128,7 @@ MAKE_OPTS:= \
        CONFIG_LIBERTAS=$(if $(CONFIG_PACKAGE_kmod-libertas-sd)$(CONFIG_PACKAGE_kmod-libertas-usb),m) \
        CONFIG_LIBERTAS_CS= \
        CONFIG_LIBERTAS_SPI= \
-       CONFIG_LIBERTAS_SDIO=$(if $(CONFIG_PACKAGE_kmod-libertas-sd),m) \
+       CONFIG_COMPAT_LIBERTAS_SDIO=$(if $(CONFIG_PACKAGE_kmod-libertas-sd),m) \
        CONFIG_LIBERTAS_THINFIRM= \
        CONFIG_LIBERTAS_USB=$(if $(CONFIG_PACKAGE_kmod-libertas-usb),m) \
        CONFIG_IPW2100=$(if $(CONFIG_PACKAGE_kmod-net-ipw2100),m) \
@@ -1227,7 +1227,7 @@ define KernelPackage/libertas-usb/install
 endef
 
 define KernelPackage/libertas-sd/install
-       $(INSTALL_DIR) $(1)/lib/firmware
+       $(INSTALL_DIR) $(1)/lib/firmware/libertas
        $(INSTALL_DATA) \
                $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385_helper.bin \
                $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8385.bin \
@@ -1237,7 +1237,7 @@ define KernelPackage/libertas-sd/install
                $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8686_v8.bin \
                $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688_helper.bin \
                $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/libertas/sd8688.bin \
-               $(1)/lib/firmware/
+               $(1)/lib/firmware/libertas
 endef
 
 define KernelPackage/cfg80211/install
@@ -1358,6 +1358,7 @@ endef
 
 define Build/b43-common
        tar xjf "$(DL_DIR)/$(PKG_B43_FWCUTTER_SOURCE)" -C "$(PKG_BUILD_DIR)"
+       patch -p1 -d  "$(PKG_BUILD_DIR)/$(PKG_B43_FWCUTTER_OBJECT)" < ./files/b43-fwcutter-fw-dirname.patch
        $(MAKE) -C "$(PKG_BUILD_DIR)/$(PKG_B43_FWCUTTER_OBJECT)" \
                CFLAGS="-I$(STAGING_DIR_HOST)/include -include endian.h" \
                QUIET_SPARSE=:
diff --git a/package/mac80211/files/b43-fwcutter-fw-dirname.patch b/package/mac80211/files/b43-fwcutter-fw-dirname.patch
new file mode 100644 (file)
index 0000000..c2f49ab
--- /dev/null
@@ -0,0 +1,16 @@
+--- a/fwcutter.c
++++ b/fwcutter.c
+@@ -48,13 +48,8 @@
+ #include "fwcutter.h"
+ #include "fwcutter_list.h"
+-#if defined(__DragonFly__) || defined(__FreeBSD__)
+-#define V3_FW_DIRNAME "v3"
+-#define V4_FW_DIRNAME "v4"
+-#else
+ #define V3_FW_DIRNAME "b43legacy"
+ #define V4_FW_DIRNAME "b43"
+-#endif
+ static struct cmdline_args cmdargs;
index a1e298d..9ef1d12 100644 (file)
@@ -16,6 +16,9 @@ mac80211_hostapd_setup_base() {
        config_get beacon_int "$device" beacon_int
        config_get basic_rate_list "$device" basic_rate
        config_get_bool noscan "$device" noscan
+
+       hostapd_set_log_options base_cfg "$device"
+
        [ -n "$channel" -a -z "$hwmode" ] && wifi_fixup_hwmode "$device"
 
        [ "$channel" = auto ] && {
@@ -280,6 +283,9 @@ enable_mac80211() {
        fixed=""
        local hostapd_ctrl=""
 
+       config_get ath9k_chanbw "$device" ath9k_chanbw
+       [ -n "$ath9k_chanbw" -a -d /sys/kernel/debug/ieee80211/$phy/ath9k ] && echo "$ath9k_chanbw" > /sys/kernel/debug/ieee80211/$phy/ath9k/chanbw
+
        [ -n "$country" ] && iw reg set "$country"
        [ "$channel" = "auto" -o "$channel" = "0" ] || {
                fixed=1
diff --git a/package/mac80211/patches/000-disable_ethernet.patch b/package/mac80211/patches/000-disable_ethernet.patch
new file mode 100644 (file)
index 0000000..f89fa53
--- /dev/null
@@ -0,0 +1,12 @@
+--- a/Makefile
++++ b/Makefile
+@@ -29,9 +29,6 @@ obj-$(CONFIG_COMPAT_WIRELESS_MODULES) +=
+ obj-$(CONFIG_COMPAT_NET_USB_MODULES) += drivers/net/usb/
+-obj-$(CONFIG_COMPAT_NETWORK_MODULES) += drivers/net/ethernet/atheros/
+-obj-$(CONFIG_COMPAT_NETWORK_MODULES) += drivers/net/ethernet/broadcom/
+-
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/ssb/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/bcma/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/misc/eeprom/
index 7e6018f..a4008bf 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -337,8 +337,8 @@ CONFIG_BCMA_HOST_PCI=y
+@@ -340,8 +340,8 @@ CONFIG_B43_BCMA_PIO=y
  
  CONFIG_P54_PCI=m
  
index 1cb319e..61e8b96 100644 (file)
@@ -9,7 +9,7 @@
  
  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")
-@@ -646,10 +646,10 @@ endif #CONFIG_COMPAT_KERNEL_2_6_27
+@@ -642,10 +642,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
index b067956..d5578d1 100644 (file)
@@ -1,14 +1,13 @@
 --- a/Makefile
 +++ b/Makefile
-@@ -30,7 +30,7 @@ obj-$(CONFIG_COMPAT_WIRELESS_MODULES) +=
+@@ -29,7 +29,6 @@ obj-$(CONFIG_COMPAT_WIRELESS_MODULES) +=
  obj-$(CONFIG_COMPAT_NET_USB_MODULES) += drivers/net/usb/
  
- obj-$(CONFIG_COMPAT_NETWORK_MODULES) += drivers/net/
--obj-$(CONFIG_COMPAT_VAR_MODULES) +=  drivers/ssb/ drivers/bcma/ drivers/misc/eeprom/
-+obj-$(CONFIG_COMPAT_VAR_MODULES) +=  drivers/bcma/ drivers/misc/eeprom/
+-obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/ssb/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/bcma/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/misc/eeprom/
  
- ifeq ($(CONFIG_STAGING_EXCLUDE_BUILD),)
- obj-$(CONFIG_COMPAT_STAGING) += drivers/staging/ath6kl/
 --- a/config.mk
 +++ b/config.mk
 @@ -9,7 +9,6 @@ ifeq ($(wildcard $(KLIB_BUILD)/.config),
@@ -19,7 +18,7 @@
  else
  include $(KLIB_BUILD)/.config
  endif
-@@ -314,7 +313,8 @@ CONFIG_IPW2200_QOS=y
+@@ -316,7 +315,8 @@ CONFIG_IPW2200_QOS=y
  # % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
  endif #CONFIG_WIRELESS_EXT
  
@@ -29,7 +28,7 @@
  # Sonics Silicon Backplane
  CONFIG_SSB_SPROM=y
  
-@@ -327,7 +327,7 @@ endif #CONFIG_PCMCIA
+@@ -329,7 +329,7 @@ endif #CONFIG_PCMCIA
  # CONFIG_SSB_DEBUG=y
  CONFIG_SSB_DRIVER_PCICORE=y
  CONFIG_B43_SSB=y
@@ -38,7 +37,7 @@
  
  CONFIG_BCMA=m
  CONFIG_BCMA_BLOCKIO=y
-@@ -534,7 +534,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -538,7 +538,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
  
  ifdef CONFIG_MMC
  
index 5835ea2..17eff65 100644 (file)
@@ -1,6 +1,16 @@
+--- a/Makefile
++++ b/Makefile
+@@ -29,7 +29,6 @@ obj-$(CONFIG_COMPAT_WIRELESS_MODULES) +=
+ obj-$(CONFIG_COMPAT_NET_USB_MODULES) += drivers/net/usb/
+-obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/bcma/
+ obj-$(CONFIG_COMPAT_VAR_MODULES) += drivers/misc/eeprom/
+ ifeq ($(CONFIG_STAGING_EXCLUDE_BUILD),)
 --- a/config.mk
 +++ b/config.mk
-@@ -329,9 +329,9 @@ CONFIG_SSB_DRIVER_PCICORE=y
+@@ -331,12 +331,12 @@ CONFIG_SSB_DRIVER_PCICORE=y
  CONFIG_B43_SSB=y
  endif #__CONFIG_SSB
  
 +# CONFIG_BCMA_BLOCKIO=y
 +# CONFIG_BCMA_HOST_PCI=y
  # CONFIG_BCMA_DEBUG=y
- # CONFIG_B43_BCMA=y
+-CONFIG_B43_BCMA=y
+-CONFIG_B43_BCMA_PIO=y
++# CONFIG_B43_BCMA=y
++# CONFIG_B43_BCMA_PIO=y
+ CONFIG_P54_PCI=m
  
index 37c03f2..103eb7b 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -212,7 +212,7 @@ $(warning "WARNING: CONFIG_CFG80211_WEXT
+@@ -213,7 +213,7 @@ $(warning "WARNING: CONFIG_CFG80211_WEXT
  endif #CONFIG_WIRELESS_EXT
  
  ifdef CONFIG_STAGING
@@ -9,7 +9,7 @@
  endif #CONFIG_STAGING
  
  # mac80211 test driver
-@@ -365,13 +365,13 @@ endif #CONFIG_CRC_ITU_T
+@@ -368,13 +368,13 @@ endif #CONFIG_CRC_ITU_T
  CONFIG_MWL8K=m
  
  # Ethernet drivers go here
@@ -28,7 +28,7 @@
  endif #CONFIG_COMPAT_KERNEL_2_6_27
  
  ifdef CONFIG_WIRELESS_EXT
-@@ -431,21 +431,21 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+@@ -435,21 +435,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
index f6b89d8..d6246b7 100644 (file)
@@ -9,7 +9,7 @@
  else
  include $(KLIB_BUILD)/.config
  endif
-@@ -247,7 +247,7 @@ CONFIG_B43=m
+@@ -248,7 +248,7 @@ CONFIG_B43=m
  CONFIG_B43_HWRNG=y
  CONFIG_B43_PCI_AUTOSELECT=y
  ifdef CONFIG_PCMCIA
index 857020e..366488a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -517,7 +517,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -521,7 +521,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
  
  ifdef CONFIG_MMC
  
index 63ae11d..8baaaca 100644 (file)
@@ -1,11 +1,11 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -253,7 +253,7 @@ ifdef CONFIG_MAC80211_LEDS
+@@ -254,7 +254,7 @@ 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_N=y
  # CONFIG_B43_PHY_HT=y
+ # CONFIG_B43_PHY_LCN=y
  # CONFIG_B43_FORCE_PIO=y
- # CONFIG_B43_DEBUG=y
index 86556d7..e449c23 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -327,7 +327,7 @@ CONFIG_RTL8180=m
+@@ -330,7 +330,7 @@ CONFIG_RTL8180=m
  
  CONFIG_ADM8211=m
  
@@ -9,7 +9,7 @@
  CONFIG_RT2400PCI=m
  CONFIG_RT2500PCI=m
  ifdef CONFIG_CRC_CCITT
-@@ -466,7 +466,7 @@ CONFIG_RT2800USB_RT35XX=y
+@@ -470,7 +470,7 @@ CONFIG_RT2800USB_RT35XX=y
  # CONFIG_RT2800USB_RT53XX=y
  CONFIG_RT2800USB_UNKNOWN=y
  endif #CONFIG_CRC_CCITT
index d275283..f341556 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -219,7 +219,7 @@ CONFIG_ATH9K_COMMON=m
+@@ -220,7 +220,7 @@ CONFIG_ATH9K_COMMON=m
  # as default once we get minstrel properly tested and blessed by
  # our systems engineering team. CCK rates also need to be used
  # for long range considerations.
index 960a65b..6aff41a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -334,83 +334,59 @@ static int b43_ratelimit(struct b43_wl *
+@@ -337,83 +337,59 @@ static int b43_ratelimit(struct b43_wl *
  
  void b43info(struct b43_wl *wl, const char *fmt, ...)
  {
@@ -98,7 +98,7 @@
  
 --- a/drivers/net/wireless/b43legacy/main.c
 +++ b/drivers/net/wireless/b43legacy/main.c
-@@ -181,75 +181,52 @@ static int b43legacy_ratelimit(struct b4
+@@ -179,75 +179,52 @@ static int b43legacy_ratelimit(struct b4
  
  void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...)
  {
index 07e3054..9de0418 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -224,7 +224,7 @@ CONFIG_ATH9K_COMMON=m
+@@ -225,7 +225,7 @@ CONFIG_ATH9K_COMMON=m
  # PCI Drivers
  ifdef CONFIG_PCI
  
diff --git a/package/mac80211/patches/020-netlink_seq.patch b/package/mac80211/patches/020-netlink_seq.patch
deleted file mode 100644 (file)
index 2897b40..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -3728,7 +3728,9 @@ static int nl80211_dump_scan(struct sk_b
-       spin_lock_bh(&rdev->bss_lock);
-       cfg80211_bss_expire(rdev);
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0))
-       cb->seq = rdev->bss_generation;
-+#endif
-       list_for_each_entry(scan, &rdev->bss_list, list) {
-               if (++idx <= start)
index 7589d73..ab77f76 100644 (file)
@@ -1,8 +1,8 @@
 --- a/compat/Makefile
 +++ b/compat/Makefile
-@@ -34,3 +34,8 @@ compat-$(CONFIG_COMPAT_KERNEL_2_6_39) +=
-       compat-2.6.39.o \
-       kstrtox.o
+@@ -38,3 +38,8 @@ compat-$(CONFIG_COMPAT_KERNEL_3_1) += \
+       cordic.o \
+       crc8.o
  
 +ifndef CONFIG_64BIT
 +ifndef CONFIG_GENERIC_ATOMIC64
@@ -11,9 +11,9 @@
 +endif
 --- a/include/linux/compat-2.6.31.h
 +++ b/include/linux/compat-2.6.31.h
-@@ -199,6 +199,20 @@ void compat_synchronize_threaded_irq(str
- #define list_entry_rcu(ptr, type, member) \
-       container_of(rcu_dereference(ptr), type, member)
+@@ -202,6 +202,20 @@ void compat_synchronize_threaded_irq(str
+ #define skb_walk_frags(skb, iter)     \
+       for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next)
  
 +#ifndef CONFIG_64BIT
 +
@@ -70,9 +70,9 @@
 +
 --- a/include/linux/compat-3.1.h
 +++ b/include/linux/compat-3.1.h
-@@ -24,6 +24,18 @@
- #define genl_dump_check_consistent(...) do {} while(0)
+@@ -19,6 +19,18 @@
+       .prod_id = { NULL, NULL, (v3), NULL }, \
+       .prod_id_hash = { 0, 0, (vh3), 0 }, }
  
 +/*
 + * In many versions, several architectures do not seem to include an
index 5738dd0..7678e3b 100644 (file)
@@ -33,7 +33,7 @@
  #endif
 --- a/config.mk
 +++ b/config.mk
-@@ -452,7 +452,7 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+@@ -456,7 +456,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.
index 6de5fd6..9b69328 100644 (file)
@@ -1,13 +1,3 @@
---- a/drivers/net/wireless/iwlwifi/iwl-agn.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
-@@ -27,6 +27,7 @@
-  *
-  *****************************************************************************/
-+#undef pr_fmt
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/kernel.h>
 --- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
 +++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
 @@ -27,6 +27,7 @@
@@ -27,7 +17,7 @@
 +#undef pr_fmt
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
- #include <linux/slab.h>
+ #include <linux/hardirq.h>
 --- a/drivers/net/wireless/libertas_tf/if_usb.c
 +++ b/drivers/net/wireless/libertas_tf/if_usb.c
 @@ -9,6 +9,7 @@
@@ -47,7 +37,7 @@
 +#undef pr_fmt
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
- #include <linux/slab.h>
+ #include <linux/hardirq.h>
 --- a/net/wireless/core.c
 +++ b/net/wireless/core.c
 @@ -4,6 +4,7 @@
 +#undef pr_fmt
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
- #include <linux/sched.h>
+ #include <linux/hardirq.h>
 --- a/drivers/net/wireless/libertas/if_cs.c
 +++ b/drivers/net/wireless/libertas/if_cs.c
 @@ -21,6 +21,7 @@
 +#undef pr_fmt
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
- #include <linux/moduleparam.h>
+ #include <linux/hardirq.h>
 --- a/drivers/net/wireless/libertas/if_usb.c
 +++ b/drivers/net/wireless/libertas/if_usb.c
 @@ -2,6 +2,7 @@
index d181971..c1f18af 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath5k/initvals.c
 +++ b/drivers/net/wireless/ath/ath5k/initvals.c
-@@ -58,8 +58,14 @@ static const struct ath5k_ini ar5210_ini
+@@ -57,8 +57,14 @@ static const struct ath5k_ini ar5210_ini
        { AR5K_IMR,             0 },
        { AR5K_IER,             AR5K_IER_DISABLE },
        { AR5K_BSR,             0, AR5K_INI_READ },
@@ -17,7 +17,7 @@
        { AR5K_RXNOFRM,         8 },
 --- a/drivers/net/wireless/ath/ath5k/dma.c
 +++ b/drivers/net/wireless/ath/ath5k/dma.c
-@@ -787,10 +787,18 @@ void ath5k_hw_dma_init(struct ath5k_hw *
+@@ -786,10 +786,18 @@ void ath5k_hw_dma_init(struct ath5k_hw *
         * guess we can tweak it and see how it goes ;-)
         */
        if (ah->ah_version != AR5K_AR5210) {
index a36f99c..ce766af 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/mac80211/agg-rx.c
 +++ b/net/mac80211/agg-rx.c
-@@ -176,6 +176,8 @@ static void ieee80211_send_addba_resp(st
+@@ -184,6 +184,8 @@ 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);
@@ -9,19 +9,6 @@
  
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                          IEEE80211_STYPE_ACTION);
-@@ -262,7 +264,11 @@ void ieee80211_process_addba_request(str
-                               "%pM on tid %u\n",
-                               mgmt->sa, tid);
- #endif /* CONFIG_MAC80211_HT_DEBUG */
--              goto end;
-+
-+              /* delete existing Rx BA session on the same tid */
-+              ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
-+                                              WLAN_STATUS_UNSPECIFIED_QOS,
-+                                              false);
-       }
-       /* prepare A-MPDU MLME for Rx aggregation */
 --- a/net/mac80211/agg-tx.c
 +++ b/net/mac80211/agg-tx.c
 @@ -79,7 +79,8 @@ static void ieee80211_send_addba_request
                return -EINVAL;
  
        if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
-@@ -809,7 +811,7 @@ void ieee80211_process_addba_resp(struct
-                * of at least 1.
-                */
-               if (!buf_size)
--                      goto out;
-+                      buf_size = 1;
-               if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED,
-                                    &tid_tx->state)) {
 --- a/net/mac80211/debugfs_sta.c
 +++ b/net/mac80211/debugfs_sta.c
 @@ -59,7 +59,7 @@ static ssize_t sta_flags_read(struct fil
                        break;
 --- a/net/mac80211/rx.c
 +++ b/net/mac80211/rx.c
-@@ -2137,7 +2137,8 @@ ieee80211_rx_h_action(struct ieee80211_r
+@@ -2160,7 +2160,8 @@ ieee80211_rx_h_action(struct ieee80211_r
                 */
                if (sdata->vif.type != NL80211_IFTYPE_STATION &&
                    sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
                        break;
  
                /* verify action_code is present */
-@@ -2335,13 +2336,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+@@ -2375,13 +2376,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):
-@@ -2680,10 +2682,16 @@ static int prepare_for_handlers(struct i
+@@ -2724,10 +2726,16 @@ static int prepare_for_handlers(struct i
                }
                break;
        case NL80211_IFTYPE_WDS:
        WLAN_STA_CLEAR_PS_FILT  = 1<<9,
        WLAN_STA_MFP            = 1<<10,
        WLAN_STA_BLOCK_BA       = 1<<11,
---- a/drivers/net/wireless/ath/ath9k/beacon.c
-+++ b/drivers/net/wireless/ath/ath9k/beacon.c
-@@ -360,6 +360,7 @@ void ath_beacon_tasklet(unsigned long da
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ath_buf *bf = NULL;
-       struct ieee80211_vif *vif;
-+      struct ath_tx_status ts;
-       int slot;
-       u32 bfaddr, bc = 0;
-@@ -384,7 +385,9 @@ void ath_beacon_tasklet(unsigned long da
-                       ath_dbg(common, ATH_DBG_BSTUCK,
-                               "beacon is officially stuck\n");
-                       sc->sc_flags |= SC_OP_TSF_RESET;
-+                      spin_lock(&sc->sc_pcu_lock);
-                       ath_reset(sc, true);
-+                      spin_unlock(&sc->sc_pcu_lock);
-               }
-               return;
-@@ -464,6 +467,11 @@ void ath_beacon_tasklet(unsigned long da
-               ath9k_hw_txstart(ah, sc->beacon.beaconq);
-               sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */
-+              if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
-+                      spin_lock_bh(&sc->sc_pcu_lock);
-+                      ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
-+                      spin_unlock_bh(&sc->sc_pcu_lock);
-+              }
-       }
- }
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -617,8 +617,11 @@ 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) {
-+                      spin_lock_bh(&sc->sc_pcu_lock);
-                       ath_reset(sc, true);
-+                      spin_unlock_bh(&sc->sc_pcu_lock);
-+              }
-       } else if (busy >= 0)
-               sc->hw_busy_count = 0;
-@@ -637,7 +640,9 @@ 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");
-+                      spin_lock_bh(&sc->sc_pcu_lock);
-                       ath_reset(sc, true);
-+                      spin_unlock_bh(&sc->sc_pcu_lock);
-                       count = 0;
-               }
-       } else
-@@ -674,7 +679,9 @@ void ath9k_tasklet(unsigned long data)
-       if ((status & ATH9K_INT_FATAL) ||
-           (status & ATH9K_INT_BB_WATCHDOG)) {
-+              spin_lock(&sc->sc_pcu_lock);
-               ath_reset(sc, true);
-+              spin_unlock(&sc->sc_pcu_lock);
-               return;
-       }
-@@ -980,7 +987,6 @@ int ath_reset(struct ath_softc *sc, bool
-       del_timer_sync(&common->ani.timer);
-       ath9k_ps_wakeup(sc);
--      spin_lock_bh(&sc->sc_pcu_lock);
-       ieee80211_stop_queues(hw);
-@@ -1023,7 +1029,6 @@ int ath_reset(struct ath_softc *sc, bool
-       }
-       ieee80211_wake_queues(hw);
--      spin_unlock_bh(&sc->sc_pcu_lock);
-       /* Start ANI */
-       if (!common->disable_ani)
-@@ -2326,9 +2331,9 @@ static void ath9k_flush(struct ieee80211
-       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);
-+      spin_unlock_bh(&sc->sc_pcu_lock);
-       ath9k_ps_restore(sc);
-       ieee80211_wake_queues(hw);
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -565,11 +565,8 @@ static void ath_tx_complete_aggr(struct 
-       rcu_read_unlock();
--      if (needreset) {
--              spin_unlock_bh(&sc->sc_pcu_lock);
-+      if (needreset)
-               ath_reset(sc, false);
--              spin_lock_bh(&sc->sc_pcu_lock);
--      }
- }
- static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
-@@ -664,7 +661,8 @@ static int ath_compute_num_delims(struct
-        * TODO - this could be improved to be dependent on the rate.
-        *      The hardware can keep up at lower rates, but not higher rates
-        */
--      if (fi->keyix != ATH9K_TXKEYIX_INVALID)
-+      if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&
-+          !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
-               ndelim += ATH_AGGR_ENCRYPTDELIM;
-       /*
-@@ -2169,7 +2167,9 @@ 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");
-+              spin_lock_bh(&sc->sc_pcu_lock);
-               ath_reset(sc, true);
-+              spin_unlock_bh(&sc->sc_pcu_lock);
-       }
-       ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
---- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
-@@ -236,7 +236,7 @@ static void ar9003_paprd_get_gain_table(
-       memset(entry, 0, sizeof(ah->paprd_gain_table_entries));
-       memset(index, 0, sizeof(ah->paprd_gain_table_index));
--      for (i = 0; i < 32; i++) {
-+      for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
-               entry[i] = REG_READ(ah, reg);
-               index[i] = (entry[i] >> 24) & 0xff;
-               reg += 4;
-@@ -246,13 +246,13 @@ static void ar9003_paprd_get_gain_table(
- static unsigned int ar9003_get_desired_gain(struct ath_hw *ah, int chain,
-                                           int target_power)
- {
--      int olpc_gain_delta = 0;
-+      int olpc_gain_delta = 0, cl_gain_mod;
-       int alpha_therm, alpha_volt;
-       int therm_cal_value, volt_cal_value;
-       int therm_value, volt_value;
-       int thermal_gain_corr, voltage_gain_corr;
-       int desired_scale, desired_gain = 0;
--      u32 reg;
-+      u32 reg_olpc  = 0, reg_cl_gain  = 0;
-       REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
-                   AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
-@@ -271,15 +271,29 @@ static unsigned int ar9003_get_desired_g
-       volt_value = REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4,
-                                   AR_PHY_BB_THERM_ADC_4_LATEST_VOLT_VALUE);
--      if (chain == 0)
--              reg = AR_PHY_TPC_11_B0;
--      else if (chain == 1)
--              reg = AR_PHY_TPC_11_B1;
--      else
--              reg = AR_PHY_TPC_11_B2;
-+      switch (chain) {
-+      case 0:
-+              reg_olpc = AR_PHY_TPC_11_B0;
-+              reg_cl_gain = AR_PHY_CL_TAB_0;
-+              break;
-+      case 1:
-+              reg_olpc = AR_PHY_TPC_11_B1;
-+              reg_cl_gain = AR_PHY_CL_TAB_1;
-+              break;
-+      case 2:
-+              reg_olpc = AR_PHY_TPC_11_B2;
-+              reg_cl_gain = AR_PHY_CL_TAB_2;
-+              break;
-+      default:
-+              ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
-+              "Invalid chainmask: %d\n", chain);
-+              break;
-+      }
--      olpc_gain_delta = REG_READ_FIELD(ah, reg,
-+      olpc_gain_delta = REG_READ_FIELD(ah, reg_olpc,
-                                        AR_PHY_TPC_11_OLPC_GAIN_DELTA);
-+      cl_gain_mod = REG_READ_FIELD(ah, reg_cl_gain,
-+                                       AR_PHY_CL_TAB_CL_GAIN_MOD);
-       if (olpc_gain_delta >= 128)
-               olpc_gain_delta = olpc_gain_delta - 256;
-@@ -289,7 +303,7 @@ static unsigned int ar9003_get_desired_g
-       voltage_gain_corr = (alpha_volt * (volt_value - volt_cal_value) +
-                            (128 / 2)) / 128;
-       desired_gain = target_power - olpc_gain_delta - thermal_gain_corr -
--          voltage_gain_corr + desired_scale;
-+          voltage_gain_corr + desired_scale + cl_gain_mod;
-       return desired_gain;
- }
-@@ -727,7 +741,7 @@ int ar9003_paprd_setup_gain_table(struct
-       desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
-       gain_index = 0;
--      for (i = 0; i < 32; i++) {
-+      for (i = 0; i < PAPRD_GAIN_TABLE_ENTRIES; i++) {
-               if (ah->paprd_gain_table_index[i] >= desired_gain)
-                       break;
-               gain_index++;
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
-@@ -1121,6 +1121,9 @@
- #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5    0x3F00
- #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S  8
-+#define AR_PHY_CL_TAB_CL_GAIN_MOD             0x1f
-+#define AR_PHY_CL_TAB_CL_GAIN_MOD_S           0
-+
- void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
- #endif  /* AR9003_PHY_H */
---- a/drivers/net/wireless/ath/ath5k/eeprom.c
-+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
-@@ -691,14 +691,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k
-               if (!chinfo[pier].pd_curves)
-                       continue;
--              for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
-+              for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) {
-                       struct ath5k_pdgain_info *pd =
-                                       &chinfo[pier].pd_curves[pdg];
--                      if (pd != NULL) {
--                              kfree(pd->pd_step);
--                              kfree(pd->pd_pwr);
--                      }
-+                      kfree(pd->pd_step);
-+                      kfree(pd->pd_pwr);
-               }
-               kfree(chinfo[pier].pd_curves);
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -229,6 +229,7 @@ static void ar9003_hw_fill_txdesc(struct
- static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
-                                struct ath_tx_status *ts)
- {
-+      struct ar9003_txc *txc = (struct ar9003_txc *) ds;
-       struct ar9003_txs *ads;
-       u32 status;
-@@ -238,7 +239,11 @@ static int ar9003_hw_proc_txdesc(struct 
-       if ((status & AR_TxDone) == 0)
-               return -EINPROGRESS;
--      ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
-+      ts->qid = MS(ads->ds_info, AR_TxQcuNum);
-+      if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
-+              ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
-+      else
-+              return -ENOENT;
-       if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
-           (MS(ads->ds_info, AR_TxRxDesc) != 1)) {
-@@ -254,7 +259,6 @@ static int ar9003_hw_proc_txdesc(struct 
-       ts->ts_seqnum = MS(status, AR_SeqNum);
-       ts->tid = MS(status, AR_TxTid);
--      ts->qid = MS(ads->ds_info, AR_TxQcuNum);
-       ts->desc_id = MS(ads->status1, AR_TxDescId);
-       ts->ts_tstamp = ads->status4;
-       ts->ts_status = 0;
---- a/net/mac80211/wpa.c
-+++ b/net/mac80211/wpa.c
-@@ -15,6 +15,7 @@
- #include <linux/gfp.h>
- #include <asm/unaligned.h>
- #include <net/mac80211.h>
-+#include <crypto/aes.h>
- #include "ieee80211_i.h"
- #include "michael.h"
-@@ -86,6 +87,11 @@ ieee80211_rx_h_michael_mic_verify(struct
-       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 queue = rx->queue;
-+
-+      /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
-+      if (rx->queue == NUM_RX_DATA_QUEUES - 1)
-+              queue = 0;
-       /*
-        * it makes no sense to check for MIC errors on anything other
-@@ -148,8 +154,8 @@ ieee80211_rx_h_michael_mic_verify(struct
- update_iv:
-       /* update IV in key information to be able to detect replays */
--      rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32;
--      rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16;
-+      rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32;
-+      rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16;
-       return RX_CONTINUE;
-@@ -165,6 +171,7 @@ static int tkip_encrypt_skb(struct ieee8
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       struct ieee80211_key *key = tx->key;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-+      unsigned long flags;
-       unsigned int hdrlen;
-       int len, tail;
-       u8 *pos;
-@@ -192,11 +199,12 @@ static int tkip_encrypt_skb(struct ieee8
-       pos += hdrlen;
-       /* Increase IV for the frame */
-+      spin_lock_irqsave(&key->u.tkip.txlock, flags);
-       key->u.tkip.tx.iv16++;
-       if (key->u.tkip.tx.iv16 == 0)
-               key->u.tkip.tx.iv32++;
--
--      pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
-+      pos = ieee80211_tkip_add_iv(pos, key);
-+      spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
-       /* hwaccel - with software IV */
-       if (info->control.hw_key)
-@@ -205,9 +213,8 @@ static int tkip_encrypt_skb(struct ieee8
-       /* Add room for ICV */
-       skb_put(skb, TKIP_ICV_LEN);
--      hdr = (struct ieee80211_hdr *) skb->data;
-       return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
--                                         key, pos, len, hdr->addr2);
-+                                         key, skb, pos, len);
- }
-@@ -235,6 +242,11 @@ ieee80211_crypto_tkip_decrypt(struct iee
-       struct ieee80211_key *key = rx->key;
-       struct sk_buff *skb = rx->skb;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+      int queue = rx->queue;
-+
-+      /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
-+      if (rx->queue == NUM_RX_DATA_QUEUES - 1)
-+              queue = 0;
-       hdrlen = ieee80211_hdrlen(hdr->frame_control);
-@@ -255,7 +267,7 @@ ieee80211_crypto_tkip_decrypt(struct iee
-       res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
-                                         key, skb->data + hdrlen,
-                                         skb->len - hdrlen, rx->sta->sta.addr,
--                                        hdr->addr1, hwaccel, rx->queue,
-+                                        hdr->addr1, hwaccel, queue,
-                                         &rx->tkip_iv32,
-                                         &rx->tkip_iv16);
-       if (res != TKIP_DECRYPT_OK)
-@@ -283,6 +295,8 @@ static void ccmp_special_blocks(struct s
-       unsigned int hdrlen;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+      memset(scratch, 0, 6 * AES_BLOCK_LEN);
-+
-       b_0 = scratch + 3 * AES_BLOCK_LEN;
-       aad = scratch + 4 * AES_BLOCK_LEN;
-@@ -373,8 +387,10 @@ static int ccmp_encrypt_skb(struct ieee8
-       struct ieee80211_key *key = tx->key;
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       int hdrlen, len, tail;
--      u8 *pos, *pn;
--      int i;
-+      u8 *pos;
-+      u8 pn[6];
-+      u64 pn64;
-+      u8 scratch[6 * AES_BLOCK_LEN];
-       if (info->control.hw_key &&
-           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
-@@ -402,14 +418,14 @@ static int ccmp_encrypt_skb(struct ieee8
-       hdr = (struct ieee80211_hdr *) pos;
-       pos += hdrlen;
--      /* PN = PN + 1 */
--      pn = key->u.ccmp.tx_pn;
-+      pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn);
--      for (i = CCMP_PN_LEN - 1; i >= 0; i--) {
--              pn[i]++;
--              if (pn[i])
--                      break;
--      }
-+      pn[5] = pn64;
-+      pn[4] = pn64 >> 8;
-+      pn[3] = pn64 >> 16;
-+      pn[2] = pn64 >> 24;
-+      pn[1] = pn64 >> 32;
-+      pn[0] = pn64 >> 40;
-       ccmp_pn2hdr(pos, pn, key->conf.keyidx);
-@@ -418,8 +434,8 @@ static int ccmp_encrypt_skb(struct ieee8
-               return 0;
-       pos += CCMP_HDR_LEN;
--      ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0);
--      ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len,
-+      ccmp_special_blocks(skb, pn, scratch, 0);
-+      ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
-                                 pos, skb_put(skb, CCMP_MIC_LEN));
-       return 0;
-@@ -475,11 +491,12 @@ ieee80211_crypto_ccmp_decrypt(struct iee
-       }
-       if (!(status->flag & RX_FLAG_DECRYPTED)) {
-+              u8 scratch[6 * AES_BLOCK_LEN];
-               /* hardware didn't decrypt/verify MIC */
--              ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1);
-+              ccmp_special_blocks(skb, pn, scratch, 1);
-               if (ieee80211_aes_ccm_decrypt(
--                          key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf,
-+                          key->u.ccmp.tfm, scratch,
-                           skb->data + hdrlen + CCMP_HDR_LEN, data_len,
-                           skb->data + skb->len - CCMP_MIC_LEN,
-                           skb->data + hdrlen + CCMP_HDR_LEN))
---- a/drivers/net/wireless/b43/xmit.c
-+++ b/drivers/net/wireless/b43/xmit.c
-@@ -323,8 +323,7 @@ int b43_generate_txhdr(struct b43_wldev 
-                       /* we give the phase1key and iv16 here, the key is stored in
-                        * shm. With that the hardware can do phase 2 and encryption.
-                        */
--                      ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
--                                      IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
-+                      ieee80211_get_tkip_p1k(info->control.hw_key, skb_frag, phase1key);
-                       /* phase1key is in host endian. Copy to little-endian txhdr->iv. */
-                       for (i = 0; i < 5; i++) {
-                               txhdr->iv[i * 2 + 0] = phase1key[i];
---- a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
-+++ b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
-@@ -240,8 +240,7 @@ static void iwl4965_tx_cmd_build_hwcrypt
-       case WLAN_CIPHER_SUITE_TKIP:
-               tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
--              ieee80211_get_tkip_key(keyconf, skb_frag,
--                      IEEE80211_TKIP_P2_KEY, tx_cmd->key);
-+              ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
-               IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
-               break;
---- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
-@@ -497,8 +497,7 @@ static void iwlagn_tx_cmd_build_hwcrypto
-       case WLAN_CIPHER_SUITE_TKIP:
-               tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
--              ieee80211_get_tkip_key(keyconf, skb_frag,
--                      IEEE80211_TKIP_P2_KEY, tx_cmd->key);
-+              ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
-               IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
-               break;
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -960,21 +960,6 @@ enum sta_notify_cmd {
- };
- /**
-- * enum ieee80211_tkip_key_type - get tkip key
-- *
-- * Used by drivers which need to get a tkip key for skb. Some drivers need a
-- * phase 1 key, others need a phase 2 key. A single function allows the driver
-- * to get the key, this enum indicates what type of key is required.
-- *
-- * @IEEE80211_TKIP_P1_KEY: the driver needs a phase 1 key
-- * @IEEE80211_TKIP_P2_KEY: the driver needs a phase 2 key
-- */
--enum ieee80211_tkip_key_type {
--      IEEE80211_TKIP_P1_KEY,
--      IEEE80211_TKIP_P2_KEY,
--};
--
--/**
-  * enum ieee80211_hw_flags - hardware flags
-  *
-  * These flags are used to indicate hardware capabilities to
-@@ -2568,21 +2553,33 @@ struct sk_buff *
- ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
- /**
-- * ieee80211_get_tkip_key - get a TKIP rc4 for skb
-+ * ieee80211_get_tkip_p1k - get a TKIP phase 1 key
-+ *
-+ * This function returns the TKIP phase 1 key for the IV32 taken
-+ * from the given packet.
-+ *
-+ * @keyconf: the parameter passed with the set key
-+ * @skb: the packet to take the IV32 value from that will be encrypted
-+ *    with this P1K
-+ * @p1k: a buffer to which the key will be written, as 5 u16 values
-+ */
-+void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf,
-+                          struct sk_buff *skb, u16 *p1k);
-+
-+/**
-+ * ieee80211_get_tkip_p2k - get a TKIP phase 2 key
-  *
-- * This function computes a TKIP rc4 key for an skb. It computes
-- * a phase 1 key if needed (iv16 wraps around). This function is to
-- * be used by drivers which can do HW encryption but need to compute
-- * to phase 1/2 key in SW.
-+ * This function computes the TKIP RC4 key for the IV values
-+ * in the packet.
-  *
-  * @keyconf: the parameter passed with the set key
-- * @skb: the skb for which the key is needed
-- * @type: TBD
-- * @key: a buffer to which the key will be written
-- */
--void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
--                              struct sk_buff *skb,
--                              enum ieee80211_tkip_key_type type, u8 *key);
-+ * @skb: the packet to take the IV32/IV16 values from that will be
-+ *    encrypted with this key
-+ * @p2k: a buffer to which the key will be written, 16 bytes
-+ */
-+void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
-+                          struct sk_buff *skb, u8 *p2k);
-+
- /**
-  * ieee80211_wake_queue - wake specific queue
-  * @hw: pointer as obtained from ieee80211_alloc_hw().
---- a/net/mac80211/key.c
-+++ b/net/mac80211/key.c
-@@ -333,6 +333,7 @@ struct ieee80211_key *ieee80211_key_allo
-                                       get_unaligned_le16(seq);
-                       }
-               }
-+              spin_lock_init(&key->u.tkip.txlock);
-               break;
-       case WLAN_CIPHER_SUITE_CCMP:
-               key->conf.iv_len = CCMP_HDR_LEN;
---- a/net/mac80211/key.h
-+++ b/net/mac80211/key.h
-@@ -52,9 +52,10 @@ enum ieee80211_internal_tkip_state {
- };
- struct tkip_ctx {
--      u32 iv32;
--      u16 iv16;
--      u16 p1k[5];
-+      u32 iv32;       /* current iv32 */
-+      u16 iv16;       /* current iv16 */
-+      u16 p1k[5];     /* p1k cache */
-+      u32 p1k_iv32;   /* iv32 for which p1k computed */
-       enum ieee80211_internal_tkip_state state;
- };
-@@ -71,6 +72,9 @@ struct ieee80211_key {
-       union {
-               struct {
-+                      /* protects tx context */
-+                      spinlock_t txlock;
-+
-                       /* last used TSC */
-                       struct tkip_ctx tx;
-@@ -78,7 +82,7 @@ struct ieee80211_key {
-                       struct tkip_ctx rx[NUM_RX_DATA_QUEUES];
-               } tkip;
-               struct {
--                      u8 tx_pn[6];
-+                      atomic64_t tx_pn;
-                       /*
-                        * Last received packet number. The first
-                        * NUM_RX_DATA_QUEUES counters are used with Data
-@@ -88,12 +92,9 @@ struct ieee80211_key {
-                       u8 rx_pn[NUM_RX_DATA_QUEUES + 1][6];
-                       struct crypto_cipher *tfm;
-                       u32 replays; /* dot11RSNAStatsCCMPReplays */
--                      /* scratch buffers for virt_to_page() (crypto API) */
- #ifndef AES_BLOCK_LEN
- #define AES_BLOCK_LEN 16
- #endif
--                      u8 tx_crypto_buf[6 * AES_BLOCK_LEN];
--                      u8 rx_crypto_buf[6 * AES_BLOCK_LEN];
-               } ccmp;
-               struct {
-                       u8 tx_pn[6];
---- a/net/mac80211/tkip.c
-+++ b/net/mac80211/tkip.c
-@@ -101,6 +101,7 @@ static void tkip_mixing_phase1(const u8 
-               p1k[4] += tkipS(p1k[3] ^ get_unaligned_le16(tk + 0 + j)) + i;
-       }
-       ctx->state = TKIP_STATE_PHASE1_DONE;
-+      ctx->p1k_iv32 = tsc_IV32;
- }
- static void tkip_mixing_phase2(const u8 *tk, struct tkip_ctx *ctx,
-@@ -140,60 +141,72 @@ static void tkip_mixing_phase2(const u8 
- /* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
-  * of the IV. Returns pointer to the octet following IVs (i.e., beginning of
-  * the packet payload). */
--u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16)
-+u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key)
- {
--      pos = write_tkip_iv(pos, iv16);
-+      lockdep_assert_held(&key->u.tkip.txlock);
-+
-+      pos = write_tkip_iv(pos, key->u.tkip.tx.iv16);
-       *pos++ = (key->conf.keyidx << 6) | (1 << 5) /* Ext IV */;
-       put_unaligned_le32(key->u.tkip.tx.iv32, pos);
-       return pos + 4;
- }
--void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
--                      struct sk_buff *skb, enum ieee80211_tkip_key_type type,
--                      u8 *outkey)
-+static void ieee80211_compute_tkip_p1k(struct ieee80211_key *key, u32 iv32)
- {
--      struct ieee80211_key *key = (struct ieee80211_key *)
--                      container_of(keyconf, struct ieee80211_key, conf);
--      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
--      u8 *data;
--      const u8 *tk;
--      struct tkip_ctx *ctx;
--      u16 iv16;
--      u32 iv32;
--
--      data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
--      iv16 = data[2] | (data[0] << 8);
--      iv32 = get_unaligned_le32(&data[4]);
--
--      tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
--      ctx = &key->u.tkip.tx;
--
--#ifdef CONFIG_MAC80211_TKIP_DEBUG
--      printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n",
--                      iv16, iv32);
-+      struct ieee80211_sub_if_data *sdata = key->sdata;
-+      struct tkip_ctx *ctx = &key->u.tkip.tx;
-+      const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
--      if (iv32 != ctx->iv32) {
--              printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n",
--                      iv32, ctx->iv32);
--              printk(KERN_DEBUG "Wrap around of iv16 in the middle of a "
--                      "fragmented packet\n");
--      }
--#endif
-+      lockdep_assert_held(&key->u.tkip.txlock);
--      /* Update the p1k only when the iv16 in the packet wraps around, this
--       * might occur after the wrap around of iv16 in the key in case of
--       * fragmented packets. */
--      if (iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
--              tkip_mixing_phase1(tk, ctx, hdr->addr2, iv32);
-+      /*
-+       * Update the P1K when the IV32 is different from the value it
-+       * had when we last computed it (or when not initialised yet).
-+       * This might flip-flop back and forth if packets are processed
-+       * out-of-order due to the different ACs, but then we have to
-+       * just compute the P1K more often.
-+       */
-+      if (ctx->p1k_iv32 != iv32 || ctx->state == TKIP_STATE_NOT_INIT)
-+              tkip_mixing_phase1(tk, ctx, sdata->vif.addr, iv32);
-+}
--      if (type == IEEE80211_TKIP_P1_KEY) {
--              memcpy(outkey, ctx->p1k, sizeof(u16) * 5);
--              return;
--      }
-+void ieee80211_get_tkip_p1k(struct ieee80211_key_conf *keyconf,
-+                          struct sk_buff *skb, u16 *p1k)
-+{
-+      struct ieee80211_key *key = (struct ieee80211_key *)
-+                      container_of(keyconf, struct ieee80211_key, conf);
-+      struct tkip_ctx *ctx = &key->u.tkip.tx;
-+      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+      const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
-+      u32 iv32 = get_unaligned_le32(&data[4]);
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&key->u.tkip.txlock, flags);
-+      ieee80211_compute_tkip_p1k(key, iv32);
-+      memcpy(p1k, ctx->p1k, sizeof(ctx->p1k));
-+      spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
-+}
-+EXPORT_SYMBOL(ieee80211_get_tkip_p1k);
--      tkip_mixing_phase2(tk, ctx, iv16, outkey);
-+void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
-+                          struct sk_buff *skb, u8 *p2k)
-+{
-+      struct ieee80211_key *key = (struct ieee80211_key *)
-+                      container_of(keyconf, struct ieee80211_key, conf);
-+      const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
-+      struct tkip_ctx *ctx = &key->u.tkip.tx;
-+      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+      const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
-+      u32 iv32 = get_unaligned_le32(&data[4]);
-+      u16 iv16 = data[2] | (data[0] << 8);
-+      unsigned long flags;
-+
-+      spin_lock_irqsave(&key->u.tkip.txlock, flags);
-+      ieee80211_compute_tkip_p1k(key, iv32);
-+      tkip_mixing_phase2(tk, ctx, iv16, p2k);
-+      spin_unlock_irqrestore(&key->u.tkip.txlock, flags);
- }
--EXPORT_SYMBOL(ieee80211_get_tkip_key);
-+EXPORT_SYMBOL(ieee80211_get_tkip_p2k);
- /*
-  * Encrypt packet payload with TKIP using @key. @pos is a pointer to the
-@@ -204,19 +217,15 @@ EXPORT_SYMBOL(ieee80211_get_tkip_key);
-  */
- int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
-                               struct ieee80211_key *key,
--                              u8 *pos, size_t payload_len, u8 *ta)
-+                              struct sk_buff *skb,
-+                              u8 *payload, size_t payload_len)
- {
-       u8 rc4key[16];
--      struct tkip_ctx *ctx = &key->u.tkip.tx;
--      const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
--
--      /* Calculate per-packet key */
--      if (ctx->iv16 == 0 || ctx->state == TKIP_STATE_NOT_INIT)
--              tkip_mixing_phase1(tk, ctx, ta, ctx->iv32);
--      tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key);
-+      ieee80211_get_tkip_p2k(&key->conf, skb, rc4key);
--      return ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
-+      return ieee80211_wep_encrypt_data(tfm, rc4key, 16,
-+                                        payload, payload_len);
- }
- /* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
---- a/net/mac80211/tkip.h
-+++ b/net/mac80211/tkip.h
-@@ -13,11 +13,13 @@
- #include <linux/crypto.h>
- #include "key.h"
--u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key, u16 iv16);
-+u8 *ieee80211_tkip_add_iv(u8 *pos, struct ieee80211_key *key);
- int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm,
--                               struct ieee80211_key *key,
--                               u8 *pos, size_t payload_len, u8 *ta);
-+                              struct ieee80211_key *key,
-+                              struct sk_buff *skb,
-+                              u8 *payload, size_t payload_len);
-+
- enum {
-       TKIP_DECRYPT_OK = 0,
-       TKIP_DECRYPT_NO_EXT_IV = -1,
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -209,6 +209,7 @@ static int ieee80211_get_key(struct wiph
-       u8 seq[6] = {0};
-       struct key_params params;
-       struct ieee80211_key *key = NULL;
-+      u64 pn64;
-       u32 iv32;
-       u16 iv16;
-       int err = -ENOENT;
-@@ -256,12 +257,13 @@ static int ieee80211_get_key(struct wiph
-               params.seq_len = 6;
-               break;
-       case WLAN_CIPHER_SUITE_CCMP:
--              seq[0] = key->u.ccmp.tx_pn[5];
--              seq[1] = key->u.ccmp.tx_pn[4];
--              seq[2] = key->u.ccmp.tx_pn[3];
--              seq[3] = key->u.ccmp.tx_pn[2];
--              seq[4] = key->u.ccmp.tx_pn[1];
--              seq[5] = key->u.ccmp.tx_pn[0];
-+              pn64 = atomic64_read(&key->u.ccmp.tx_pn);
-+              seq[0] = pn64;
-+              seq[1] = pn64 >> 8;
-+              seq[2] = pn64 >> 16;
-+              seq[3] = pn64 >> 24;
-+              seq[4] = pn64 >> 32;
-+              seq[5] = pn64 >> 40;
-               params.seq = seq;
-               params.seq_len = 6;
-               break;
---- a/net/mac80211/debugfs_key.c
-+++ b/net/mac80211/debugfs_key.c
-@@ -79,6 +79,7 @@ static ssize_t key_tx_spec_read(struct f
-                               size_t count, loff_t *ppos)
- {
-       const u8 *tpn;
-+      u64 pn;
-       char buf[20];
-       int len;
-       struct ieee80211_key *key = file->private_data;
-@@ -94,9 +95,10 @@ static ssize_t key_tx_spec_read(struct f
-                               key->u.tkip.tx.iv16);
-               break;
-       case WLAN_CIPHER_SUITE_CCMP:
--              tpn = key->u.ccmp.tx_pn;
-+              pn = atomic64_read(&key->u.ccmp.tx_pn);
-               len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
--                              tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
-+                              (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
-+                              (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
-               break;
-       case WLAN_CIPHER_SUITE_AES_CMAC:
-               tpn = key->u.aes_cmac.tx_pn;
---- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
-@@ -653,8 +653,8 @@ static const u32 ar9300_2p2_baseband_pos
-       {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
-       {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
--      {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982},
--      {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
-+      {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
-+      {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
-       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c},
-       {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000},
-@@ -761,7 +761,7 @@ static const u32 ar9300_2p2_baseband_cor
-       {0x0000a3ec, 0x20202020},
-       {0x0000a3f0, 0x00000000},
-       {0x0000a3f4, 0x00000246},
--      {0x0000a3f8, 0x0cdbd380},
-+      {0x0000a3f8, 0x0c9bd380},
-       {0x0000a3fc, 0x000f0f01},
-       {0x0000a400, 0x8fa91f01},
-       {0x0000a404, 0x00000000},
-@@ -780,7 +780,7 @@ static const u32 ar9300_2p2_baseband_cor
-       {0x0000a43c, 0x00100000},
-       {0x0000a440, 0x00000000},
-       {0x0000a444, 0x00000000},
--      {0x0000a448, 0x06000080},
-+      {0x0000a448, 0x05000080},
-       {0x0000a44c, 0x00000001},
-       {0x0000a450, 0x00010000},
-       {0x0000a458, 0x00000000},
-@@ -1500,8 +1500,6 @@ static const u32 ar9300_2p2_mac_core[][2
-       {0x0000816c, 0x00000000},
-       {0x000081c0, 0x00000000},
-       {0x000081c4, 0x33332210},
--      {0x000081c8, 0x00000000},
--      {0x000081cc, 0x00000000},
-       {0x000081ec, 0x00000000},
-       {0x000081f0, 0x00000000},
-       {0x000081f4, 0x00000000},
---- a/net/mac80211/work.c
-+++ b/net/mac80211/work.c
-@@ -1075,14 +1075,13 @@ static void ieee80211_work_work(struct w
-                       continue;
-               if (wk->chan != local->tmp_channel)
-                       continue;
--              if (ieee80211_work_ct_coexists(wk->chan_type,
--                                             local->tmp_channel_type))
-+              if (!ieee80211_work_ct_coexists(wk->chan_type,
-+                                              local->tmp_channel_type))
-                       continue;
-               remain_off_channel = true;
-       }
-       if (!remain_off_channel && local->tmp_channel) {
--              bool on_oper_chan = ieee80211_cfg_on_oper_channel(local);
-               local->tmp_channel = NULL;
-               /* If tmp_channel wasn't operating channel, then
-                * we need to go back on-channel.
-@@ -1092,7 +1091,7 @@ static void ieee80211_work_work(struct w
-                * we still need to do a hardware config.  Currently,
-                * we cannot be here while scanning, however.
-                */
--              if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan)
-+              if (!ieee80211_cfg_on_oper_channel(local))
-                       ieee80211_hw_config(local, 0);
-               /* At the least, we need to disable offchannel_ps,
---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-@@ -627,6 +627,11 @@ static void ar5008_hw_init_bb(struct ath
-       else
-               synthDelay /= 10;
-+      if (IS_CHAN_HALF_RATE(chan))
-+              synthDelay *= 2;
-+      else if (IS_CHAN_QUARTER_RATE(chan))
-+              synthDelay *= 4;
-+
-       REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
-       udelay(synthDelay + BASE_ACTIVATE_DELAY);
---- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
-@@ -499,45 +499,6 @@ void ar9002_hw_enable_async_fifo(struct 
-       }
- }
--/*
-- * If Async FIFO is enabled, the following counters change as MAC now runs
-- * at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
-- *
-- * The values below tested for ht40 2 chain.
-- * Overwrite the delay/timeouts initialized in process ini.
-- */
--void ar9002_hw_update_async_fifo(struct ath_hw *ah)
--{
--      if (AR_SREV_9287_13_OR_LATER(ah)) {
--              REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
--                        AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
--              REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
--                        AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
--              REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
--                        AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
--
--              REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
--              REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
--
--              REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
--                          AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
--              REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
--                            AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
--      }
--}
--
--/*
-- * We don't enable WEP aggregation on mac80211 but we keep this
-- * around for HAL unification purposes.
-- */
--void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
--{
--      if (AR_SREV_9287_13_OR_LATER(ah)) {
--              REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
--                          AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
--      }
--}
--
- /* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
- void ar9002_hw_attach_ops(struct ath_hw *ah)
- {
---- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
-@@ -111,7 +111,9 @@ static int ar9002_hw_set_channel(struct 
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -671,7 +671,7 @@ static int ar9003_hw_process_ini(struct 
+               REG_WRITE_ARRAY(&ah->iniModesAdditional,
+                               modesIndex, regWrites);
  
-               switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
-               case 0:
--                      if ((freq % 20) == 0)
-+                      if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
-+                              aModeRefSel = 0;
-+                      else if ((freq % 20) == 0)
-                               aModeRefSel = 3;
-                       else if ((freq % 10) == 0)
-                               aModeRefSel = 2;
-@@ -129,8 +131,9 @@ static int ar9002_hw_set_channel(struct 
-                       channelSel = CHANSEL_5G(freq);
-                       /* RefDivA setting */
--                      REG_RMW_FIELD(ah, AR_AN_SYNTH9,
--                                    AR_AN_SYNTH9_REFDIVA, refDivA);
-+                      ath9k_hw_analog_shift_rmw(ah, AR_AN_SYNTH9,
-+                                    AR_AN_SYNTH9_REFDIVA,
-+                                    AR_AN_SYNTH9_REFDIVA_S, refDivA);
-               }
-@@ -447,26 +450,27 @@ static void ar9002_olc_init(struct ath_h
- static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
-                                        struct ath9k_channel *chan)
- {
-+      int ref_div = 5;
-+      int pll_div = 0x2c;
-       u32 pll;
--      pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-+      if (chan && IS_CHAN_5GHZ(chan) && !IS_CHAN_A_FAST_CLOCK(ah, chan)) {
-+              if (AR_SREV_9280_20(ah)) {
-+                      ref_div = 10;
-+                      pll_div = 0x50;
-+              } else {
-+                      pll_div = 0x28;
-+              }
-+      }
-+
-+      pll = SM(ref_div, AR_RTC_9160_PLL_REFDIV);
-+      pll |= SM(pll_div, AR_RTC_9160_PLL_DIV);
-       if (chan && IS_CHAN_HALF_RATE(chan))
-               pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
-       else if (chan && IS_CHAN_QUARTER_RATE(chan))
-               pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
--      if (chan && IS_CHAN_5GHZ(chan)) {
--              if (IS_CHAN_A_FAST_CLOCK(ah, chan))
--                      pll = 0x142c;
--              else if (AR_SREV_9280_20(ah))
--                      pll = 0x2850;
--              else
--                      pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
--      } else {
--              pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
--      }
--
-       return pll;
- }
+-      if (AR_SREV_9300(ah))
++      if (AR_SREV_9330(ah))
+               REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
  
+       if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -87,7 +87,10 @@ static void ath9k_hw_set_clockrate(struc
-       struct ath_common *common = ath9k_hw_common(ah);
-       unsigned int clockrate;
--      if (!ah->curchan) /* should really check for CCK instead */
-+      /* AR9287 v1.3+ uses async FIFO and runs the MAC at 117 MHz */
-+      if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah))
-+              clockrate = 117;
-+      else if (!ah->curchan) /* should really check for CCK instead */
-               clockrate = ATH9K_CLOCK_RATE_CCK;
-       else if (conf->channel->band == IEEE80211_BAND_2GHZ)
-               clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM;
-@@ -99,6 +102,13 @@ static void ath9k_hw_set_clockrate(struc
-       if (conf_is_ht40(conf))
-               clockrate *= 2;
-+      if (ah->curchan) {
-+              if (IS_CHAN_HALF_RATE(ah->curchan))
-+                      clockrate /= 2;
-+              if (IS_CHAN_QUARTER_RATE(ah->curchan))
-+                      clockrate /= 4;
-+      }
-+
-       common->clockrate = clockrate;
- }
-@@ -895,6 +905,13 @@ static void ath9k_hw_init_interrupt_mask
-       }
- }
-+static void ath9k_hw_set_sifs_time(struct ath_hw *ah, u32 us)
-+{
-+      u32 val = ath9k_hw_mac_to_clks(ah, us - 2);
-+      val = min(val, (u32) 0xFFFF);
-+      REG_WRITE(ah, AR_D_GBL_IFS_SIFS, val);
-+}
-+
- static void ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
- {
-       u32 val = ath9k_hw_mac_to_clks(ah, us);
-@@ -932,25 +949,60 @@ static bool ath9k_hw_set_global_txtimeou
- void ath9k_hw_init_global_settings(struct ath_hw *ah)
- {
--      struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf;
-+      struct ath_common *common = ath9k_hw_common(ah);
-+      struct ieee80211_conf *conf = &common->hw->conf;
-+      const struct ath9k_channel *chan = ah->curchan;
-       int acktimeout;
-       int slottime;
-       int sifstime;
-+      int rx_lat = 0, tx_lat = 0, eifs = 0;
-+      u32 reg;
-       ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n",
-               ah->misc_mode);
-+      if (!chan)
-+              return;
-+
+@@ -975,7 +975,10 @@ void ath9k_hw_init_global_settings(struc
        if (ah->misc_mode != 0)
                REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode);
  
--      if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ)
--              sifstime = 16;
--      else
--              sifstime = 10;
-+      rx_lat = 37;
-+      tx_lat = 54;
-+
-+      if (IS_CHAN_HALF_RATE(chan)) {
-+              eifs = 175;
-+              rx_lat *= 2;
-+              tx_lat *= 2;
-+              if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-+                  tx_lat += 11;
-+
-+              slottime = 13;
-+              sifstime = 32;
-+      } else if (IS_CHAN_QUARTER_RATE(chan)) {
-+              eifs = 340;
-+              rx_lat *= 4;
-+              tx_lat *= 4;
-+              if (IS_CHAN_A_FAST_CLOCK(ah, chan))
-+                  tx_lat += 22;
-+
-+              slottime = 21;
-+              sifstime = 64;
-+      } else {
-+              eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS);
-+              reg = REG_READ(ah, AR_USEC);
-+              rx_lat = MS(reg, AR_USEC_RX_LAT);
-+              tx_lat = MS(reg, AR_USEC_TX_LAT);
-+
-+              slottime = ah->slottime;
-+              if (IS_CHAN_5GHZ(chan))
-+                      sifstime = 16;
-+              else
-+                      sifstime = 10;
-+      }
-       /* As defined by IEEE 802.11-2007 17.3.8.6 */
--      slottime = ah->slottime + 3 * ah->coverage_class;
--      acktimeout = slottime + sifstime;
-+      acktimeout = slottime + sifstime + 3 * ah->coverage_class;
-       /*
-        * Workaround for early ACK timeouts, add an offset to match the
-@@ -962,11 +1014,20 @@ void ath9k_hw_init_global_settings(struc
-       if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
-               acktimeout += 64 - sifstime - ah->slottime;
--      ath9k_hw_setslottime(ah, ah->slottime);
-+      ath9k_hw_set_sifs_time(ah, sifstime);
-+      ath9k_hw_setslottime(ah, slottime);
-       ath9k_hw_set_ack_timeout(ah, acktimeout);
-       ath9k_hw_set_cts_timeout(ah, acktimeout);
-       if (ah->globaltxtimeout != (u32) -1)
-               ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
-+
-+      REG_WRITE(ah, AR_D_GBL_IFS_EIFS, ath9k_hw_mac_to_clks(ah, eifs));
-+      REG_RMW(ah, AR_USEC,
-+              (common->clockrate - 1) |
-+              SM(rx_lat, AR_USEC_RX_LAT) |
-+              SM(tx_lat, AR_USEC_TX_LAT),
-+              AR_USEC_TX_LAT | AR_USEC_RX_LAT | AR_USEC_USEC);
-+
- }
- EXPORT_SYMBOL(ath9k_hw_init_global_settings);
-@@ -1570,9 +1631,13 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-       ath9k_hw_init_global_settings(ah);
--      if (!AR_SREV_9300_20_OR_LATER(ah)) {
--              ar9002_hw_update_async_fifo(ah);
--              ar9002_hw_enable_wep_aggregation(ah);
-+      if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
-+              REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
-+                          AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
-+              REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
-+                            AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
-+              REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
-+                          AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
-       }
-       REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
-@@ -1932,12 +1997,22 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_ti
- /* HW Capabilities */
- /*******************/
-+static u8 fixup_chainmask(u8 chip_chainmask, u8 eeprom_chainmask)
-+{
-+      eeprom_chainmask &= chip_chainmask;
-+      if (eeprom_chainmask)
-+              return eeprom_chainmask;
-+      else
-+              return chip_chainmask;
-+}
-+
- int ath9k_hw_fill_cap_info(struct ath_hw *ah)
- {
-       struct ath9k_hw_capabilities *pCap = &ah->caps;
-       struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
-+      unsigned int chip_chainmask;
-       u16 eeval;
-       u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
-@@ -1974,6 +2049,15 @@ int ath9k_hw_fill_cap_info(struct ath_hw
-       if (eeval & AR5416_OPFLAGS_11G)
-               pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
-+      if (AR_SREV_9485(ah) || AR_SREV_9285(ah) || AR_SREV_9330(ah))
-+              chip_chainmask = 1;
-+      else if (!AR_SREV_9280_20_OR_LATER(ah))
-+              chip_chainmask = 7;
-+      else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah))
-+              chip_chainmask = 3;
+-      rx_lat = 37;
++      if (IS_CHAN_A_FAST_CLOCK(ah, chan))
++              rx_lat = 41;
 +      else
-+              chip_chainmask = 7;
-+
-       pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
-       /*
-        * For AR9271 we will temporarilly uses the rx chainmax as read from
-@@ -1990,6 +2074,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw
-               /* Use rx_chainmask from EEPROM. */
-               pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
-+      pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
-+      pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
-+
-       ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
-       /* enable key search for every frame in an aggregate */
-@@ -2079,10 +2166,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw
-                       pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
++              rx_lat = 37;
+       tx_lat = 54;
+       if (IS_CHAN_HALF_RATE(chan)) {
+@@ -989,7 +992,7 @@ void ath9k_hw_init_global_settings(struc
+               sifstime = 32;
+       } else if (IS_CHAN_QUARTER_RATE(chan)) {
+               eifs = 340;
+-              rx_lat *= 4;
++              rx_lat = (rx_lat * 4) - 1;
+               tx_lat *= 4;
+               if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+                   tx_lat += 22;
+@@ -997,8 +1000,14 @@ void ath9k_hw_init_global_settings(struc
+               slottime = 21;
+               sifstime = 64;
        } else {
-               pCap->tx_desc_len = sizeof(struct ath_desc);
--              if (AR_SREV_9280_20(ah) &&
--                  ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <=
--                    AR5416_EEP_MINOR_VER_16) ||
--                   ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G)))
-+              if (AR_SREV_9280_20(ah))
-                       pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
-       }
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -983,8 +983,6 @@ void ath9k_hw_get_delta_slope_vals(struc
- void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
- int ar9002_hw_rf_claim(struct ath_hw *ah);
- void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
--void ar9002_hw_update_async_fifo(struct ath_hw *ah);
--void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
- /*
-  * Code specific to AR9003, we stuff these here to avoid callbacks
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -814,16 +814,19 @@ static bool ath9k_rx_accept(struct ath_c
-                           struct ath_rx_status *rx_stats,
-                           bool *decrypt_error)
- {
--#define is_mc_or_valid_tkip_keyix ((is_mc ||                  \
--              (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \
--              test_bit(rx_stats->rs_keyix, common->tkip_keymap))))
--
-+      bool is_mc, is_valid_tkip, strip_mic, mic_error = false;
-       struct ath_hw *ah = common->ah;
-       __le16 fc;
-       u8 rx_status_len = ah->caps.rx_status_len;
-       fc = hdr->frame_control;
-+      is_mc = !!is_multicast_ether_addr(hdr->addr1);
-+      is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
-+              test_bit(rx_stats->rs_keyix, common->tkip_keymap);
-+      strip_mic = is_valid_tkip && !(rx_stats->rs_status &
-+              (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));
-+
-       if (!rx_stats->rs_datalen)
-               return false;
-         /*
-@@ -838,6 +841,11 @@ static bool ath9k_rx_accept(struct ath_c
-       if (rx_stats->rs_more)
-               return true;
-+      mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
-+              !ieee80211_has_morefrags(fc) &&
-+              !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
-+              (rx_stats->rs_status & ATH9K_RXERR_MIC);
-+
-       /*
-        * The rx_stats->rs_status will not be set until the end of the
-        * chained descriptors so it can be ignored if rs_more is set. The
-@@ -845,30 +853,18 @@ static bool ath9k_rx_accept(struct ath_c
-        * descriptors.
-        */
-       if (rx_stats->rs_status != 0) {
--              if (rx_stats->rs_status & ATH9K_RXERR_CRC)
-+              if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
-                       rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
-+                      mic_error = false;
+-              eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/common->clockrate;
+-              reg = REG_READ(ah, AR_USEC);
++              if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
++                      eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
++                      reg = AR_USEC_ASYNC_FIFO;
++              } else {
++                      eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/
++                              common->clockrate;
++                      reg = REG_READ(ah, AR_USEC);
 +              }
-               if (rx_stats->rs_status & ATH9K_RXERR_PHY)
-                       return false;
+               rx_lat = MS(reg, AR_USEC_RX_LAT);
+               tx_lat = MS(reg, AR_USEC_TX_LAT);
  
-               if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
-                       *decrypt_error = true;
--              } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
--                      bool is_mc;
--                      /*
--                       * The MIC error bit is only valid if the frame
--                       * is not a control frame or fragment, and it was
--                       * decrypted using a valid TKIP key.
--                       */
--                      is_mc = !!is_multicast_ether_addr(hdr->addr1);
--
--                      if (!ieee80211_is_ctl(fc) &&
--                          !ieee80211_has_morefrags(fc) &&
--                          !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
--                          is_mc_or_valid_tkip_keyix)
--                              rxs->flag |= RX_FLAG_MMIC_ERROR;
--                      else
--                              rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
-+                      mic_error = false;
-               }
-+
-               /*
-                * Reject error frames with the exception of
-                * decryption and MIC failures. For monitor mode,
-@@ -886,6 +882,18 @@ static bool ath9k_rx_accept(struct ath_c
-                       }
-               }
-       }
-+
-+      /*
-+       * For unicast frames the MIC error bit can have false positives,
-+       * so all MIC error reports need to be validated in software.
-+       * False negatives are not common, so skip software verification
-+       * if the hardware considers the MIC valid.
-+       */
-+      if (strip_mic)
-+              rxs->flag |= RX_FLAG_MMIC_STRIPPED;
-+      else if (is_mc && mic_error)
-+              rxs->flag |= RX_FLAG_MMIC_ERROR;
-+
-       return true;
- }
-@@ -1938,6 +1946,9 @@ int ath_rx_tasklet(struct ath_softc *sc,
-                       sc->rx.rxotherant = 0;
-               }
-+              if (rxs->flag & RX_FLAG_MMIC_STRIPPED)
-+                      skb_trim(skb, skb->len - 8);
-+
-               spin_lock_irqsave(&sc->sc_pm_lock, flags);
-               if ((sc->ps_flags & (PS_WAIT_FOR_BEACON |
 --- a/drivers/net/wireless/ath/ath9k/reg.h
 +++ b/drivers/net/wireless/ath/ath9k/reg.h
-@@ -600,7 +600,6 @@
- #define AR_D_GBL_IFS_SIFS         0x1030
- #define AR_D_GBL_IFS_SIFS_M       0x0000FFFF
--#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB
- #define AR_D_GBL_IFS_SIFS_RESV0   0xFFFFFFFF
- #define AR_D_TXBLK_BASE            0x1038
-@@ -616,12 +615,10 @@
- #define AR_D_GBL_IFS_SLOT         0x1070
- #define AR_D_GBL_IFS_SLOT_M       0x0000FFFF
- #define AR_D_GBL_IFS_SLOT_RESV0   0xFFFF0000
--#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR   0x00000420
+@@ -619,6 +619,7 @@
  #define AR_D_GBL_IFS_EIFS         0x10b0
  #define AR_D_GBL_IFS_EIFS_M       0x0000FFFF
  #define AR_D_GBL_IFS_EIFS_RESV0   0xFFFF0000
--#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR   0x0000A5EB
++#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO 363
  
  #define AR_D_GBL_IFS_MISC        0x10f0
  #define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL        0x00000007
-@@ -1477,7 +1474,6 @@ enum {
- #define AR_TIME_OUT_ACK_S    0
- #define AR_TIME_OUT_CTS      0x3FFF0000
- #define AR_TIME_OUT_CTS_S    16
--#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR    0x16001D56
- #define AR_RSSI_THR          0x8018
- #define AR_RSSI_THR_MASK     0x000000FF
-@@ -1493,7 +1489,6 @@ enum {
+@@ -1503,6 +1504,7 @@ enum {
  #define AR_USEC_TX_LAT_S     14
  #define AR_USEC_RX_LAT       0x1F800000
  #define AR_USEC_RX_LAT_S     23
--#define AR_USEC_ASYNC_FIFO_DUR    0x12e00074
++#define AR_USEC_ASYNC_FIFO   0x12E00074
  
  #define AR_RESET_TSF        0x8020
  #define AR_RESET_TSF_ONCE   0x01000000
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -582,7 +582,10 @@ static bool ath_lookup_legacy(struct ath
+       tx_info = IEEE80211_SKB_CB(skb);
+       rates = tx_info->control.rates;
+-      for (i = 3; i >= 0; i--) {
++      for (i = 0; i < 4; i++) {
++              if (!rates[i].count || rates[i].idx < 0)
++                      break;
++
+               if (!(rates[i].flags & IEEE80211_TX_RC_MCS))
+                       return true;
+       }
index 1518afd..eb1c8fc 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/net/cfg80211.h
 +++ b/include/net/cfg80211.h
-@@ -1038,6 +1038,7 @@ struct cfg80211_ibss_params {
+@@ -1085,6 +1085,7 @@ struct cfg80211_ibss_params {
        u8 *ssid;
        u8 *bssid;
        struct ieee80211_channel *channel;
@@ -8,7 +8,7 @@
        u8 *ie;
        u8 ssid_len, ie_len;
        u16 beacon_interval;
-@@ -2539,6 +2540,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
+@@ -2584,6 +2585,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
                                      const u8 *bssid,
                                      const u8 *ssid, size_t ssid_len,
                                      u16 capa_mask, u16 capa_val);
  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
+@@ -4470,13 +4470,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
+@@ -441,6 +441,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
-@@ -439,6 +439,7 @@ struct ieee80211_if_ibss {
+@@ -464,6 +464,7 @@ struct ieee80211_if_ibss {
        u8 ssid_len, ie_len;
        u8 *ie;
        struct ieee80211_channel *channel;
  
        unsigned long ibss_join_req;
        /* probe response/beacon for IBSS */
-@@ -1121,6 +1122,7 @@ void ieee80211_ibss_notify_scan_complete
+@@ -1089,6 +1090,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,
                                        gfp_t gfp);
  int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
                        struct cfg80211_ibss_params *params);
-@@ -1373,6 +1375,12 @@ void ieee80211_recalc_smps(struct ieee80
+@@ -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);
  
  /* internal work items */
  void ieee80211_work_init(struct ieee80211_local *local);
-@@ -1401,6 +1409,8 @@ ieee80211_get_channel_mode(struct ieee80
+@@ -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);
  #define debug_noinline noinline
 --- a/net/mac80211/util.c
 +++ b/net/mac80211/util.c
-@@ -1007,23 +1007,8 @@ int ieee80211_build_preq_ies(struct ieee
+@@ -841,23 +841,8 @@ int ieee80211_build_preq_ies(struct ieee
                offset = noffset;
        }
  
  
        /*
         * If adding more here, adjust code in main.c
-@@ -1464,3 +1449,100 @@ size_t ieee80211_ie_split_vendor(const u
-       return pos;
+@@ -1381,3 +1366,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)
 +}
 --- a/net/mac80211/work.c
 +++ b/net/mac80211/work.c
-@@ -117,7 +117,6 @@ static void ieee80211_add_ht_ie(struct s
+@@ -118,7 +118,6 @@ static void ieee80211_add_ht_ie(struct s
        u8 *pos;
        u32 flags = channel->flags;
        u16 cap = sband->ht_cap.cap;
  
        if (!sband->ht_cap.ht_supported)
                return;
-@@ -168,34 +167,8 @@ static void ieee80211_add_ht_ie(struct s
+@@ -169,34 +168,8 @@ static void ieee80211_add_ht_ie(struct s
        }
  
        /* reserve and fill IE */
  }
  
  static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
---- a/net/wireless/scan.c
-+++ b/net/wireless/scan.c
-@@ -365,6 +365,18 @@ struct cfg80211_bss *cfg80211_get_bss(st
-                                     const u8 *ssid, size_t ssid_len,
-                                     u16 capa_mask, u16 capa_val)
- {
-+      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 channel_type)
-+{
-       struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
-       struct cfg80211_internal_bss *bss, *res = NULL;
-       unsigned long now = jiffies;
-@@ -374,8 +386,27 @@ 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 (channel_type == NL80211_CHAN_HT40MINUS ||
-+                          channel_type == NL80211_CHAN_HT40PLUS) {
-+                              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 (channel_type == NL80211_CHAN_HT40MINUS &&
-+                                            !(ht_info->ht_param &
-+                                            IEEE80211_HT_PARAM_CHA_SEC_BELOW))
-+                                      continue;
-+                              if (channel_type == 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/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -4282,13 +4282,42 @@ 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)
-               return -EINVAL;
-+#if 0
-+      if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
-+           ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
-+          !can_beacon_sec_chan(&rdev->wiphy, ibss.chan, ibss.channel_type)) {
-+              printk(KERN_DEBUG
-+                     "cfg80211: Secondary channel not "
-+                     "allowed to initiate communication\n");
-+              return -EINVAL;
-+      }
-+#endif
-+
-       ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
-       ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
---- a/net/mac80211/agg-rx.c
-+++ b/net/mac80211/agg-rx.c
-@@ -178,6 +178,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);
 --- a/net/mac80211/agg-tx.c
 +++ b/net/mac80211/agg-tx.c
 @@ -84,6 +84,8 @@ static void ieee80211_send_addba_request
                                          IEEE80211_STYPE_ACTION);
 --- a/net/mac80211/ibss.c
 +++ b/net/mac80211/ibss.c
-@@ -64,6 +64,7 @@ static void ieee80211_rx_mgmt_auth_ibss(
+@@ -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,
                                      const u32 basic_rates,
                                      const u16 capability, u64 tsf)
  {
-@@ -104,8 +105,12 @@ static void __ieee80211_sta_join_ibss(st
+@@ -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));
-+      WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));
++
++      /* 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 +176,17 @@ static void __ieee80211_sta_join_ibss(st
+@@ -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) +
        if (local->hw.queues >= 4) {
                pos = skb_put(skb, 9);
                *pos++ = WLAN_EID_VENDOR_SPECIFIC;
-@@ -219,6 +235,8 @@ static void ieee80211_sta_join_ibss(stru
+@@ -219,6 +311,8 @@ static void ieee80211_sta_join_ibss(stru
        u32 basic_rates;
        int i, j;
        u16 beacon_int = cbss->beacon_interval;
  
        lockdep_assert_held(&sdata->u.ibss.mtx);
  
-@@ -242,9 +260,15 @@ static void ieee80211_sta_join_ibss(stru
+@@ -242,9 +336,23 @@ static void ieee80211_sta_join_ibss(stru
                }
        }
  
 +      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,
                                  basic_rates,
                                  cbss->capability,
                                  cbss->tsf);
-@@ -310,11 +334,65 @@ static void ieee80211_rx_bss_info(struct
+@@ -310,11 +418,24 @@ static void ieee80211_rx_bss_info(struct
                        } else
                                sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
                                                mgmt->sa, supp_rates,
 +                      if (elems->wmm_info)
 +                              set_sta_flags(sta, WLAN_STA_WME);
 +
++                      /* remote station uses ht */
 +                      if (elems->ht_info_elem) {
-+                              struct ieee80211_supported_band *sband =
-+                                      local->hw.wiphy->bands[channel->band];
-+                              enum nl80211_channel_type channel_type;
-+
-+                              channel_type =
-+                                      ieee80211_ht_info_to_channel_type(
-+                                              elems->ht_info_elem);
-+                              if (channel_type != local->_oper_channel_type) {
-+                                      struct sk_buff *skb =
-+                                                      sdata->u.ibss.presp;
-+                                      struct sk_buff *nskb;
-+                                      u8 *ht_ie;
-+
-+                                      nskb = skb_copy(skb, GFP_ATOMIC);
-+                                      ht_ie = (u8 *) cfg80211_find_ie(
-+                                              WLAN_EID_HT_CAPABILITY,
-+                                              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,
-+                                                               channel,
-+                                                               channel_type);
-+                                      sdata->u.ibss.presp = nskb;
-+                                      kfree_skb(skb);
-+
-+                                      local->_oper_channel_type =
-+                                                              channel_type;
-+                                      WARN_ON(!ieee80211_set_channel_type(
-+                                                              local,
-+                                                              sdata,
-+                                                              channel_type));
-+                                      ieee80211_hw_config(local,
-+                                              IEEE80211_CONF_CHANGE_CHANNEL);
-+                              }
-+                              ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
-+                                                      elems->ht_cap_elem,
-+                                                      &sta->sta.ht_cap);
-+
++                              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 +482,7 @@ static void ieee80211_rx_bss_info(struct
+@@ -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,
        }
  
   put_bss:
-@@ -417,7 +495,8 @@ static void ieee80211_rx_bss_info(struct
+@@ -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,
                                        gfp_t gfp)
  {
        struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
-@@ -458,6 +537,11 @@ struct sta_info *ieee80211_ibss_add_sta(
+@@ -458,6 +580,11 @@ struct sta_info *ieee80211_ibss_add_sta(
        sta->sta.supp_rates[band] = supp_rates |
                        ieee80211_mandatory_rates(local, band);
  
        rate_control_rate_init(sta);
  
        /* If it fails, maybe we raced another insertion? */
-@@ -556,8 +640,8 @@ static void ieee80211_sta_create_ibss(st
+@@ -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,
  }
  
  /*
-@@ -594,10 +678,10 @@ static void ieee80211_sta_find_ibss(stru
+@@ -594,10 +721,10 @@ static void ieee80211_sta_find_ibss(stru
                chan = ifibss->channel;
        if (!is_zero_ether_addr(ifibss->bssid))
                bssid = ifibss->bssid;
  
        if (cbss) {
                struct ieee80211_bss *bss;
-@@ -896,10 +980,15 @@ int ieee80211_ibss_join(struct ieee80211
+@@ -896,10 +1023,15 @@ int ieee80211_ibss_join(struct ieee80211
        struct sk_buff *skb;
  
        skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
                            params->ie_len);
        if (!skb)
                return -ENOMEM;
-@@ -920,13 +1009,14 @@ int ieee80211_ibss_join(struct ieee80211
+@@ -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;
        /* 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,
+-              WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
 -                                                  NL80211_CHAN_NO_HT));
-+                                                  params->channel_type));
++              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
-@@ -2138,7 +2138,8 @@ ieee80211_rx_h_action(struct ieee80211_r
+@@ -2161,7 +2161,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 &&
                        break;
  
                /* verify action_code is present */
-@@ -2654,7 +2655,8 @@ static int prepare_for_handlers(struct i
+@@ -2696,7 +2697,8 @@ static int prepare_for_handlers(struct i
                        else
                                rate_idx = status->rate_idx;
                        rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
                }
                break;
        case NL80211_IFTYPE_MESH_POINT:
+--- a/net/mac80211/agg-rx.c
++++ b/net/mac80211/agg-rx.c
+@@ -186,6 +186,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);
diff --git a/package/mac80211/patches/400-ath_move_debug_code.patch b/package/mac80211/patches/400-ath_move_debug_code.patch
new file mode 100644 (file)
index 0000000..47f3b4a
--- /dev/null
@@ -0,0 +1,27 @@
+--- a/drivers/net/wireless/ath/Makefile
++++ b/drivers/net/wireless/ath/Makefile
+@@ -8,6 +8,5 @@ obj-$(CONFIG_ATH_COMMON)       += ath.o
+ ath-objs :=   main.o \
+               regd.o \
+               hw.o \
+-              key.o
+-
+-ath-$(CONFIG_ATH_DEBUG) += debug.o
++              key.o \
++              debug.o
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -277,13 +277,6 @@ ath_dbg(struct ath_common *common, enum 
+ #endif /* CONFIG_ATH_DEBUG */
+ /** Returns string describing opmode, or NULL if unknown mode. */
+-#ifdef CONFIG_ATH_DEBUG
+ const char *ath_opmode_to_string(enum nl80211_iftype opmode);
+-#else
+-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+-{
+-      return "UNKNOWN";
+-}
+-#endif
+ #endif /* ATH_H */
index 75e6454..0721227 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -34,7 +34,7 @@ int ath9k_modparam_nohwcrypt;
+@@ -35,7 +35,7 @@ int ath9k_modparam_nohwcrypt;
  module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
  MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
  
index 8803888..cc59b75 100644 (file)
@@ -8,7 +8,7 @@
  #include <asm/unaligned.h>
  
  #include "hw.h"
-@@ -453,8 +454,16 @@ static int ath9k_hw_init_macaddr(struct 
+@@ -460,8 +461,16 @@ static int ath9k_hw_init_macaddr(struct 
                common->macaddr[2 * i] = eeval >> 8;
                common->macaddr[2 * i + 1] = eeval & 0xff;
        }
index 597d151..582d569 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/wireless/reg.c
 +++ b/net/wireless/reg.c
-@@ -1643,6 +1643,8 @@ void regulatory_hint_11d(struct wiphy *w
+@@ -1642,6 +1642,8 @@ void regulatory_hint_11d(struct wiphy *w
        enum environment_cap env = ENVIRON_ANY;
        struct regulatory_request *request;
  
@@ -9,7 +9,7 @@
        mutex_lock(&reg_mutex);
  
        if (unlikely(!last_request))
-@@ -1849,6 +1851,8 @@ static void restore_regulatory_settings(
+@@ -1848,6 +1850,8 @@ static void restore_regulatory_settings(
  
  void regulatory_hint_disconnect(void)
  {
index fdff5dc..13f11bb 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1495,15 +1495,6 @@ static int ath9k_add_interface(struct ie
+@@ -1491,15 +1491,6 @@ static int ath9k_add_interface(struct ie
                }
        }
  
@@ -16,7 +16,7 @@
        ath_dbg(common, ATH_DBG_CONFIG,
                "Attach a VIF of type: %d\n", vif->type);
  
-@@ -1529,15 +1520,6 @@ static int ath9k_change_interface(struct
+@@ -1525,15 +1516,6 @@ static int ath9k_change_interface(struct
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
  
index a754774..65491e0 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
 +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
-@@ -95,13 +95,8 @@ ath5k_add_interface(struct ieee80211_hw 
+@@ -83,13 +83,8 @@ ath5k_add_interface(struct ieee80211_hw 
                goto end;
        }
  
@@ -9,30 +9,30 @@
 -       * We would need to operate the HW in ad-hoc mode to allow TSF updates
 -       * for the IBSS, but this breaks with additional AP or STA interfaces
 -       * at the moment. */
--      if (sc->num_adhoc_vifs ||
--          (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+-      if (ah->num_adhoc_vifs ||
+-          (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
 +      /* Don't allow more than one ad-hoc interface */
-+      if (sc->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
-               ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n");
++      if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
+               ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
                ret = -ELNRNG;
                goto end;
 --- a/drivers/net/wireless/ath/ath5k/base.c
 +++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1883,7 +1883,7 @@ ath5k_beacon_send(struct ath5k_softc *sc
-               sc->bmisscount = 0;
+@@ -1866,7 +1866,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+               ah->bmisscount = 0;
        }
  
--      if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) ||
-+      if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs + sc->num_adhoc_vifs > 1) ||
-                       sc->opmode == NL80211_IFTYPE_MESH_POINT) {
+-      if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) ||
++      if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + ah->num_adhoc_vifs > 1) ||
+                       ah->opmode == NL80211_IFTYPE_MESH_POINT) {
                u64 tsf = ath5k_hw_get_tsf64(ah);
                u32 tsftu = TSF_TO_TU(tsf);
-@@ -1961,7 +1961,7 @@ ath5k_beacon_update_timers(struct ath5k_
+@@ -1951,7 +1951,7 @@ ath5k_beacon_update_timers(struct ath5k_
        u64 hw_tsf;
  
-       intval = sc->bintval & AR5K_BEACON_PERIOD;
--      if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) {
-+      if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs + sc->num_adhoc_vifs > 1) {
+       intval = ah->bintval & AR5K_BEACON_PERIOD;
+-      if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) {
++      if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs + ah->num_adhoc_vifs > 1) {
                intval /= ATH_BCBUF;    /* staggered multi-bss beacons */
                if (intval < 15)
-                       ATH5K_WARN(sc, "intval %u is too low, min 15\n",
+                       ATH5K_WARN(ah, "intval %u is too low, min 15\n",
index e049645..8ca821c 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath5k/reset.c
 +++ b/drivers/net/wireless/ath/ath5k/reset.c
-@@ -1035,6 +1035,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, 
+@@ -1040,6 +1040,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, 
        tsf_lo = 0;
        mode = 0;
  
@@ -8,7 +8,7 @@
        /*
         * Sanity check for fast flag
         * Fast channel change only available
-@@ -1042,6 +1043,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, 
+@@ -1047,6 +1048,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, 
         */
        if (fast && (ah->ah_radio != AR5K_RF2413) &&
        (ah->ah_radio != AR5K_RF5413))
diff --git a/package/mac80211/patches/440-ath5k_calibrate_srev_checks.patch b/package/mac80211/patches/440-ath5k_calibrate_srev_checks.patch
deleted file mode 100644 (file)
index cbfdad4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/phy.c
-+++ b/drivers/net/wireless/ath/ath5k/phy.c
-@@ -1604,11 +1604,13 @@ int ath5k_hw_phy_calibrate(struct ath5k_
-       int ret;
-       if (ah->ah_radio == AR5K_RF5110)
--              ret = ath5k_hw_rf5110_calibrate(ah, channel);
--      else {
--              ret = ath5k_hw_rf511x_iq_calibrate(ah);
-+              return ath5k_hw_rf5110_calibrate(ah, channel);
-+
-+      ret = ath5k_hw_rf511x_iq_calibrate(ah);
-+
-+      if (ah->ah_radio == AR5K_RF5112 &&
-+          (channel->hw_value & (CHANNEL_5GHZ | CHANNEL_OFDM)))
-               ath5k_hw_request_rfgain_probe(ah);
--      }
-       return ret;
- }
diff --git a/package/mac80211/patches/441-ath5k_synth_voltage_srev_check.patch b/package/mac80211/patches/441-ath5k_synth_voltage_srev_check.patch
deleted file mode 100644 (file)
index d08b823..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/phy.c
-+++ b/drivers/net/wireless/ath/ath5k/phy.c
-@@ -970,17 +970,20 @@ static int ath5k_hw_rfregs_init(struct a
-                       }
-                       /* Lower synth voltage on Rev 2 */
--                      ath5k_hw_rfb_op(ah, rf_regs, 2,
--                                      AR5K_RF_HIGH_VC_CP, true);
-+                      if (ah->ah_radio == AR5K_RF5112 &&
-+                          (ah->ah_radio_5ghz_revision & AR5K_SREV_REV) > 0) {
-+                              ath5k_hw_rfb_op(ah, rf_regs, 2,
-+                                              AR5K_RF_HIGH_VC_CP, true);
--                      ath5k_hw_rfb_op(ah, rf_regs, 2,
--                                      AR5K_RF_MID_VC_CP, true);
-+                              ath5k_hw_rfb_op(ah, rf_regs, 2,
-+                                              AR5K_RF_MID_VC_CP, true);
--                      ath5k_hw_rfb_op(ah, rf_regs, 2,
--                                      AR5K_RF_LOW_VC_CP, true);
-+                              ath5k_hw_rfb_op(ah, rf_regs, 2,
-+                                              AR5K_RF_LOW_VC_CP, true);
--                      ath5k_hw_rfb_op(ah, rf_regs, 2,
--                                      AR5K_RF_PUSH_UP, true);
-+                              ath5k_hw_rfb_op(ah, rf_regs, 2,
-+                                              AR5K_RF_PUSH_UP, true);
-+                      }
-                       /* Decrease power consumption on 5213+ BaseBand */
-                       if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
diff --git a/package/mac80211/patches/442-ath5k_spur_channel_srev_check.patch b/package/mac80211/patches/442-ath5k_spur_channel_srev_check.patch
deleted file mode 100644 (file)
index 1931be8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/phy.c
-+++ b/drivers/net/wireless/ath/ath5k/phy.c
-@@ -105,6 +105,7 @@ bool ath5k_hw_chan_has_spur_noise(struct
-       if ((ah->ah_radio == AR5K_RF5112) ||
-       (ah->ah_radio == AR5K_RF5413) ||
-+      (ah->ah_radio == AR5K_RF2413) ||
-       (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)))
-               refclk_freq = 40;
-       else
diff --git a/package/mac80211/patches/443-ath5k_initialize_clockrate.patch b/package/mac80211/patches/443-ath5k_initialize_clockrate.patch
deleted file mode 100644 (file)
index fedc2f4..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/base.c
-+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -2422,6 +2422,7 @@ ath5k_init_softc(struct ath5k_softc *sc,
-       common->ah = sc->ah;
-       common->hw = hw;
-       common->priv = sc;
-+      common->clockrate = 40;
-       /*
-        * Cache line size is used to size and align various
diff --git a/package/mac80211/patches/444-ath5k_delay_calibration.patch b/package/mac80211/patches/444-ath5k_delay_calibration.patch
deleted file mode 100644 (file)
index f5dd3f2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/base.c
-+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -2728,7 +2728,7 @@ ath5k_reset(struct ath5k_softc *sc, stru
-       ath5k_ani_init(ah, ani_mode);
--      ah->ah_cal_next_full = jiffies;
-+      ah->ah_cal_next_full = jiffies + msecs_to_jiffies(100);
-       ah->ah_cal_next_ani = jiffies;
-       ah->ah_cal_next_nf = jiffies;
-       ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8);
diff --git a/package/mac80211/patches/445-ath5k_fix_mac_clock_restore.patch b/package/mac80211/patches/445-ath5k_fix_mac_clock_restore.patch
deleted file mode 100644 (file)
index e171cd1..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/reset.c
-+++ b/drivers/net/wireless/ath/ath5k/reset.c
-@@ -233,7 +233,7 @@ static void ath5k_hw_init_core_clock(str
- static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
- {
-       struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
--      u32 scal, spending;
-+      u32 scal, spending, sclock;
-       /* Only set 32KHz settings if we have an external
-        * 32KHz crystal present */
-@@ -317,6 +317,15 @@ static void ath5k_hw_set_sleep_clock(str
-               /* Set up tsf increment on each cycle */
-               AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1);
-+
-+              if ((ah->ah_radio == AR5K_RF5112) ||
-+                      (ah->ah_radio == AR5K_RF5413) ||
-+                      (ah->ah_radio == AR5K_RF2316) ||
-+                      (ah->ah_radio == AR5K_RF2317))
-+                      sclock = 40 - 1;
-+              else
-+                      sclock = 32 - 1;
-+              AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, sclock);
-       }
- }
diff --git a/package/mac80211/patches/446-ath5k_disable_32khz_clock.patch b/package/mac80211/patches/446-ath5k_disable_32khz_clock.patch
deleted file mode 100644 (file)
index 21bf037..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/reset.c
-+++ b/drivers/net/wireless/ath/ath5k/reset.c
-@@ -1287,15 +1287,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, 
-        */
-       ath5k_hw_dma_init(ah);
--
--      /* Enable 32KHz clock function for AR5212+ chips
--       * Set clocks to 32KHz operation and use an
--       * external 32KHz crystal when sleeping if one
--       * exists */
--      if (ah->ah_version == AR5K_AR5212 &&
--          op_mode != NL80211_IFTYPE_AP)
--              ath5k_hw_set_sleep_clock(ah, true);
--
-       /*
-        * Disable beacons and reset the TSF
-        */
diff --git a/package/mac80211/patches/447-ath5k_fix_queue_stop_warning.patch b/package/mac80211/patches/447-ath5k_fix_queue_stop_warning.patch
deleted file mode 100644 (file)
index ade0eef..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
---- a/drivers/net/wireless/ath/ath5k/base.c
-+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1555,7 +1555,8 @@ ath5k_tx_queue(struct ieee80211_hw *hw, 
-               goto drop_packet;
-       }
--      if (txq->txq_len >= txq->txq_max)
-+      if (txq->txq_len >= txq->txq_max &&
-+          txq->qnum <= AR5K_TX_QUEUE_ID_DATA_MAX)
-               ieee80211_stop_queue(hw, txq->qnum);
-       spin_lock_irqsave(&sc->txbuflock, flags);
-@@ -1931,6 +1932,10 @@ ath5k_beacon_send(struct ath5k_softc *sc
-       skb = ieee80211_get_buffered_bc(sc->hw, vif);
-       while (skb) {
-               ath5k_tx_queue(sc->hw, skb, sc->cabq);
-+
-+              if (sc->cabq->txq_len >= sc->cabq->txq_max)
-+                      break;
-+
-               skb = ieee80211_get_buffered_bc(sc->hw, vif);
-       }
index df11fe4..742088c 100644 (file)
@@ -1,7 +1,7 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1181,6 +1181,53 @@ static const struct file_operations fops
-       .llseek = default_llseek,/* read accesses f_pos */
+@@ -1272,6 +1272,53 @@ static const struct file_operations fops
+       .llseek = default_llseek,
  };
  
 +static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
@@ -54,7 +54,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
-@@ -1231,6 +1278,9 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1328,6 +1375,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);
  
index d93686c..6c29e9c 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1656,8 +1656,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1674,8 +1674,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
        REG_WRITE(ah, AR_OBS, 8);
  
        if (ah->config.rx_intr_mitigation) {
index 0b829ec..2931a5e 100644 (file)
@@ -1,6 +1,6 @@
 --- 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
@@ -11,7 +11,7 @@
  #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
-@@ -374,8 +374,8 @@ static void ath9k_hw_init_config(struct 
+@@ -382,8 +382,8 @@ static void ath9k_hw_init_config(struct 
  {
        int i;
  
index 2384931..7451e61 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -117,7 +117,7 @@ void ath_descdma_cleanup(struct ath_soft
+@@ -123,7 +123,7 @@ void ath_descdma_cleanup(struct ath_soft
  /* RX / TX */
  /***********/
  
index 28251ee..b144af4 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -586,6 +586,7 @@ struct ath_softc {
+@@ -587,6 +587,7 @@ struct ath_softc {
        struct ieee80211_hw *hw;
        struct device *dev;
  
@@ -10,7 +10,7 @@
        struct survey_info *cur_survey;
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1281,6 +1281,9 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1378,6 +1378,9 @@ int ath9k_init_debug(struct ath_hw *ah)
        debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_eeprom);
  
  }
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -226,6 +226,7 @@ static int ath_set_channel(struct ath_so
-       bool fastcc = true, stopped;
-       struct ieee80211_channel *channel = hw->conf.channel;
-       struct ath9k_hw_cal_data *caldata = NULL;
-+      u32 oldflags;
-       int r;
+@@ -1654,9 +1654,10 @@ static int ath9k_config(struct ieee80211
  
-       if (sc->sc_flags & SC_OP_INVALID)
-@@ -268,6 +269,24 @@ static int ath_set_channel(struct ath_so
-       if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
-               fastcc = false;
+       if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+               struct ieee80211_channel *curchan = hw->conf.channel;
+-              struct ath9k_channel old_chan;
++              struct ath9k_channel old_chan, *hchan;
+               int pos = curchan->hw_value;
+               int old_pos = -1;
++              u32 oldflags;
+               unsigned long flags;
  
-+      oldflags = hchan->channelFlags;
-+      switch (sc->chan_bw) {
-+      case 5:
-+              hchan->channelFlags &= ~CHANNEL_HALF;
-+              hchan->channelFlags |= CHANNEL_QUARTER;
-+              break;
-+      case 10:
-+              hchan->channelFlags &= ~CHANNEL_QUARTER;
-+              hchan->channelFlags |= CHANNEL_HALF;
-+              break;
-+      default:
-+              hchan->channelFlags &= ~(CHANNEL_HALF | CHANNEL_QUARTER);
-+              break;
-+      }
-+
-+      if (oldflags != hchan->channelFlags)
-+              fastcc = false;
+               if (ah->curchan)
+@@ -1709,7 +1710,23 @@ static int ath9k_config(struct ieee80211
+                       memset(&sc->survey[pos], 0, sizeof(struct survey_info));
+               }
+-              if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
++              hchan = &sc->sc_ah->channels[pos];
++              oldflags = hchan->channelFlags;
++              switch (sc->chan_bw) {
++              case 5:
++                      hchan->channelFlags &= ~CHANNEL_HALF;
++                      hchan->channelFlags |= CHANNEL_QUARTER;
++                      break;
++              case 10:
++                      hchan->channelFlags &= ~CHANNEL_QUARTER;
++                      hchan->channelFlags |= CHANNEL_HALF;
++                      break;
++              default:
++                      hchan->channelFlags &= ~(CHANNEL_HALF | CHANNEL_QUARTER);
++                      break;
++              }
 +
-       if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
-               caldata = &sc->caldata;
++              if (ath_set_channel(sc, hw, hchan) < 0) {
+                       ath_err(common, "Unable to set channel\n");
+                       mutex_unlock(&sc->mutex);
+                       return -EINVAL;
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1507,6 +1507,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+       }
+       ah->noise = ath9k_hw_getchan_noise(ah, chan);
  
++      if (!ah->curchan || ((ah->curchan->channelFlags ^ chan->channelFlags) &
++          (CHANNEL_HALF | CHANNEL_QUARTER)))
++              bChannelChange = false;
++
+       if (bChannelChange &&
+           (ah->chip_fullsleep != true) &&
+           (ah->curchan != NULL) &&
diff --git a/package/mac80211/patches/530-ath9k_noise_dbm_fixup.patch b/package/mac80211/patches/530-ath9k_noise_dbm_fixup.patch
deleted file mode 100644 (file)
index 4e9f387..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/calib.c
-+++ b/drivers/net/wireless/ath/ath9k/calib.c
-@@ -63,6 +63,19 @@ static s16 ath9k_hw_get_default_nf(struc
-       return ath9k_hw_get_nf_limits(ah, chan)->nominal;
- }
-+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
-+{
-+      s8 noise = ATH_DEFAULT_NOISE_FLOOR;
-+
-+      if (chan && chan->noisefloor) {
-+              s8 delta = chan->noisefloor -
-+                         ath9k_hw_get_default_nf(ah, chan);
-+              if (delta > 0)
-+                      noise += delta;
-+      }
-+      return noise;
-+}
-+EXPORT_SYMBOL(ath9k_hw_getchan_noise);
- static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
-                                             struct ath9k_hw_cal_data *cal,
-@@ -378,6 +391,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
-       if (!caldata) {
-               chan->noisefloor = nf;
-+              ah->noise = ath9k_hw_getchan_noise(ah, chan);
-               return false;
-       }
-@@ -385,6 +399,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, s
-       caldata->nfcal_pending = false;
-       ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
-       chan->noisefloor = h[0].privNF;
-+      ah->noise = ath9k_hw_getchan_noise(ah, chan);
-       return true;
- }
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1488,6 +1488,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-               memset(caldata, 0, sizeof(*caldata));
-               ath9k_init_nfcal_hist_buffer(ah, chan);
-       }
-+      ah->noise = ath9k_hw_getchan_noise(ah, chan);
-       if (bChannelChange &&
-           (ah->chip_fullsleep != true) &&
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -688,6 +688,7 @@ struct ath_hw {
-       enum nl80211_iftype opmode;
-       enum ath9k_power_mode power_mode;
-+      s8 noise;
-       struct ath9k_hw_cal_data *caldata;
-       struct ath9k_pacal_info pacal_info;
-       struct ar5416Stats stats;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -163,7 +163,7 @@ static void ath_update_survey_nf(struct 
-       if (chan->noisefloor) {
-               survey->filled |= SURVEY_INFO_NOISE_DBM;
--              survey->noise = chan->noisefloor;
-+              survey->noise = ath9k_hw_getchan_noise(ah, chan);
-       }
- }
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -994,6 +994,8 @@ static int ath9k_rx_skb_preprocess(struc
-                                  struct ieee80211_rx_status *rx_status,
-                                  bool *decrypt_error)
- {
-+      struct ath_hw *ah = common->ah;
-+
-       memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
-       /*
-@@ -1014,7 +1016,7 @@ static int ath9k_rx_skb_preprocess(struc
-       rx_status->band = hw->conf.channel->band;
-       rx_status->freq = hw->conf.channel->center_freq;
--      rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
-+      rx_status->signal = ah->noise + rx_stats->rs_rssi;
-       rx_status->antenna = rx_stats->rs_antenna;
-       rx_status->flag |= RX_FLAG_MACTIME_MPDU;
---- a/drivers/net/wireless/ath/ath9k/calib.h
-+++ b/drivers/net/wireless/ath/ath9k/calib.h
-@@ -108,6 +108,7 @@ void ath9k_init_nfcal_hist_buffer(struct
- void ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
- void ath9k_hw_reset_calibration(struct ath_hw *ah,
-                               struct ath9k_cal_list *currCal);
-+s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
- #endif /* CALIB_H */
@@ -1,6 +1,6 @@
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -779,7 +779,7 @@ enum ieee80211_smps_mode {
+@@ -790,7 +790,7 @@ enum ieee80211_smps_mode {
   */
  struct ieee80211_conf {
        u32 flags;
@@ -11,7 +11,7 @@
        u16 listen_interval;
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -1524,7 +1524,7 @@ static int ieee80211_get_tx_power(struct
+@@ -1551,7 +1551,7 @@ static int ieee80211_get_tx_power(struct
  {
        struct ieee80211_local *local = wiphy_priv(wiphy);
  
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1727,6 +1727,8 @@ static int ath9k_config(struct ieee80211
+@@ -1732,6 +1732,8 @@ static int ath9k_config(struct ieee80211
                        return -EINVAL;
                }
  
@@ -9,7 +9,7 @@
                /*
                 * The most recent snapshot of channel->noisefloor for the old
                 * channel is only available after the hardware reset. Copy it to
-@@ -1744,6 +1746,7 @@ static int ath9k_config(struct ieee80211
+@@ -1749,6 +1751,7 @@ static int ath9k_config(struct ieee80211
                ath9k_cmn_update_txpow(ah, sc->curtxpow,
                                       sc->config.txpowlimit, &sc->curtxpow);
                ath9k_ps_restore(sc);
diff --git a/package/mac80211/patches/540-ath9k_rx_stop.patch b/package/mac80211/patches/540-ath9k_rx_stop.patch
deleted file mode 100644 (file)
index 17c4c28..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -737,7 +737,9 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
-               if (!AR_SREV_9300_20_OR_LATER(ah)) {
-                       mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
--                      if (mac_status == 0x1c0 && mac_status == last_mac_status) {
-+                      if (mac_status == last_mac_status &&
-+                          (mac_status == 0x1c0 ||
-+                           (AR_SREV_9100(ah) && mac_status == 0x020))) {
-                               *reset = true;
-                               break;
-                       }
diff --git a/package/mac80211/patches/540-ath9k_txkeyidx_u8.patch b/package/mac80211/patches/540-ath9k_txkeyidx_u8.patch
new file mode 100644 (file)
index 0000000..2b59533
--- /dev/null
@@ -0,0 +1,56 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+@@ -273,7 +273,7 @@ static int ar9002_hw_proc_txdesc(struct 
+ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
+                                   u32 pktLen, enum ath9k_pkt_type type,
+-                                  u32 txPower, u32 keyIx,
++                                  u32 txPower, u8 keyIx,
+                                   enum ath9k_key_type keyType, u32 flags)
+ {
+       struct ar5416_desc *ads = AR5416DESC(ds);
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -207,8 +207,8 @@ struct ath_atx_ac {
+ struct ath_frame_info {
+       int framelen;
+-      u32 keyix;
+       enum ath9k_key_type keytype;
++      u8 keyix;
+       u8 retries;
+       u16 seqno;
+ };
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -623,7 +623,7 @@ struct ath_hw_ops {
+                          struct ath_tx_status *ts);
+       void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
+                             u32 pktLen, enum ath9k_pkt_type type,
+-                            u32 txPower, u32 keyIx,
++                            u32 txPower, u8 keyIx,
+                             enum ath9k_key_type keyType,
+                             u32 flags);
+       void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -194,7 +194,7 @@ struct ath_htc_rx_status {
+ #define ATH9K_RX_DECRYPT_BUSY     0x40
+ #define ATH9K_RXKEYIX_INVALID ((u8)-1)
+-#define ATH9K_TXKEYIX_INVALID ((u32)-1)
++#define ATH9K_TXKEYIX_INVALID ((u8)-1)
+ enum ath9k_phyerr {
+       ATH9K_PHYERR_UNDERRUN             = 0,  /* Transmit underrun */
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+@@ -312,7 +312,7 @@ static int ar9003_hw_proc_txdesc(struct 
+ static void ar9003_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)
++              u8 keyIx, enum ath9k_key_type keyType, u32 flags)
+ {
+       struct ar9003_txc *ads = (struct ar9003_txc *) ds;
diff --git a/package/mac80211/patches/541-ath9k_aggr_queue_cleanup.patch b/package/mac80211/patches/541-ath9k_aggr_queue_cleanup.patch
new file mode 100644 (file)
index 0000000..27c144f
--- /dev/null
@@ -0,0 +1,281 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -206,6 +206,7 @@ struct ath_atx_ac {
+ };
+ struct ath_frame_info {
++      struct ath_buf *bf;
+       int framelen;
+       enum ath9k_key_type keytype;
+       u8 keyix;
+@@ -235,7 +236,7 @@ struct ath_buf {
+ struct ath_atx_tid {
+       struct list_head list;
+-      struct list_head buf_q;
++      struct sk_buff_head buf_q;
+       struct ath_node *an;
+       struct ath_atx_ac *ac;
+       unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -711,7 +711,7 @@ static ssize_t read_file_stations(struct
+                                       " tid: %p %s %s %i %p %p\n",
+                                       tid, tid->sched ? "sched" : "idle",
+                                       tid->paused ? "paused" : "running",
+-                                      list_empty(&tid->buf_q),
++                                      skb_queue_empty(&tid->buf_q),
+                                       tid->an, tid->ac);
+                       if (len >= size)
+                               goto done;
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -129,7 +129,7 @@ static void ath_tx_resume_tid(struct ath
+       spin_lock_bh(&txq->axq_lock);
+       tid->paused = false;
+-      if (list_empty(&tid->buf_q))
++      if (skb_queue_empty(&tid->buf_q))
+               goto unlock;
+       ath_tx_queue_tid(txq, tid);
+@@ -149,6 +149,7 @@ static struct ath_frame_info *get_frame_
+ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+ {
+       struct ath_txq *txq = tid->ac->txq;
++      struct sk_buff *skb;
+       struct ath_buf *bf;
+       struct list_head bf_head;
+       struct ath_tx_status ts;
+@@ -159,12 +160,13 @@ static void ath_tx_flush_tid(struct ath_
+       memset(&ts, 0, sizeof(ts));
+       spin_lock_bh(&txq->axq_lock);
+-      while (!list_empty(&tid->buf_q)) {
+-              bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+-              list_move_tail(&bf->list, &bf_head);
++      while ((skb = __skb_dequeue(&tid->buf_q))) {
++              fi = get_frame_info(skb);
++              bf = fi->bf;
++
++              list_add_tail(&bf->list, &bf_head);
+               spin_unlock_bh(&txq->axq_lock);
+-              fi = get_frame_info(bf->bf_mpdu);
+               if (fi->retries) {
+                       ath_tx_update_baw(sc, tid, fi->seqno);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
+@@ -219,6 +221,7 @@ static void ath_tid_drain(struct ath_sof
+                         struct ath_atx_tid *tid)
+ {
++      struct sk_buff *skb;
+       struct ath_buf *bf;
+       struct list_head bf_head;
+       struct ath_tx_status ts;
+@@ -227,14 +230,12 @@ static void ath_tid_drain(struct ath_sof
+       memset(&ts, 0, sizeof(ts));
+       INIT_LIST_HEAD(&bf_head);
+-      for (;;) {
+-              if (list_empty(&tid->buf_q))
+-                      break;
++      while ((skb = __skb_dequeue(&tid->buf_q))) {
++              fi = get_frame_info(skb);
++              bf = fi->bf;
+-              bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+-              list_move_tail(&bf->list, &bf_head);
++              list_add_tail(&bf->list, &bf_head);
+-              fi = get_frame_info(bf->bf_mpdu);
+               if (fi->retries)
+                       ath_tx_update_baw(sc, tid, fi->seqno);
+@@ -349,7 +350,8 @@ static void ath_tx_complete_aggr(struct 
+       struct ieee80211_tx_info *tx_info;
+       struct ath_atx_tid *tid = NULL;
+       struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
+-      struct list_head bf_head, bf_pending;
++      struct list_head bf_head;
++      struct sk_buff_head bf_pending;
+       u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
+       u32 ba[WME_BA_BMP_SIZE >> 5];
+       int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
+@@ -422,8 +424,7 @@ static void ath_tx_complete_aggr(struct 
+               }
+       }
+-      INIT_LIST_HEAD(&bf_pending);
+-      INIT_LIST_HEAD(&bf_head);
++      __skb_queue_head_init(&bf_pending);
+       ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
+       while (bf) {
+@@ -467,10 +468,10 @@ static void ath_tx_complete_aggr(struct 
+                * Make sure the last desc is reclaimed if it
+                * not a holding desc.
+                */
+-              if (!bf_last->bf_stale || bf_next != NULL)
++              INIT_LIST_HEAD(&bf_head);
++              if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ||
++                  bf_next != NULL || !bf_last->bf_stale)
+                       list_move_tail(&bf->list, &bf_head);
+-              else
+-                      INIT_LIST_HEAD(&bf_head);
+               if (!txpending || (tid->state & AGGR_CLEANUP)) {
+                       /*
+@@ -521,7 +522,7 @@ static void ath_tx_complete_aggr(struct 
+                                       ath9k_hw_cleartxdesc(sc->sc_ah,
+                                                            tbf->bf_desc);
+-                                      list_add_tail(&tbf->list, &bf_head);
++                                      fi->bf = tbf;
+                               } else {
+                                       /*
+                                        * Clear descriptor status words for
+@@ -536,21 +537,21 @@ static void ath_tx_complete_aggr(struct 
+                        * Put this buffer to the temporary pending
+                        * queue to retain ordering
+                        */
+-                      list_splice_tail_init(&bf_head, &bf_pending);
++                      __skb_queue_tail(&bf_pending, skb);
+               }
+               bf = bf_next;
+       }
+       /* prepend un-acked frames to the beginning of the pending frame queue */
+-      if (!list_empty(&bf_pending)) {
++      if (!skb_queue_empty(&bf_pending)) {
+               if (an->sleeping)
+                       ieee80211_sta_set_tim(sta);
+               spin_lock_bh(&txq->axq_lock);
+               if (clear_filter)
+                       tid->ac->clear_ps_filter = true;
+-              list_splice(&bf_pending, &tid->buf_q);
++              skb_queue_splice(&bf_pending, &tid->buf_q);
+               if (!an->sleeping)
+                       ath_tx_queue_tid(txq, tid);
+               spin_unlock_bh(&txq->axq_lock);
+@@ -743,19 +744,22 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+                                            int *aggr_len)
+ {
+ #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
+-      struct ath_buf *bf, *bf_first, *bf_prev = NULL;
++      struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
+       int rl = 0, nframes = 0, ndelim, prev_al = 0;
+       u16 aggr_limit = 0, al = 0, bpad = 0,
+               al_delta, h_baw = tid->baw_size / 2;
+       enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
+       struct ieee80211_tx_info *tx_info;
+       struct ath_frame_info *fi;
+-
+-      bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list);
++      struct sk_buff *skb;
+       do {
+-              bf = list_first_entry(&tid->buf_q, struct ath_buf, list);
+-              fi = get_frame_info(bf->bf_mpdu);
++              skb = skb_peek(&tid->buf_q);
++              fi = get_frame_info(skb);
++              bf = fi->bf;
++
++              if (!bf_first)
++                      bf_first = bf;
+               /* do not step over block-ack window */
+               if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
+@@ -808,7 +812,9 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+               if (!fi->retries)
+                       ath_tx_addto_baw(sc, tid, fi->seqno);
+               ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
+-              list_move_tail(&bf->list, bf_q);
++
++              __skb_unlink(skb, &tid->buf_q);
++              list_add_tail(&bf->list, bf_q);
+               if (bf_prev) {
+                       bf_prev->bf_next = bf;
+                       ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
+@@ -816,7 +822,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+               }
+               bf_prev = bf;
+-      } while (!list_empty(&tid->buf_q));
++      } while (!skb_queue_empty(&tid->buf_q));
+       *aggr_len = al;
+@@ -834,7 +840,7 @@ static void ath_tx_sched_aggr(struct ath
+       int aggr_len;
+       do {
+-              if (list_empty(&tid->buf_q))
++              if (skb_queue_empty(&tid->buf_q))
+                       return;
+               INIT_LIST_HEAD(&bf_q);
+@@ -955,7 +961,7 @@ bool ath_tx_aggr_sleep(struct ath_softc 
+               spin_lock_bh(&txq->axq_lock);
+-              if (!list_empty(&tid->buf_q))
++              if (!skb_queue_empty(&tid->buf_q))
+                       buffered = true;
+               tid->sched = false;
+@@ -988,7 +994,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
+               spin_lock_bh(&txq->axq_lock);
+               ac->clear_ps_filter = true;
+-              if (!list_empty(&tid->buf_q) && !tid->paused) {
++              if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
+                       ath_tx_queue_tid(txq, tid);
+                       ath_txq_schedule(sc, txq);
+               }
+@@ -1332,7 +1338,7 @@ void ath_txq_schedule(struct ath_softc *
+                        * add tid to round-robin queue if more frames
+                        * are pending for the tid
+                        */
+-                      if (!list_empty(&tid->buf_q))
++                      if (!skb_queue_empty(&tid->buf_q))
+                               ath_tx_queue_tid(txq, tid);
+                       if (tid == last_tid ||
+@@ -1438,7 +1444,7 @@ static void ath_tx_send_ampdu(struct ath
+        * - seqno is not within block-ack window
+        * - h/w queue depth exceeds low water mark
+        */
+-      if (!list_empty(&tid->buf_q) || tid->paused ||
++      if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
+           !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
+           txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
+               /*
+@@ -1446,7 +1452,7 @@ static void ath_tx_send_ampdu(struct ath
+                * for aggregation.
+                */
+               TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
+-              list_add_tail(&bf->list, &tid->buf_q);
++              __skb_queue_tail(&tid->buf_q, bf->bf_mpdu);
+               if (!txctl->an || !txctl->an->sleeping)
+                       ath_tx_queue_tid(txctl->txq, tid);
+               return;
+@@ -1777,6 +1783,7 @@ static struct ath_buf *ath_tx_setup_buff
+                           bf->bf_buf_addr,
+                           txq->axq_qnum);
++      fi->bf = bf;
+       return bf;
+ }
+@@ -2394,7 +2401,7 @@ void ath_tx_node_init(struct ath_softc *
+               tid->sched     = false;
+               tid->paused    = false;
+               tid->state &= ~AGGR_CLEANUP;
+-              INIT_LIST_HEAD(&tid->buf_q);
++              __skb_queue_head_init(&tid->buf_q);
+               acno = TID_TO_WME_AC(tidno);
+               tid->ac = &an->ac[acno];
+               tid->state &= ~AGGR_ADDBA_COMPLETE;
diff --git a/package/mac80211/patches/542-ath9k_move_seqno.patch b/package/mac80211/patches/542-ath9k_move_seqno.patch
new file mode 100644 (file)
index 0000000..c0d293a
--- /dev/null
@@ -0,0 +1,207 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -211,12 +211,12 @@ struct ath_frame_info {
+       enum ath9k_key_type keytype;
+       u8 keyix;
+       u8 retries;
+-      u16 seqno;
+ };
+ struct ath_buf_state {
+       u8 bf_type;
+       u8 bfs_paprd;
++      u16 seqno;
+       unsigned long bfs_paprd_timestamp;
+ };
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -168,7 +168,7 @@ static void ath_tx_flush_tid(struct ath_
+               spin_unlock_bh(&txq->axq_lock);
+               if (fi->retries) {
+-                      ath_tx_update_baw(sc, tid, fi->seqno);
++                      ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
+               } else {
+                       ath_tx_send_normal(sc, txq, NULL, &bf_head);
+@@ -237,7 +237,7 @@ static void ath_tid_drain(struct ath_sof
+               list_add_tail(&bf->list, &bf_head);
+               if (fi->retries)
+-                      ath_tx_update_baw(sc, tid, fi->seqno);
++                      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);
+@@ -327,7 +327,7 @@ static void ath_tx_count_frames(struct a
+       while (bf) {
+               fi = get_frame_info(bf->bf_mpdu);
+-              ba_index = ATH_BA_INDEX(seq_st, fi->seqno);
++              ba_index = ATH_BA_INDEX(seq_st, bf->bf_state.seqno);
+               (*nframes)++;
+               if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index)))
+@@ -428,6 +428,8 @@ static void ath_tx_complete_aggr(struct 
+       ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
+       while (bf) {
++              u16 seqno = bf->bf_state.seqno;
++
+               txfail = txpending = sendbar = 0;
+               bf_next = bf->bf_next;
+@@ -435,7 +437,7 @@ static void ath_tx_complete_aggr(struct 
+               tx_info = IEEE80211_SKB_CB(skb);
+               fi = get_frame_info(skb);
+-              if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) {
++              if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) {
+                       /* transmit completion, subframe is
+                        * acked by block ack */
+                       acked_cnt++;
+@@ -479,7 +481,7 @@ static void ath_tx_complete_aggr(struct 
+                        * block-ack window
+                        */
+                       spin_lock_bh(&txq->axq_lock);
+-                      ath_tx_update_baw(sc, tid, fi->seqno);
++                      ath_tx_update_baw(sc, tid, seqno);
+                       spin_unlock_bh(&txq->axq_lock);
+                       if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+@@ -507,7 +509,7 @@ static void ath_tx_complete_aggr(struct 
+                                        */
+                                       if (!tbf) {
+                                               spin_lock_bh(&txq->axq_lock);
+-                                              ath_tx_update_baw(sc, tid, fi->seqno);
++                                              ath_tx_update_baw(sc, tid, seqno);
+                                               spin_unlock_bh(&txq->axq_lock);
+                                               bf->bf_state.bf_type |=
+@@ -752,17 +754,19 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+       struct ieee80211_tx_info *tx_info;
+       struct ath_frame_info *fi;
+       struct sk_buff *skb;
++      u16 seqno;
+       do {
+               skb = skb_peek(&tid->buf_q);
+               fi = get_frame_info(skb);
+               bf = fi->bf;
++              seqno = bf->bf_state.seqno;
+               if (!bf_first)
+                       bf_first = bf;
+               /* do not step over block-ack window */
+-              if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) {
++              if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
+                       status = ATH_AGGR_BAW_CLOSED;
+                       break;
+               }
+@@ -810,7 +814,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+               /* link buffers of this frame to the aggregate */
+               if (!fi->retries)
+-                      ath_tx_addto_baw(sc, tid, fi->seqno);
++                      ath_tx_addto_baw(sc, tid, seqno);
+               ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
+               __skb_unlink(skb, &tid->buf_q);
+@@ -1434,6 +1438,7 @@ static void ath_tx_send_ampdu(struct ath
+ {
+       struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
+       struct list_head bf_head;
++      u16 seqno = bf->bf_state.seqno;
+       bf->bf_state.bf_type |= BUF_AMPDU;
+@@ -1445,7 +1450,7 @@ static void ath_tx_send_ampdu(struct ath
+        * - h/w queue depth exceeds low water mark
+        */
+       if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
+-          !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
++          !BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) ||
+           txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
+               /*
+                * Add this frame to software queue for scheduling later
+@@ -1463,7 +1468,7 @@ static void ath_tx_send_ampdu(struct ath
+       /* Add sub-frame to BAW */
+       if (!fi->retries)
+-              ath_tx_addto_baw(sc, tid, fi->seqno);
++              ath_tx_addto_baw(sc, tid, seqno);
+       /* Queue to h/w without aggregation */
+       TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
+@@ -1519,39 +1524,19 @@ static enum ath9k_pkt_type get_hw_packet
+ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
+                            int framelen)
+ {
+-      struct ath_softc *sc = hw->priv;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_sta *sta = tx_info->control.sta;
+       struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
+-      struct ieee80211_hdr *hdr;
++      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ath_frame_info *fi = get_frame_info(skb);
+       struct ath_node *an = NULL;
+-      struct ath_atx_tid *tid;
+       enum ath9k_key_type keytype;
+-      u16 seqno = 0;
+-      u8 tidno;
+       keytype = ath9k_cmn_get_hw_crypto_keytype(skb);
+       if (sta)
+               an = (struct ath_node *) sta->drv_priv;
+-      hdr = (struct ieee80211_hdr *)skb->data;
+-      if (an && ieee80211_is_data_qos(hdr->frame_control) &&
+-              conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) {
+-
+-              tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
+-
+-              /*
+-               * Override seqno set by upper layer with the one
+-               * in tx aggregation state.
+-               */
+-              tid = ATH_AN_2_TID(an, tidno);
+-              seqno = tid->seq_next;
+-              hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+-              INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+-      }
+-
+       memset(fi, 0, sizeof(*fi));
+       if (hw_key)
+               fi->keyix = hw_key->hw_key_idx;
+@@ -1561,7 +1546,6 @@ static void setup_frame_info(struct ieee
+               fi->keyix = ATH9K_TXKEYIX_INVALID;
+       fi->keytype = keytype;
+       fi->framelen = framelen;
+-      fi->seqno = seqno;
+ }
+ static int setup_tx_flags(struct sk_buff *skb)
+@@ -1797,6 +1781,7 @@ static void ath_tx_start_dma(struct ath_
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct list_head bf_head;
+       struct ath_atx_tid *tid = NULL;
++      u16 seqno;
+       u8 tidno;
+       spin_lock_bh(&txctl->txq->axq_lock);
+@@ -1806,6 +1791,12 @@ static void ath_tx_start_dma(struct ath_
+                       IEEE80211_QOS_CTL_TID_MASK;
+               tid = ATH_AN_2_TID(txctl->an, tidno);
++              seqno = tid->seq_next;
++              hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
++              INCR(tid->seq_next, IEEE80211_SEQ_MAX);
++
++              bf->bf_state.seqno = seqno;
++
+               WARN_ON(tid->ac->txq != txctl->txq);
+       }
diff --git a/package/mac80211/patches/543-ath9k_move_seqno_alloc.patch b/package/mac80211/patches/543-ath9k_move_seqno_alloc.patch
new file mode 100644 (file)
index 0000000..8de5fd2
--- /dev/null
@@ -0,0 +1,119 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1717,17 +1717,19 @@ static void ath_buf_set_rate(struct ath_
+ }
+-static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
++static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+                                          struct ath_txq *txq,
++                                         struct ath_atx_tid *tid,
+                                          struct sk_buff *skb)
+ {
+-      struct ath_softc *sc = hw->priv;
+       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);
+       if (!bf) {
+@@ -1737,6 +1739,13 @@ static struct ath_buf *ath_tx_setup_buff
+       ATH_TXBUF_RESET(bf);
++      if (tid) {
++              seqno = tid->seq_next;
++              hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
++              INCR(tid->seq_next, IEEE80211_SEQ_MAX);
++              bf->bf_state.seqno = seqno;
++      }
++
+       bf->bf_flags = setup_tx_flags(skb);
+       bf->bf_mpdu = skb;
+@@ -1773,15 +1782,15 @@ static struct ath_buf *ath_tx_setup_buff
+ }
+ /* FIXME: tx power */
+-static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
++static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
+                            struct ath_tx_control *txctl)
+ {
+-      struct sk_buff *skb = bf->bf_mpdu;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct list_head bf_head;
+       struct ath_atx_tid *tid = NULL;
+-      u16 seqno;
++      struct ath_buf *bf;
++      int ret = 0;
+       u8 tidno;
+       spin_lock_bh(&txctl->txq->axq_lock);
+@@ -1791,15 +1800,15 @@ static void ath_tx_start_dma(struct ath_
+                       IEEE80211_QOS_CTL_TID_MASK;
+               tid = ATH_AN_2_TID(txctl->an, tidno);
+-              seqno = tid->seq_next;
+-              hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
+-              INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+-
+-              bf->bf_state.seqno = seqno;
+-
+               WARN_ON(tid->ac->txq != txctl->txq);
+       }
++      bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
++      if (unlikely(!bf)) {
++              ret = -ENOMEM;
++              goto out;
++      }
++
+       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+               /*
+                * Try aggregation if it's a unicast data frame
+@@ -1825,7 +1834,9 @@ static void ath_tx_start_dma(struct ath_
+               ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
+       }
++out:
+       spin_unlock_bh(&txctl->txq->axq_lock);
++      return ret;
+ }
+ /* Upon failure caller should free skb */
+@@ -1838,7 +1849,6 @@ 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;
+-      struct ath_buf *bf;
+       int padpos, padsize;
+       int frmlen = skb->len + FCS_LEN;
+       int q;
+@@ -1885,10 +1895,6 @@ int ath_tx_start(struct ieee80211_hw *hw
+        * info are no longer valid (overwritten by the ath_frame_info data.
+        */
+-      bf = ath_tx_setup_buffer(hw, txctl->txq, skb);
+-      if (unlikely(!bf))
+-              return -ENOMEM;
+-
+       q = skb_get_queue_mapping(skb);
+       spin_lock_bh(&txq->axq_lock);
+       if (txq == sc->tx.txq_map[q] &&
+@@ -1898,9 +1904,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+       }
+       spin_unlock_bh(&txq->axq_lock);
+-      ath_tx_start_dma(sc, bf, txctl);
+-
+-      return 0;
++      return ath_tx_start_dma(sc, skb, txctl);
+ }
+ /*****************/
diff --git a/package/mac80211/patches/544-ath9k_defer_buffer_setup.patch b/package/mac80211/patches/544-ath9k_defer_buffer_setup.patch
new file mode 100644 (file)
index 0000000..d91ced0
--- /dev/null
@@ -0,0 +1,264 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -48,8 +48,9 @@ static u16 bits_per_symbol[][2] = {
+ #define IS_HT_RATE(_rate)     ((_rate) & 0x80)
+ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+-                             struct ath_atx_tid *tid,
+-                             struct list_head *bf_head);
++                             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);
+ 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);
+@@ -61,6 +62,10 @@ static void ath_tx_rc_status(struct ath_
+                            int txok, bool update_rc);
+ 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,
++                                         struct ath_txq *txq,
++                                         struct ath_atx_tid *tid,
++                                         struct sk_buff *skb);
+ enum {
+       MCS_HT20,
+@@ -164,14 +169,13 @@ static void ath_tx_flush_tid(struct ath_
+               fi = get_frame_info(skb);
+               bf = fi->bf;
+-              list_add_tail(&bf->list, &bf_head);
+-
+               spin_unlock_bh(&txq->axq_lock);
+-              if (fi->retries) {
++              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);
+               } else {
+-                      ath_tx_send_normal(sc, txq, NULL, &bf_head);
++                      ath_tx_send_normal(sc, txq, NULL, skb);
+               }
+               spin_lock_bh(&txq->axq_lock);
+       }
+@@ -234,6 +238,13 @@ static void ath_tid_drain(struct ath_sof
+               fi = get_frame_info(skb);
+               bf = fi->bf;
++              if (!bf) {
++                      spin_unlock(&txq->axq_lock);
++                      ath_tx_complete(sc, skb, ATH_TX_ERROR, txq);
++                      spin_lock(&txq->axq_lock);
++                      continue;
++              }
++
+               list_add_tail(&bf->list, &bf_head);
+               if (fi->retries)
+@@ -760,8 +771,14 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+               skb = skb_peek(&tid->buf_q);
+               fi = get_frame_info(skb);
+               bf = fi->bf;
+-              seqno = bf->bf_state.seqno;
++              if (!fi->bf)
++                      bf = ath_tx_setup_buffer(sc, txq, tid, skb);
++              if (!bf)
++                      continue;
++
++              bf->bf_state.bf_type |= BUF_AMPDU;
++              seqno = bf->bf_state.seqno;
+               if (!bf_first)
+                       bf_first = bf;
+@@ -1434,13 +1451,11 @@ static void ath_tx_txqaddbuf(struct ath_
+ }
+ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
+-                            struct ath_buf *bf, struct ath_tx_control *txctl)
++                            struct sk_buff *skb, struct ath_tx_control *txctl)
+ {
+-      struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
++      struct ath_frame_info *fi = get_frame_info(skb);
+       struct list_head bf_head;
+-      u16 seqno = bf->bf_state.seqno;
+-
+-      bf->bf_state.bf_type |= BUF_AMPDU;
++      struct ath_buf *bf;
+       /*
+        * Do not queue to h/w when any of the following conditions is true:
+@@ -1450,25 +1465,29 @@ static void ath_tx_send_ampdu(struct ath
+        * - h/w queue depth exceeds low water mark
+        */
+       if (!skb_queue_empty(&tid->buf_q) || tid->paused ||
+-          !BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) ||
++          !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
+           txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
+               /*
+                * Add this frame to software queue for scheduling later
+                * for aggregation.
+                */
+               TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
+-              __skb_queue_tail(&tid->buf_q, bf->bf_mpdu);
++              __skb_queue_tail(&tid->buf_q, skb);
+               if (!txctl->an || !txctl->an->sleeping)
+                       ath_tx_queue_tid(txctl->txq, tid);
+               return;
+       }
++      bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
++      if (!bf)
++              return;
++
++      bf->bf_state.bf_type |= BUF_AMPDU;
+       INIT_LIST_HEAD(&bf_head);
+       list_add(&bf->list, &bf_head);
+       /* Add sub-frame to BAW */
+-      if (!fi->retries)
+-              ath_tx_addto_baw(sc, tid, seqno);
++      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);
+@@ -1478,13 +1497,21 @@ static void ath_tx_send_ampdu(struct ath
+ }
+ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+-                             struct ath_atx_tid *tid,
+-                             struct list_head *bf_head)
++                             struct ath_atx_tid *tid, struct sk_buff *skb)
+ {
+-      struct ath_frame_info *fi;
++      struct ath_frame_info *fi = get_frame_info(skb);
++      struct list_head bf_head;
+       struct ath_buf *bf;
+-      bf = list_first_entry(bf_head, struct ath_buf, list);
++      bf = fi->bf;
++      if (!bf)
++              bf = ath_tx_setup_buffer(sc, txq, tid, skb);
++
++      if (!bf)
++              return;
++
++      INIT_LIST_HEAD(&bf_head);
++      list_add_tail(&bf->list, &bf_head);
+       bf->bf_state.bf_type &= ~BUF_AMPDU;
+       /* update starting sequence number for subsequent ADDBA request */
+@@ -1492,9 +1519,8 @@ static void ath_tx_send_normal(struct at
+               INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+       bf->bf_lastbf = bf;
+-      fi = get_frame_info(bf->bf_mpdu);
+       ath_buf_set_rate(sc, bf, fi->framelen);
+-      ath_tx_txqaddbuf(sc, txq, bf_head, false);
++      ath_tx_txqaddbuf(sc, txq, &bf_head, false);
+       TX_STAT_INC(txq->axq_qnum, queued);
+ }
+@@ -1717,6 +1743,10 @@ static void ath_buf_set_rate(struct ath_
+ }
++/*
++ * Assign a descriptor (and sequence number if necessary,
++ * and map buffer for DMA. Frees skb on error
++ */
+ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+                                          struct ath_txq *txq,
+                                          struct ath_atx_tid *tid,
+@@ -1734,7 +1764,7 @@ static struct ath_buf *ath_tx_setup_buff
+       bf = ath_tx_get_buffer(sc);
+       if (!bf) {
+               ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n");
+-              return NULL;
++              goto error;
+       }
+       ATH_TXBUF_RESET(bf);
+@@ -1757,7 +1787,7 @@ static struct ath_buf *ath_tx_setup_buff
+               ath_err(ath9k_hw_common(sc->sc_ah),
+                       "dma_mapping_error() on TX\n");
+               ath_tx_return_buffer(sc, bf);
+-              return NULL;
++              goto error;
+       }
+       frm_type = get_hw_packet_type(skb);
+@@ -1779,18 +1809,20 @@ static struct ath_buf *ath_tx_setup_buff
+       fi->bf = bf;
+       return bf;
++
++error:
++      dev_kfree_skb_any(skb);
++      return NULL;
+ }
+ /* FIXME: tx power */
+-static int ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
++static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
+                            struct ath_tx_control *txctl)
+ {
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+-      struct list_head bf_head;
+       struct ath_atx_tid *tid = NULL;
+       struct ath_buf *bf;
+-      int ret = 0;
+       u8 tidno;
+       spin_lock_bh(&txctl->txq->axq_lock);
+@@ -1803,21 +1835,16 @@ static int ath_tx_start_dma(struct ath_s
+               WARN_ON(tid->ac->txq != txctl->txq);
+       }
+-      bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+-      if (unlikely(!bf)) {
+-              ret = -ENOMEM;
+-              goto out;
+-      }
+-
+       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+               /*
+                * Try aggregation if it's a unicast data frame
+                * and the destination is HT capable.
+                */
+-              ath_tx_send_ampdu(sc, tid, bf, txctl);
++              ath_tx_send_ampdu(sc, tid, skb, txctl);
+       } else {
+-              INIT_LIST_HEAD(&bf_head);
+-              list_add_tail(&bf->list, &bf_head);
++              bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
++              if (!bf)
++                      goto out;
+               bf->bf_state.bfs_paprd = txctl->paprd;
+@@ -1831,12 +1858,11 @@ static int ath_tx_start_dma(struct ath_s
+               if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
+                       ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true);
+-              ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
++              ath_tx_send_normal(sc, txctl->txq, tid, skb);
+       }
+ out:
+       spin_unlock_bh(&txctl->txq->axq_lock);
+-      return ret;
+ }
+ /* Upon failure caller should free skb */
+@@ -1904,7 +1930,8 @@ int ath_tx_start(struct ieee80211_hw *hw
+       }
+       spin_unlock_bh(&txq->axq_lock);
+-      return ath_tx_start_dma(sc, skb, txctl);
++      ath_tx_start_dma(sc, skb, txctl);
++      return 0;
+ }
+ /*****************/
diff --git a/package/mac80211/patches/545-ath9k_aggr_padding_fix.patch b/package/mac80211/patches/545-ath9k_aggr_padding_fix.patch
new file mode 100644 (file)
index 0000000..77938c4
--- /dev/null
@@ -0,0 +1,24 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -709,7 +709,9 @@ static int ath_compute_num_delims(struct
+        * Add delimiter when using RTS/CTS with aggregation
+        * and non enterprise AR9003 card
+        */
+-      if (first_subfrm)
++      if (first_subfrm && (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
++          !AR_SREV_9580_10_OR_LATER(sc->sc_ah) &&
++          (sc->sc_ah->ent_mode & AR_ENT_OTP_MIN_PKT_SIZE_DISABLE))
+               ndelim = max(ndelim, FIRST_DESC_NDELIMS);
+       /*
+--- a/drivers/net/wireless/ath/ath9k/reg.h
++++ b/drivers/net/wireless/ath/ath9k/reg.h
+@@ -1132,7 +1132,7 @@ enum {
+ #define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
+ #define AR_ENT_OTP              0x40d8
+ #define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
+-#define AR_ENT_OTP_MPSD               0x00800000
++#define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE               0x00800000
+ #define AR_CH0_BB_DPLL1                0x16180
+ #define AR_CH0_BB_DPLL1_REFDIV         0xF8000000
diff --git a/package/mac80211/patches/546-ath9k_retry_cache_sync.patch b/package/mac80211/patches/546-ath9k_retry_cache_sync.patch
new file mode 100644 (file)
index 0000000..ed543ac
--- /dev/null
@@ -0,0 +1,19 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -263,6 +263,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 +272,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)
diff --git a/package/mac80211/patches/550-ath9k_limit_qlen.patch b/package/mac80211/patches/550-ath9k_limit_qlen.patch
new file mode 100644 (file)
index 0000000..6ecf66d
--- /dev/null
@@ -0,0 +1,152 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -240,6 +240,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)];
++      int buf_pending;
+       u16 seq_start;
+       u16 seq_next;
+       u16 baw_size;
+@@ -286,6 +287,9 @@ struct ath_tx_control {
+  *  (axq_qnum).
+  */
+ struct ath_tx {
++      u32 qlen_single;
++      u32 qlen_aggr;
++
+       u16 seq_no;
+       u32 txqsetup;
+       spinlock_t txbuflock;
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1341,6 +1341,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_u32("qlen_single", S_IRUSR | S_IWUSR,
++                         sc->debug.debugfs_phy, &sc->tx.qlen_single);
++      debugfs_create_u32("qlen_aggr", S_IRUSR | S_IWUSR,
++                         sc->debug.debugfs_phy, &sc->tx.qlen_aggr);
+       debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc,
+                           &fops_stations);
+       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
+@@ -351,6 +351,14 @@ static void ath_tx_count_frames(struct a
+       }
+ }
++static struct ath_atx_tid *ath_get_tid(struct ath_node *an, struct sk_buff *skb)
++{
++      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++      u8 tidno;
++
++      tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
++      return ATH_AN_2_TID(an, tidno);
++}
+ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
+                                struct ath_buf *bf, struct list_head *bf_q,
+@@ -441,6 +449,8 @@ static void ath_tx_complete_aggr(struct 
+       __skb_queue_head_init(&bf_pending);
+       ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
++      tid->buf_pending -= nframes;
++
+       while (bf) {
+               u16 seqno = bf->bf_state.seqno;
+@@ -839,6 +849,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+                       ath_tx_addto_baw(sc, tid, seqno);
+               ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim);
++              tid->buf_pending++;
+               __skb_unlink(skb, &tid->buf_q);
+               list_add_tail(&bf->list, bf_q);
+               if (bf_prev) {
+@@ -1494,6 +1505,8 @@ static void ath_tx_send_ampdu(struct ath
+       /* Add sub-frame to BAW */
+       ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
++      tid->buf_pending++;
++
+       /* Queue to h/w without aggregation */
+       TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
+       bf->bf_lastbf = bf;
+@@ -1822,23 +1835,13 @@ error:
+ /* FIXME: tx power */
+ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
+-                           struct ath_tx_control *txctl)
++                           struct ath_tx_control *txctl,
++                           struct ath_atx_tid *tid)
+ {
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+-      struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+-      struct ath_atx_tid *tid = NULL;
+       struct ath_buf *bf;
+-      u8 tidno;
+       spin_lock_bh(&txctl->txq->axq_lock);
+-      if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
+-              ieee80211_is_data_qos(hdr->frame_control)) {
+-              tidno = ieee80211_get_qos_ctl(hdr)[0] &
+-                      IEEE80211_QOS_CTL_TID_MASK;
+-              tid = ATH_AN_2_TID(txctl->an, tidno);
+-
+-              WARN_ON(tid->ac->txq != txctl->txq);
+-      }
+       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+               /*
+@@ -1880,6 +1883,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;
++      struct ath_atx_tid *tid = NULL;
+       int padpos, padsize;
+       int frmlen = skb->len + FCS_LEN;
+       int q;
+@@ -1912,6 +1916,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+               skb_push(skb, padsize);
+               memmove(skb->data, skb->data + padsize, padpos);
++              hdr = (struct ieee80211_hdr *) skb->data;
+       }
+       if ((vif && vif->type != NL80211_IFTYPE_AP &&
+@@ -1921,6 +1926,24 @@ int ath_tx_start(struct ieee80211_hw *hw
+       setup_frame_info(hw, skb, frmlen);
++      if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
++          ieee80211_is_data_qos(hdr->frame_control)) {
++              tid = ath_get_tid(txctl->an, skb);
++
++              WARN_ON(tid->ac->txq != txq);
++      }
++
++      if ((info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
++              if (sc->tx.qlen_aggr > 0 && skb_queue_len(&tid->buf_q) +
++                  tid->buf_pending >= sc->tx.qlen_aggr)
++                      return -ENOMEM;
++      } else {
++              if (sc->tx.qlen_single > 0 &&
++                  txq->axq_depth - txq->axq_ampdu_depth >=
++                    sc->tx.qlen_single)
++                      return -ENOMEM;
++      }
++
+       /*
+        * 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.
+@@ -1935,7 +1958,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+       }
+       spin_unlock_bh(&txq->axq_lock);
+-      ath_tx_start_dma(sc, skb, txctl);
++      ath_tx_start_dma(sc, skb, txctl, tid);
+       return 0;
+ }
diff --git a/package/mac80211/patches/551-ath9k_initialize_chainmask.patch b/package/mac80211/patches/551-ath9k_initialize_chainmask.patch
deleted file mode 100644 (file)
index 03f7c36..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -667,8 +667,10 @@ static void ath9k_init_band_txpower(stru
- static void ath9k_init_txpower_limits(struct ath_softc *sc)
- {
-       struct ath_hw *ah = sc->sc_ah;
-+      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-       struct ath9k_channel *curchan = ah->curchan;
-+      ah->txchainmask = common->tx_chainmask;
-       if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
-               ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
-       if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
diff --git a/package/mac80211/patches/551-ath9k_sw_retry_reduce.patch b/package/mac80211/patches/551-ath9k_sw_retry_reduce.patch
new file mode 100644 (file)
index 0000000..1c61866
--- /dev/null
@@ -0,0 +1,62 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -260,14 +260,17 @@ static void ath_tid_drain(struct ath_sof
+ }
+ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
+-                           struct sk_buff *skb)
++                           struct sk_buff *skb, int count)
+ {
+       struct ath_frame_info *fi = get_frame_info(skb);
+       struct ath_buf *bf = fi->bf;
+       struct ieee80211_hdr *hdr;
++      int prev = fi->retries;
+       TX_STAT_INC(txq->axq_qnum, a_retries);
+-      if (fi->retries++ > 0)
++      fi->retries += count;
++
++      if (prev > 0)
+               return;
+       hdr = (struct ieee80211_hdr *)skb->data;
+@@ -383,6 +386,7 @@ static void ath_tx_complete_aggr(struct 
+       int nframes;
+       u8 tidno;
+       bool clear_filter;
++      int i, retries;
+       skb = bf->bf_mpdu;
+       hdr = (struct ieee80211_hdr *)skb->data;
+@@ -391,6 +395,10 @@ static void ath_tx_complete_aggr(struct 
+       memcpy(rates, tx_info->control.rates, sizeof(rates));
++      retries = ts->ts_longretry + 1;
++      for (i = 0; i < ts->ts_rateindex; i++)
++              retries += rates[i].count;
++
+       rcu_read_lock();
+       sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2);
+@@ -478,7 +486,8 @@ static void ath_tx_complete_aggr(struct 
+                       } else if (fi->retries < ATH_MAX_SW_RETRIES) {
+                               if (!(ts->ts_status & ATH9K_TXERR_FILT) ||
+                                   !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;
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -543,7 +543,7 @@ struct ath_ant_comb {
+ #define DEFAULT_CACHELINE       32
+ #define ATH_REGCLASSIDS_MAX     10
+ #define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
+-#define ATH_MAX_SW_RETRIES      10
++#define ATH_MAX_SW_RETRIES      20
+ #define ATH_CHAN_MAX            255
+ #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
diff --git a/package/mac80211/patches/552-ath9k_remove_tx_indexoffset.patch b/package/mac80211/patches/552-ath9k_remove_tx_indexoffset.patch
deleted file mode 100644 (file)
index c8e2640..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-@@ -247,8 +247,7 @@ static u32 ath9k_hw_4k_get_eeprom(struct
- }
- static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
--                                struct ath9k_channel *chan,
--                                int16_t *pTxPowerIndexOffset)
-+                                struct ath9k_channel *chan)
- {
-       struct ath_common *common = ath9k_hw_common(ah);
-       struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
-@@ -358,8 +357,6 @@ static void ath9k_hw_set_4k_power_cal_ta
-                       REGWRITE_BUFFER_FLUSH(ah);
-               }
-       }
--
--      *pTxPowerIndexOffset = 0;
- }
- static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
-@@ -582,7 +579,6 @@ static void ath9k_hw_4k_set_txpower(stru
-       struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
-       struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
-       int16_t ratesArray[Ar5416RateSize];
--      int16_t txPowerIndexOffset = 0;
-       u8 ht40PowerIncForPdadc = 2;
-       int i;
-@@ -599,11 +595,10 @@ static void ath9k_hw_4k_set_txpower(stru
-                                            twiceMaxRegulatoryPower,
-                                            powerLimit);
--      ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
-+      ath9k_hw_set_4k_power_cal_table(ah, chan);
-       regulatory->max_power_level = 0;
-       for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
--              ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
-               if (ratesArray[i] > MAX_RATE_POWER)
-                       ratesArray[i] = MAX_RATE_POWER;
---- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-@@ -306,8 +306,7 @@ static void ar9287_eeprom_olpc_set_pdadc
- }
- static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
--                                              struct ath9k_channel *chan,
--                                              int16_t *pTxPowerIndexOffset)
-+                                              struct ath9k_channel *chan)
- {
-       struct cal_data_per_freq_ar9287 *pRawDataset;
-       struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
-@@ -446,8 +445,6 @@ static void ath9k_hw_set_ar9287_power_ca
-                       REGWRITE_BUFFER_FLUSH(ah);
-               }
-       }
--
--      *pTxPowerIndexOffset = 0;
- }
- static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
-@@ -722,7 +719,6 @@ static void ath9k_hw_ar9287_set_txpower(
-       struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
-       struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
-       int16_t ratesArray[Ar5416RateSize];
--      int16_t txPowerIndexOffset = 0;
-       u8 ht40PowerIncForPdadc = 2;
-       int i;
-@@ -738,11 +734,10 @@ static void ath9k_hw_ar9287_set_txpower(
-                                                twiceMaxRegulatoryPower,
-                                                powerLimit);
--      ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
-+      ath9k_hw_set_ar9287_power_cal_table(ah, chan);
-       regulatory->max_power_level = 0;
-       for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
--              ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
-               if (ratesArray[i] > MAX_RATE_POWER)
-                       ratesArray[i] = MAX_RATE_POWER;
---- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
-@@ -692,8 +692,7 @@ static void ath9k_adjust_pdadc_values(st
- }
- static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
--                                struct ath9k_channel *chan,
--                                int16_t *pTxPowerIndexOffset)
-+                                struct ath9k_channel *chan)
- {
- #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
- #define SM_PDGAIN_B(x, y) \
-@@ -857,7 +856,6 @@ static void ath9k_hw_set_def_power_cal_t
-               }
-       }
--      *pTxPowerIndexOffset = 0;
- #undef SM_PD_GAIN
- #undef SM_PDGAIN_B
- }
-@@ -1145,7 +1143,6 @@ static void ath9k_hw_def_set_txpower(str
-       struct modal_eep_header *pModal =
-               &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
-       int16_t ratesArray[Ar5416RateSize];
--      int16_t txPowerIndexOffset = 0;
-       u8 ht40PowerIncForPdadc = 2;
-       int i, cck_ofdm_delta = 0;
-@@ -1162,11 +1159,10 @@ static void ath9k_hw_def_set_txpower(str
-                                              twiceMaxRegulatoryPower,
-                                              powerLimit);
--      ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
-+      ath9k_hw_set_def_power_cal_table(ah, chan);
-       regulatory->max_power_level = 0;
-       for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
--              ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
-               if (ratesArray[i] > MAX_RATE_POWER)
-                       ratesArray[i] = MAX_RATE_POWER;
-               if (ratesArray[i] > regulatory->max_power_level)
diff --git a/package/mac80211/patches/553-ath9k_fix_rate_power.patch b/package/mac80211/patches/553-ath9k_fix_rate_power.patch
deleted file mode 100644 (file)
index fc79d5f..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
-@@ -4922,25 +4922,7 @@ static void ath9k_hw_ar9300_set_txpower(
-                       "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
-       }
--      /*
--       * This is the TX power we send back to driver core,
--       * and it can use to pass to userspace to display our
--       * currently configured TX power setting.
--       *
--       * Since power is rate dependent, use one of the indices
--       * from the AR9300_Rates enum to select an entry from
--       * targetPowerValT2[] to report. Currently returns the
--       * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
--       * as CCK power is less interesting (?).
--       */
--      i = ALL_TARGET_LEGACY_6_24; /* legacy */
--      if (IS_CHAN_HT40(chan))
--              i = ALL_TARGET_HT40_0_8_16; /* ht40 */
--      else if (IS_CHAN_HT20(chan))
--              i = ALL_TARGET_HT20_0_8_16; /* ht20 */
--
--      ah->txpower_limit = targetPowerValT2[i];
--      regulatory->max_power_level = targetPowerValT2[i];
-+      ah->txpower_limit = regulatory->max_power_level;
-       /* Write target power array to registers */
-       ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
-@@ -609,15 +609,6 @@ static void ath9k_hw_4k_set_txpower(stru
-       if (test)
-           return;
--      /* Update regulatory */
--      i = rate6mb;
--      if (IS_CHAN_HT40(chan))
--              i = rateHt40_0;
--      else if (IS_CHAN_HT20(chan))
--              i = rateHt20_0;
--
--      regulatory->max_power_level = ratesArray[i];
--
-       if (AR_SREV_9280_20_OR_LATER(ah)) {
-               for (i = 0; i < Ar5416RateSize; i++)
-                       ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
---- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
-@@ -748,13 +748,6 @@ static void ath9k_hw_ar9287_set_txpower(
-       if (test)
-               return;
--      if (IS_CHAN_2GHZ(chan))
--              i = rate1l;
--      else
--              i = rate6mb;
--
--      regulatory->max_power_level = ratesArray[i];
--
-       if (AR_SREV_9280_20_OR_LATER(ah)) {
-               for (i = 0; i < Ar5416RateSize; i++)
-                       ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
---- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
-+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
-@@ -1169,17 +1169,6 @@ static void ath9k_hw_def_set_txpower(str
-                       regulatory->max_power_level = ratesArray[i];
-       }
--      if (!test) {
--              i = rate6mb;
--
--              if (IS_CHAN_HT40(chan))
--                      i = rateHt40_0;
--              else if (IS_CHAN_HT20(chan))
--                      i = rateHt20_0;
--
--              regulatory->max_power_level = ratesArray[i];
--      }
--
-       switch(ar5416_get_ntxchains(ah->txchainmask)) {
-       case 1:
-               break;
diff --git a/package/mac80211/patches/554-ath9k_test_txpower.patch b/package/mac80211/patches/554-ath9k_test_txpower.patch
deleted file mode 100644 (file)
index 96131dc..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2442,15 +2442,18 @@ void ath9k_hw_set_txpowerlimit(struct at
-       struct ath_regulatory *regulatory = 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, regulatory->power_limit);
-+      int chan_pwr = channel->max_power * 2;
-+
-+      if (test)
-+              reg_pwr = chan_pwr = MAX_RATE_POWER;
-       regulatory->power_limit = min(limit, (u32) MAX_RATE_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), test);
-+                               chan_pwr, reg_pwr, test);
- }
- EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
diff --git a/package/mac80211/patches/560-ath9k_ps_tx_aggr_fix.patch b/package/mac80211/patches/560-ath9k_ps_tx_aggr_fix.patch
deleted file mode 100644 (file)
index 666b002..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -550,7 +550,8 @@ static void ath_tx_complete_aggr(struct 
-               if (clear_filter)
-                       tid->ac->clear_ps_filter = true;
-               list_splice(&bf_pending, &tid->buf_q);
--              ath_tx_queue_tid(txq, tid);
-+              if (!an->sleeping)
-+                      ath_tx_queue_tid(txq, tid);
-               spin_unlock_bh(&txq->axq_lock);
-       }
-@@ -1410,7 +1411,8 @@ static void ath_tx_send_ampdu(struct ath
-                */
-               TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
-               list_add_tail(&bf->list, &tid->buf_q);
--              ath_tx_queue_tid(txctl->txq, tid);
-+              if (!txctl->an || !txctl->an->sleeping)
-+                      ath_tx_queue_tid(txctl->txq, tid);
-               return;
-       }
diff --git a/package/mac80211/patches/560-mac80211_defer_bar_tx.patch b/package/mac80211/patches/560-mac80211_defer_bar_tx.patch
new file mode 100644 (file)
index 0000000..9bf8918
--- /dev/null
@@ -0,0 +1,90 @@
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -84,6 +84,8 @@ enum ieee80211_sta_info_flags {
+  * @stop_initiator: initiator of a session stop
+  * @tx_stop: TX DelBA frame when stopping
+  * @buf_size: reorder buffer size at receiver
++ * @failed_bar_ssn: ssn of the last failed BAR tx attempt
++ * @bar_pending: BAR needs to be re-sent
+  *
+  * This structure's lifetime is managed by RCU, assignments to
+  * the array holding it must hold the aggregation mutex.
+@@ -104,6 +106,9 @@ struct tid_ampdu_tx {
+       u8 stop_initiator;
+       bool tx_stop;
+       u8 buf_size;
++
++      u16 failed_bar_ssn;
++      bool bar_pending;
+ };
+ /**
+--- a/net/mac80211/status.c
++++ b/net/mac80211/status.c
+@@ -127,12 +127,32 @@ static void ieee80211_handle_filtered_fr
+       dev_kfree_skb(skb);
+ }
++static void ieee80211_check_pending_bar(struct sta_info *sta, u8 *addr, u8 tid)
++{
++      struct tid_ampdu_tx *tid_tx;
++
++      tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++      if (!tid_tx || !tid_tx->bar_pending)
++              return;
++
++      tid_tx->bar_pending = false;
++      ieee80211_send_bar(sta->sdata, addr, tid, tid_tx->failed_bar_ssn);
++}
++
+ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
+ {
+       struct ieee80211_mgmt *mgmt = (void *) skb->data;
+       struct ieee80211_local *local = sta->local;
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
++      if (ieee80211_is_data_qos(mgmt->frame_control)) {
++              struct ieee80211_hdr *hdr = (void *) skb->data;
++              u8 *qc = ieee80211_get_qos_ctl(hdr);
++              u16 tid = qc[0] & 0xf;
++
++              ieee80211_check_pending_bar(sta, hdr->addr1, tid);
++      }
++
+       if (ieee80211_is_action(mgmt->frame_control) &&
+           sdata->vif.type == NL80211_IFTYPE_STATION &&
+           mgmt->u.action.category == WLAN_CATEGORY_HT &&
+@@ -161,6 +181,18 @@ static void ieee80211_frame_acked(struct
+       }
+ }
++static void ieee80211_set_bar_pending(struct sta_info *sta, u8 tid, u16 ssn)
++{
++      struct tid_ampdu_tx *tid_tx;
++
++      tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
++      if (!tid_tx)
++              return;
++
++      tid_tx->failed_bar_ssn = ssn;
++      tid_tx->bar_pending = true;
++}
++
+ /*
+  * Use a static threshold for now, best value to be determined
+  * by testing ...
+@@ -254,10 +286,13 @@ void ieee80211_tx_status(struct ieee8021
+                        */
+                       bar = (struct ieee80211_bar *) skb->data;
+                       if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) {
++                              u16 ssn = le16_to_cpu(bar->start_seq_num);
++
+                               tid = (bar->control &
+                                      IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
+                                     IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
+-                              ieee80211_stop_tx_ba_session(&sta->sta, tid);
++
++                              ieee80211_set_bar_pending(sta, tid, ssn);
+                       }
+               }
diff --git a/package/mac80211/patches/570-ath9k_fix_ack_cts_timeout.patch b/package/mac80211/patches/570-ath9k_fix_ack_cts_timeout.patch
new file mode 100644 (file)
index 0000000..ed955b4
--- /dev/null
@@ -0,0 +1,28 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -969,7 +969,7 @@ void ath9k_hw_init_global_settings(struc
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &common->hw->conf;
+       const struct ath9k_channel *chan = ah->curchan;
+-      int acktimeout;
++      int acktimeout, ctstimeout;
+       int slottime;
+       int sifstime;
+       int rx_lat = 0, tx_lat = 0, eifs = 0;
+@@ -1029,6 +1029,7 @@ void ath9k_hw_init_global_settings(struc
+       /* As defined by IEEE 802.11-2007 17.3.8.6 */
+       acktimeout = slottime + sifstime + 3 * ah->coverage_class;
++      ctstimeout = acktimeout;
+       /*
+        * Workaround for early ACK timeouts, add an offset to match the
+@@ -1043,7 +1044,7 @@ void ath9k_hw_init_global_settings(struc
+       ath9k_hw_set_sifs_time(ah, sifstime);
+       ath9k_hw_setslottime(ah, slottime);
+       ath9k_hw_set_ack_timeout(ah, acktimeout);
+-      ath9k_hw_set_cts_timeout(ah, acktimeout);
++      ath9k_hw_set_cts_timeout(ah, ctstimeout);
+       if (ah->globaltxtimeout != (u32) -1)
+               ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout);
diff --git a/package/mac80211/patches/580-ath9k_remove_common_chainmask.patch b/package/mac80211/patches/580-ath9k_remove_common_chainmask.patch
new file mode 100644 (file)
index 0000000..58d972c
--- /dev/null
@@ -0,0 +1,273 @@
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -140,9 +140,6 @@ struct ath_common {
+       u8 curbssid[ETH_ALEN];
+       u8 bssidmask[ETH_ALEN];
+-      u8 tx_chainmask;
+-      u8 rx_chainmask;
+-
+       u32 rx_bufsize;
+       u32 keymax;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+@@ -113,7 +113,7 @@ static int ar9003_get_training_power_5g(
+       if (delta > scale)
+               return -1;
+-      switch (get_streams(common->tx_chainmask)) {
++      switch (get_streams(ah->txchainmask)) {
+       case 1:
+               delta = 6;
+               break;
+@@ -126,7 +126,7 @@ static int ar9003_get_training_power_5g(
+       default:
+               delta = 0;
+               ath_dbg(common, ATH_DBG_CALIBRATE,
+-              "Invalid tx-chainmask: %u\n", common->tx_chainmask);
++              "Invalid tx-chainmask: %u\n", ah->txchainmask);
+       }
+       power += delta;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -318,7 +318,6 @@ static void ath_paprd_activate(struct at
+ {
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+-      struct ath_common *common = ath9k_hw_common(ah);
+       int chain;
+       if (!caldata || !caldata->paprd_done)
+@@ -327,7 +326,7 @@ static void ath_paprd_activate(struct at
+       ath9k_ps_wakeup(sc);
+       ar9003_paprd_enable(ah, false);
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+-              if (!(common->tx_chainmask & BIT(chain)))
++              if (!(ah->txchainmask & BIT(chain)))
+                       continue;
+               ar9003_paprd_populate_single_table(ah, caldata, chain);
+@@ -414,7 +413,7 @@ void ath_paprd_calibrate(struct work_str
+       memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
+       for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
+-              if (!(common->tx_chainmask & BIT(chain)))
++              if (!(ah->txchainmask & BIT(chain)))
+                       continue;
+               chain_ok = 0;
+@@ -535,7 +534,7 @@ void ath_ani_calibrate(unsigned long dat
+       if (longcal || shortcal) {
+               common->ani.caldone =
+                       ath9k_hw_calibrate(ah, ah->curchan,
+-                                              common->rx_chainmask, longcal);
++                                              ah->rxchainmask, longcal);
+       }
+       ath9k_ps_restore(sc);
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1488,9 +1488,6 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+       u64 tsf = 0;
+       int i, r;
+-      ah->txchainmask = common->tx_chainmask;
+-      ah->rxchainmask = common->rx_chainmask;
+-
+       if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+               return -EIO;
+@@ -2108,6 +2105,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+       pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
+       pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
++      ah->txchainmask = pCap->tx_chainmask;
++      ah->rxchainmask = pCap->rx_chainmask;
+       ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA;
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1660,7 +1660,7 @@ u8 ath_txchainmask_reduction(struct ath_
+ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len)
+ {
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      struct ath_hw *ah = sc->sc_ah;
+       struct ath9k_11n_rate_series series[4];
+       struct sk_buff *skb;
+       struct ieee80211_tx_info *tx_info;
+@@ -1720,7 +1720,7 @@ static void ath_buf_set_rate(struct ath_
+                       /* MCS rates */
+                       series[i].Rate = rix | 0x80;
+                       series[i].ChSel = ath_txchainmask_reduction(sc,
+-                                      common->tx_chainmask, series[i].Rate);
++                                      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))
+@@ -1745,10 +1745,10 @@ static void ath_buf_set_rate(struct ath_
+               }
+               if (bf->bf_state.bfs_paprd)
+-                      series[i].ChSel = common->tx_chainmask;
++                      series[i].ChSel = ah->txchainmask;
+               else
+                       series[i].ChSel = ath_txchainmask_reduction(sc,
+-                                      common->tx_chainmask, series[i].Rate);
++                                      ah->txchainmask, series[i].Rate);
+               series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
+                       phy, rate->bitrate * 100, len, rix, is_sp);
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -107,7 +107,7 @@ static void ath_beacon_setup(struct ath_
+       series[0].Tries = 1;
+       series[0].Rate = rate;
+       series[0].ChSel = ath_txchainmask_reduction(sc,
+-                      common->tx_chainmask, series[0].Rate);
++                      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);
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -95,11 +95,11 @@ static ssize_t read_file_tx_chainmask(st
+                            size_t count, loff_t *ppos)
+ {
+       struct ath_softc *sc = file->private_data;
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      struct ath_hw *ah = sc->sc_ah;
+       char buf[32];
+       unsigned int len;
+-      len = sprintf(buf, "0x%08x\n", common->tx_chainmask);
++      len = sprintf(buf, "0x%08x\n", ah->txchainmask);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ }
+@@ -107,7 +107,7 @@ static ssize_t write_file_tx_chainmask(s
+                            size_t count, loff_t *ppos)
+ {
+       struct ath_softc *sc = file->private_data;
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      struct ath_hw *ah = sc->sc_ah;
+       unsigned long mask;
+       char buf[32];
+       ssize_t len;
+@@ -120,8 +120,8 @@ static ssize_t write_file_tx_chainmask(s
+       if (strict_strtoul(buf, 0, &mask))
+               return -EINVAL;
+-      common->tx_chainmask = mask;
+-      sc->sc_ah->caps.tx_chainmask = mask;
++      ah->txchainmask = mask;
++      ah->caps.tx_chainmask = mask;
+       return count;
+ }
+@@ -138,11 +138,11 @@ static ssize_t read_file_rx_chainmask(st
+                            size_t count, loff_t *ppos)
+ {
+       struct ath_softc *sc = file->private_data;
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      struct ath_hw *ah = sc->sc_ah;
+       char buf[32];
+       unsigned int len;
+-      len = sprintf(buf, "0x%08x\n", common->rx_chainmask);
++      len = sprintf(buf, "0x%08x\n", ah->rxchainmask);
+       return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ }
+@@ -150,7 +150,7 @@ static ssize_t write_file_rx_chainmask(s
+                            size_t count, loff_t *ppos)
+ {
+       struct ath_softc *sc = file->private_data;
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      struct ath_hw *ah = sc->sc_ah;
+       unsigned long mask;
+       char buf[32];
+       ssize_t len;
+@@ -163,8 +163,8 @@ static ssize_t write_file_rx_chainmask(s
+       if (strict_strtoul(buf, 0, &mask))
+               return -EINVAL;
+-      common->rx_chainmask = mask;
+-      sc->sc_ah->caps.rx_chainmask = mask;
++      ah->rxchainmask = mask;
++      ah->caps.rx_chainmask = mask;
+       return count;
+ }
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -509,8 +509,8 @@ static void setup_ht_cap(struct ath9k_ht
+       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+       /* ath9k_htc supports only 1 or 2 stream devices */
+-      tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2);
+-      rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2);
++      tx_streams = ath9k_cmn_count_streams(priv->ah->txchainmask, 2);
++      rx_streams = ath9k_cmn_count_streams(priv->ah->rxchainmask, 2);
+       ath_dbg(common, ATH_DBG_CONFIG,
+               "TX streams %d, RX streams: %d\n",
+@@ -601,9 +601,6 @@ static void ath9k_init_misc(struct ath9k
+ {
+       struct ath_common *common = ath9k_hw_common(priv->ah);
+-      common->tx_chainmask = priv->ah->caps.tx_chainmask;
+-      common->rx_chainmask = priv->ah->caps.rx_chainmask;
+-
+       memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
+       priv->ah->opmode = NL80211_IFTYPE_STATION;
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+@@ -826,8 +826,7 @@ void ath9k_htc_ani_work(struct work_stru
+               if (longcal || shortcal)
+                       common->ani.caldone =
+                               ath9k_hw_calibrate(ah, ah->curchan,
+-                                                 common->rx_chainmask,
+-                                                 longcal);
++                                                 ah->rxchainmask, longcal);
+               ath9k_htc_ps_restore(priv);
+       }
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -270,8 +270,8 @@ static void setup_ht_cap(struct ath_soft
+       /* set up supported mcs set */
+       memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+-      tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams);
+-      rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams);
++      tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams);
++      rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams);
+       ath_dbg(common, ATH_DBG_CONFIG,
+               "TX streams %d, RX streams: %d\n",
+@@ -506,9 +506,6 @@ static void ath9k_init_misc(struct ath_s
+               sc->sc_flags |= SC_OP_RXAGGR;
+       }
+-      common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
+-      common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
+-
+       ath9k_hw_set_diversity(sc->sc_ah, true);
+       sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
+@@ -645,10 +642,8 @@ static void ath9k_init_band_txpower(stru
+ static void ath9k_init_txpower_limits(struct ath_softc *sc)
+ {
+       struct ath_hw *ah = sc->sc_ah;
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath9k_channel *curchan = ah->curchan;
+-      ah->txchainmask = common->tx_chainmask;
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+               ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
diff --git a/package/mac80211/patches/581-ath9k_use_reset_work.patch b/package/mac80211/patches/581-ath9k_use_reset_work.patch
new file mode 100644 (file)
index 0000000..7836718
--- /dev/null
@@ -0,0 +1,317 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -429,6 +429,7 @@ void ath9k_set_beaconing_status(struct a
+ #define ATH_PAPRD_TIMEOUT     100 /* msecs */
++void ath_reset_work(struct work_struct *work);
+ void ath_hw_check(struct work_struct *work);
+ void ath_hw_pll_work(struct work_struct *work);
+ void ath_paprd_calibrate(struct work_struct *work);
+@@ -559,6 +560,7 @@ struct ath_ant_comb {
+ #define SC_OP_RXFLUSH                BIT(7)
+ #define SC_OP_LED_ASSOCIATED         BIT(8)
+ #define SC_OP_LED_ON                 BIT(9)
++#define SC_OP_HW_RESET               BIT(10)
+ #define SC_OP_TSF_RESET              BIT(11)
+ #define SC_OP_BT_PRIORITY_DETECTED   BIT(12)
+ #define SC_OP_BT_SCAN              BIT(13)
+@@ -609,6 +611,7 @@ struct ath_softc {
+       struct mutex mutex;
+       struct work_struct paprd_work;
+       struct work_struct hw_check_work;
++      struct work_struct hw_reset_work;
+       struct completion paprd_complete;
+       unsigned int hw_busy_count;
+@@ -655,7 +658,6 @@ struct ath_softc {
+ };
+ void ath9k_tasklet(unsigned long data);
+-int ath_reset(struct ath_softc *sc, bool retry_tx);
+ int ath_cabq_update(struct ath_softc *);
+ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
+--- a/drivers/net/wireless/ath/ath9k/beacon.c
++++ b/drivers/net/wireless/ath/ath9k/beacon.c
+@@ -386,9 +386,7 @@ void ath_beacon_tasklet(unsigned long da
+                       ath_dbg(common, ATH_DBG_BSTUCK,
+                               "beacon is officially stuck\n");
+                       sc->sc_flags |= SC_OP_TSF_RESET;
+-                      spin_lock(&sc->sc_pcu_lock);
+-                      ath_reset(sc, true);
+-                      spin_unlock(&sc->sc_pcu_lock);
++                      ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+               }
+               return;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -776,6 +776,7 @@ int ath9k_init_device(u16 devid, struct 
+                       goto error_world;
+       }
++      INIT_WORK(&sc->hw_reset_work, ath_reset_work);
+       INIT_WORK(&sc->hw_check_work, ath_hw_check);
+       INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
+       INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -236,6 +236,7 @@ static int ath_set_channel(struct ath_so
+       del_timer_sync(&common->ani.timer);
+       cancel_work_sync(&sc->paprd_work);
+       cancel_work_sync(&sc->hw_check_work);
++      cancel_work_sync(&sc->hw_reset_work);
+       cancel_delayed_work_sync(&sc->tx_complete_work);
+       cancel_delayed_work_sync(&sc->hw_pll_work);
+@@ -595,74 +596,6 @@ static void ath_node_detach(struct ath_s
+               ath_tx_node_cleanup(sc, an);
+ }
+-void ath_hw_check(struct work_struct *work)
+-{
+-      struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+-      unsigned long flags;
+-      int busy;
+-
+-      ath9k_ps_wakeup(sc);
+-      if (ath9k_hw_check_alive(sc->sc_ah))
+-              goto out;
+-
+-      spin_lock_irqsave(&common->cc_lock, flags);
+-      busy = ath_update_survey_stats(sc);
+-      spin_unlock_irqrestore(&common->cc_lock, flags);
+-
+-      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) {
+-                      spin_lock_bh(&sc->sc_pcu_lock);
+-                      ath_reset(sc, true);
+-                      spin_unlock_bh(&sc->sc_pcu_lock);
+-              }
+-      } else if (busy >= 0)
+-              sc->hw_busy_count = 0;
+-
+-out:
+-      ath9k_ps_restore(sc);
+-}
+-
+-static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
+-{
+-      static int count;
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+-
+-      if (pll_sqsum >= 0x40000) {
+-              count++;
+-              if (count == 3) {
+-                      /* Rx is hung for more than 500ms. Reset it */
+-                      ath_dbg(common, ATH_DBG_RESET,
+-                              "Possible RX hang, resetting");
+-                      spin_lock_bh(&sc->sc_pcu_lock);
+-                      ath_reset(sc, true);
+-                      spin_unlock_bh(&sc->sc_pcu_lock);
+-                      count = 0;
+-              }
+-      } else
+-              count = 0;
+-}
+-
+-void ath_hw_pll_work(struct work_struct *work)
+-{
+-      struct ath_softc *sc = container_of(work, struct ath_softc,
+-                                          hw_pll_work.work);
+-      u32 pll_sqsum;
+-
+-      if (AR_SREV_9485(sc->sc_ah)) {
+-
+-              ath9k_ps_wakeup(sc);
+-              pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
+-              ath9k_ps_restore(sc);
+-
+-              ath_hw_pll_rx_hang_check(sc, pll_sqsum);
+-
+-              ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
+-      }
+-}
+-
+ void ath9k_tasklet(unsigned long data)
+ {
+@@ -675,9 +608,7 @@ void ath9k_tasklet(unsigned long data)
+       if ((status & ATH9K_INT_FATAL) ||
+           (status & ATH9K_INT_BB_WATCHDOG)) {
+-              spin_lock(&sc->sc_pcu_lock);
+-              ath_reset(sc, true);
+-              spin_unlock(&sc->sc_pcu_lock);
++              ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+               return;
+       }
+@@ -968,13 +899,14 @@ void ath_radio_disable(struct ath_softc 
+       ath9k_ps_restore(sc);
+ }
+-int ath_reset(struct ath_softc *sc, bool retry_tx)
++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(ah);
+       struct ieee80211_hw *hw = sc->hw;
+       int r;
++      sc->sc_flags &= ~SC_OP_HW_RESET;
+       sc->hw_busy_count = 0;
+       /* Stop ANI */
+@@ -1035,6 +967,84 @@ int ath_reset(struct ath_softc *sc, bool
+       return r;
+ }
++void ath_reset_work(struct work_struct *work)
++{
++      struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
++
++      spin_lock_bh(&sc->sc_pcu_lock);
++      ath_reset(sc, true);
++      spin_unlock_bh(&sc->sc_pcu_lock);
++}
++
++void ath_hw_check(struct work_struct *work)
++{
++      struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
++      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      unsigned long flags;
++      int busy;
++
++      ath9k_ps_wakeup(sc);
++      if (ath9k_hw_check_alive(sc->sc_ah))
++              goto out;
++
++      spin_lock_irqsave(&common->cc_lock, flags);
++      busy = ath_update_survey_stats(sc);
++      spin_unlock_irqrestore(&common->cc_lock, flags);
++
++      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) {
++                      spin_lock_bh(&sc->sc_pcu_lock);
++                      ath_reset(sc, true);
++                      spin_unlock_bh(&sc->sc_pcu_lock);
++              }
++
++      } else if (busy >= 0)
++              sc->hw_busy_count = 0;
++
++out:
++      ath9k_ps_restore(sc);
++}
++
++static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
++{
++      static int count;
++      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++
++      if (pll_sqsum >= 0x40000) {
++              count++;
++              if (count == 3) {
++                      /* Rx is hung for more than 500ms. Reset it */
++                      ath_dbg(common, ATH_DBG_RESET,
++                              "Possible RX hang, resetting");
++                      spin_lock_bh(&sc->sc_pcu_lock);
++                      ath_reset(sc, true);
++                      spin_unlock_bh(&sc->sc_pcu_lock);
++                      count = 0;
++              }
++      } else
++              count = 0;
++}
++
++void ath_hw_pll_work(struct work_struct *work)
++{
++      struct ath_softc *sc = container_of(work, struct ath_softc,
++                                          hw_pll_work.work);
++      u32 pll_sqsum;
++
++      if (AR_SREV_9485(sc->sc_ah)) {
++
++              ath9k_ps_wakeup(sc);
++              pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
++              ath9k_ps_restore(sc);
++
++              ath_hw_pll_rx_hang_check(sc, pll_sqsum);
++
++              ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
++      }
++}
++
+ /**********************/
+ /* mac80211 callbacks */
+ /**********************/
+@@ -1227,6 +1237,7 @@ static void ath9k_stop(struct ieee80211_
+       cancel_delayed_work_sync(&sc->hw_pll_work);
+       cancel_work_sync(&sc->paprd_work);
+       cancel_work_sync(&sc->hw_check_work);
++      cancel_work_sync(&sc->hw_reset_work);
+       if (sc->sc_flags & SC_OP_INVALID) {
+               ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -603,8 +603,10 @@ static void ath_tx_complete_aggr(struct 
+       rcu_read_unlock();
+-      if (needreset)
+-              ath_reset(sc, false);
++      if (needreset) {
++              sc->sc_flags |= SC_OP_HW_RESET;
++              ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
++      }
+ }
+ static bool ath_lookup_legacy(struct ath_buf *bf)
+@@ -1357,7 +1359,7 @@ void ath_txq_schedule(struct ath_softc *
+       struct ath_atx_ac *ac, *ac_tmp, *last_ac;
+       struct ath_atx_tid *tid, *last_tid;
+-      if (list_empty(&txq->axq_acq) ||
++      if ((sc->sc_flags & SC_OP_HW_RESET) || list_empty(&txq->axq_acq) ||
+           txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+               return;
+@@ -2184,6 +2186,9 @@ static void ath_tx_processq(struct ath_s
+       spin_lock_bh(&txq->axq_lock);
+       for (;;) {
++              if (sc->sc_flags & SC_OP_HW_RESET)
++                      break;
++
+               if (list_empty(&txq->axq_q)) {
+                       txq->axq_link = NULL;
+                       if (sc->sc_flags & SC_OP_TXAGGR)
+@@ -2271,9 +2276,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");
+-              spin_lock_bh(&sc->sc_pcu_lock);
+-              ath_reset(sc, true);
+-              spin_unlock_bh(&sc->sc_pcu_lock);
++              ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+       }
+       ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
+@@ -2306,6 +2309,9 @@ void ath_tx_edma_tasklet(struct ath_soft
+       int status;
+       for (;;) {
++              if (sc->sc_flags & SC_OP_HW_RESET)
++                      break;
++
+               status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);
+               if (status == -EINPROGRESS)
+                       break;
diff --git a/package/mac80211/patches/582-ath9k_merge_reset_functions.patch b/package/mac80211/patches/582-ath9k_merge_reset_functions.patch
new file mode 100644 (file)
index 0000000..ff491a4
--- /dev/null
@@ -0,0 +1,451 @@
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -212,84 +212,57 @@ static int ath_update_survey_stats(struc
+       return ret;
+ }
+-/*
+- * Set/change channels.  If the channel is really being changed, it's done
+- * by reseting the chip.  To accomplish this we must first cleanup any pending
+- * DMA, then restart stuff.
+-*/
+-static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
+-                  struct ath9k_channel *hchan)
++static void __ath_cancel_work(struct ath_softc *sc)
+ {
+-      struct ath_hw *ah = sc->sc_ah;
+-      struct ath_common *common = ath9k_hw_common(ah);
+-      struct ieee80211_conf *conf = &common->hw->conf;
+-      bool fastcc = true, stopped;
+-      struct ieee80211_channel *channel = hw->conf.channel;
+-      struct ath9k_hw_cal_data *caldata = NULL;
+-      int r;
+-
+-      if (sc->sc_flags & SC_OP_INVALID)
+-              return -EIO;
+-
+-      sc->hw_busy_count = 0;
+-
+-      del_timer_sync(&common->ani.timer);
+       cancel_work_sync(&sc->paprd_work);
+       cancel_work_sync(&sc->hw_check_work);
+-      cancel_work_sync(&sc->hw_reset_work);
+       cancel_delayed_work_sync(&sc->tx_complete_work);
+       cancel_delayed_work_sync(&sc->hw_pll_work);
++}
+-      ath9k_ps_wakeup(sc);
++static void ath_cancel_work(struct ath_softc *sc)
++{
++      __ath_cancel_work(sc);
++      cancel_work_sync(&sc->hw_reset_work);
++}
+-      spin_lock_bh(&sc->sc_pcu_lock);
++static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      struct ath_common *common = ath9k_hw_common(ah);
++      bool ret;
+-      /*
+-       * This is only performed if the channel settings have
+-       * actually changed.
+-       *
+-       * To switch channels clear any pending DMA operations;
+-       * wait long enough for the RX fifo to drain, reset the
+-       * hardware at the new frequency, and then re-enable
+-       * the relevant bits of the h/w.
+-       */
+-      ath9k_hw_disable_interrupts(ah);
+-      stopped = ath_drain_all_txq(sc, false);
++      ieee80211_stop_queues(sc->hw);
+-      if (!ath_stoprecv(sc))
+-              stopped = false;
++      sc->hw_busy_count = 0;
++      del_timer_sync(&common->ani.timer);
+-      if (!ath9k_hw_check_alive(ah))
+-              stopped = false;
++      ath9k_hw_disable_interrupts(ah);
+-      /* XXX: do not flush receive queue here. We don't want
+-       * to flush data frames already in queue because of
+-       * changing channel. */
++      ret = ath_drain_all_txq(sc, retry_tx);
+-      if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
+-              fastcc = false;
++      if (!ath_stoprecv(sc))
++              ret = false;
+-      if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
+-              caldata = &sc->caldata;
++      if (!flush) {
++              if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
++                      ath_rx_tasklet(sc, 0, true);
++              ath_rx_tasklet(sc, 0, false);
++      } else {
++              ath_flushrecv(sc);
++      }
+-      ath_dbg(common, ATH_DBG_CONFIG,
+-              "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
+-              sc->sc_ah->curchan->channel,
+-              channel->center_freq, conf_is_ht40(conf),
+-              fastcc);
++      return ret;
++}
+-      r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
+-      if (r) {
+-              ath_err(common,
+-                      "Unable to reset channel (%u MHz), reset status %d\n",
+-                      channel->center_freq, r);
+-              goto ps_restore;
+-      }
++static bool ath_complete_reset(struct ath_softc *sc, bool start)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      struct ath_common *common = ath9k_hw_common(ah);
+       if (ath_startrecv(sc) != 0) {
+               ath_err(common, "Unable to restart recv logic\n");
+-              r = -EIO;
+-              goto ps_restore;
++              return false;
+       }
+       ath9k_cmn_update_txpow(ah, sc->curtxpow,
+@@ -297,21 +270,95 @@ static int ath_set_channel(struct ath_so
+       ath9k_hw_set_interrupts(ah, ah->imask);
+       ath9k_hw_enable_interrupts(ah);
+-      if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
++      if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) {
+               if (sc->sc_flags & SC_OP_BEACONS)
+                       ath_set_beacon(sc);
++
+               ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+               ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
+               if (!common->disable_ani)
+                       ath_start_ani(common);
+       }
+- ps_restore:
+-      ieee80211_wake_queues(hw);
++      ieee80211_wake_queues(sc->hw);
++
++      return true;
++}
++
++static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
++                            bool retry_tx)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      struct ath_common *common = ath9k_hw_common(ah);
++      struct ath9k_hw_cal_data *caldata = NULL;
++      bool fastcc = true;
++      bool flush = false;
++      int r;
++
++      __ath_cancel_work(sc);
++
++      spin_lock_bh(&sc->sc_pcu_lock);
++
++      sc->sc_flags &= ~SC_OP_HW_RESET;
++      if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) {
++              fastcc = false;
++              caldata = &sc->caldata;
++      }
++
++      if (!hchan) {
++              fastcc = false;
++              flush = true;
++              hchan = ah->curchan;
++      }
++
++      if (fastcc && !ath9k_hw_check_alive(ah))
++              fastcc = false;
++
++      if (!ath_prepare_reset(sc, retry_tx, flush))
++              fastcc = false;
++
++      ath_dbg(common, ATH_DBG_CONFIG,
++              "Reset to %u MHz, HT40: %d fastcc: %d\n",
++              hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS |
++                                                        CHANNEL_HT40PLUS)),
++              fastcc);
++
++      r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
++      if (r) {
++              ath_err(common,
++                      "Unable to reset channel, reset status %d\n", r);
++              goto out;
++      }
++
++      if (!ath_complete_reset(sc, true))
++              r = -EIO;
++
++out:
+       spin_unlock_bh(&sc->sc_pcu_lock);
++      return r;
++}
++
++
++/*
++ * Set/change channels.  If the channel is really being changed, it's done
++ * by reseting the chip.  To accomplish this we must first cleanup any pending
++ * DMA, then restart stuff.
++*/
++static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
++                  struct ath9k_channel *hchan)
++{
++      int r;
++
++      if (sc->sc_flags & SC_OP_INVALID)
++              return -EIO;
++
++      ath9k_ps_wakeup(sc);
++
++      r = ath_reset_internal(sc, hchan, false);
+       ath9k_ps_restore(sc);
++
+       return r;
+ }
+@@ -824,28 +871,13 @@ static void ath_radio_enable(struct ath_
+                       channel->center_freq, r);
+       }
+-      ath9k_cmn_update_txpow(ah, sc->curtxpow,
+-                             sc->config.txpowlimit, &sc->curtxpow);
+-      if (ath_startrecv(sc) != 0) {
+-              ath_err(common, "Unable to restart recv logic\n");
+-              goto out;
+-      }
+-      if (sc->sc_flags & SC_OP_BEACONS)
+-              ath_set_beacon(sc);     /* restart beacons */
+-
+-      /* Re-Enable  interrupts */
+-      ath9k_hw_set_interrupts(ah, ah->imask);
+-      ath9k_hw_enable_interrupts(ah);
++      ath_complete_reset(sc, true);
+       /* 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);
+-      ieee80211_wake_queues(hw);
+-      ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
+-
+-out:
+       spin_unlock_bh(&sc->sc_pcu_lock);
+       ath9k_ps_restore(sc);
+@@ -858,11 +890,10 @@ void ath_radio_disable(struct ath_softc 
+       int r;
+       ath9k_ps_wakeup(sc);
+-      cancel_delayed_work_sync(&sc->hw_pll_work);
+-      spin_lock_bh(&sc->sc_pcu_lock);
++      ath_cancel_work(sc);
+-      ieee80211_stop_queues(hw);
++      spin_lock_bh(&sc->sc_pcu_lock);
+       /*
+        * Keep the LED on when the radio is disabled
+@@ -873,13 +904,7 @@ void ath_radio_disable(struct ath_softc 
+               ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
+       }
+-      /* Disable interrupts */
+-      ath9k_hw_disable_interrupts(ah);
+-
+-      ath_drain_all_txq(sc, false);   /* clear pending tx frames */
+-
+-      ath_stoprecv(sc);               /* turn off frame recv */
+-      ath_flushrecv(sc);              /* flush recv queue */
++      ath_prepare_reset(sc, false, true);
+       if (!ah->curchan)
+               ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
+@@ -901,49 +926,11 @@ void ath_radio_disable(struct ath_softc 
+ 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(ah);
+-      struct ieee80211_hw *hw = sc->hw;
+       int r;
+-      sc->sc_flags &= ~SC_OP_HW_RESET;
+-      sc->hw_busy_count = 0;
+-
+-      /* Stop ANI */
+-
+-      del_timer_sync(&common->ani.timer);
+-
+       ath9k_ps_wakeup(sc);
+-      ieee80211_stop_queues(hw);
+-
+-      ath9k_hw_disable_interrupts(ah);
+-      ath_drain_all_txq(sc, retry_tx);
+-
+-      ath_stoprecv(sc);
+-      ath_flushrecv(sc);
+-
+-      r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
+-      if (r)
+-              ath_err(common,
+-                      "Unable to reset hardware; reset status %d\n", r);
+-
+-      if (ath_startrecv(sc) != 0)
+-              ath_err(common, "Unable to start recv logic\n");
+-
+-      /*
+-       * We may be doing a reset in response to a request
+-       * that changes the channel so update any state that
+-       * might change as a result.
+-       */
+-      ath9k_cmn_update_txpow(ah, sc->curtxpow,
+-                             sc->config.txpowlimit, &sc->curtxpow);
+-
+-      if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
+-              ath_set_beacon(sc);     /* restart beacons */
+-
+-      ath9k_hw_set_interrupts(ah, ah->imask);
+-      ath9k_hw_enable_interrupts(ah);
++      r = ath_reset_internal(sc, NULL, retry_tx);
+       if (retry_tx) {
+               int i;
+@@ -956,12 +943,6 @@ static int ath_reset(struct ath_softc *s
+               }
+       }
+-      ieee80211_wake_queues(hw);
+-
+-      /* Start ANI */
+-      if (!common->disable_ani)
+-              ath_start_ani(common);
+-
+       ath9k_ps_restore(sc);
+       return r;
+@@ -971,9 +952,7 @@ void ath_reset_work(struct work_struct *
+ {
+       struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
+-      spin_lock_bh(&sc->sc_pcu_lock);
+       ath_reset(sc, true);
+-      spin_unlock_bh(&sc->sc_pcu_lock);
+ }
+ void ath_hw_check(struct work_struct *work)
+@@ -994,11 +973,8 @@ 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) {
+-                      spin_lock_bh(&sc->sc_pcu_lock);
+-                      ath_reset(sc, true);
+-                      spin_unlock_bh(&sc->sc_pcu_lock);
+-              }
++              if (++sc->hw_busy_count >= 3)
++                      ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+       } else if (busy >= 0)
+               sc->hw_busy_count = 0;
+@@ -1018,9 +994,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");
+-                      spin_lock_bh(&sc->sc_pcu_lock);
+-                      ath_reset(sc, true);
+-                      spin_unlock_bh(&sc->sc_pcu_lock);
++                      ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+                       count = 0;
+               }
+       } else
+@@ -1091,28 +1065,6 @@ static int ath9k_start(struct ieee80211_
+               goto mutex_unlock;
+       }
+-      /*
+-       * This is needed only to setup initial state
+-       * but it's best done after a reset.
+-       */
+-      ath9k_cmn_update_txpow(ah, sc->curtxpow,
+-                      sc->config.txpowlimit, &sc->curtxpow);
+-
+-      /*
+-       * Setup the hardware after reset:
+-       * The receive engine is set going.
+-       * Frame transmit is handled entirely
+-       * in the frame output path; there's nothing to do
+-       * here except setup the interrupt mask.
+-       */
+-      if (ath_startrecv(sc) != 0) {
+-              ath_err(common, "Unable to start recv logic\n");
+-              r = -EIO;
+-              spin_unlock_bh(&sc->sc_pcu_lock);
+-              goto mutex_unlock;
+-      }
+-      spin_unlock_bh(&sc->sc_pcu_lock);
+-
+       /* Setup our intr mask. */
+       ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
+                   ATH9K_INT_RXORN | ATH9K_INT_FATAL |
+@@ -1135,12 +1087,14 @@ static int ath9k_start(struct ieee80211_
+       /* Disable BMISS interrupt when we're not associated */
+       ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+-      ath9k_hw_set_interrupts(ah, ah->imask);
+-      ath9k_hw_enable_interrupts(ah);
+-      ieee80211_wake_queues(hw);
++      if (!ath_complete_reset(sc, false)) {
++              r = -EIO;
++              spin_unlock_bh(&sc->sc_pcu_lock);
++              goto mutex_unlock;
++      }
+-      ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
++      spin_unlock_bh(&sc->sc_pcu_lock);
+       if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
+           !ah->btcoex_hw.enabled) {
+@@ -1233,11 +1187,7 @@ static void ath9k_stop(struct ieee80211_
+       mutex_lock(&sc->mutex);
+-      cancel_delayed_work_sync(&sc->tx_complete_work);
+-      cancel_delayed_work_sync(&sc->hw_pll_work);
+-      cancel_work_sync(&sc->paprd_work);
+-      cancel_work_sync(&sc->hw_check_work);
+-      cancel_work_sync(&sc->hw_reset_work);
++      ath_cancel_work(sc);
+       if (sc->sc_flags & SC_OP_INVALID) {
+               ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
+@@ -2354,9 +2304,11 @@ static void ath9k_flush(struct ieee80211
+       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);
+-      spin_unlock_bh(&sc->sc_pcu_lock);
++
+       ath9k_ps_restore(sc);
+       ieee80211_wake_queues(hw);
diff --git a/package/mac80211/patches/583-ath9k_antenna_control.patch b/package/mac80211/patches/583-ath9k_antenna_control.patch
new file mode 100644 (file)
index 0000000..08f1b8f
--- /dev/null
@@ -0,0 +1,178 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -652,9 +652,22 @@ static void ath9k_init_txpower_limits(st
+       ah->curchan = curchan;
+ }
++void ath9k_reload_chainmask_settings(struct ath_softc *sc)
++{
++      if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT))
++              return;
++
++      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
++              setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
++      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
++              setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
++}
++
++
+ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
+ {
+-      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++      struct ath_hw *ah = sc->sc_ah;
++      struct ath_common *common = ath9k_hw_common(ah);
+       hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+               IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+@@ -692,6 +705,16 @@ void ath9k_set_hw_capab(struct ath_softc
+       hw->sta_data_size = sizeof(struct ath_node);
+       hw->vif_data_size = sizeof(struct ath_vif);
++      hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
++      hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
++
++      /* single chain devices with rx diversity */
++      if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
++              hw->wiphy->available_antennas_rx = BIT(0) | BIT(1);
++
++      sc->ant_rx = hw->wiphy->available_antennas_rx;
++      sc->ant_tx = hw->wiphy->available_antennas_tx;
++
+ #ifdef CONFIG_ATH9K_RATE_CONTROL
+       hw->rate_control_algorithm = "ath9k_rate_control";
+ #endif
+@@ -703,12 +726,7 @@ void ath9k_set_hw_capab(struct ath_softc
+               hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+                       &sc->sbands[IEEE80211_BAND_5GHZ];
+-      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
+-              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+-                      setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+-              if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+-                      setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
+-      }
++      ath9k_reload_chainmask_settings(sc);
+       SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
+ }
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -655,6 +655,7 @@ struct ath_softc {
+       struct ath_descdma txsdma;
+       struct ath_ant_comb ant_comb;
++      u8 ant_tx, ant_rx;
+ };
+ void ath9k_tasklet(unsigned long data);
+@@ -675,6 +676,7 @@ int ath9k_init_device(u16 devid, struct 
+                   const struct ath_bus_ops *bus_ops);
+ void ath9k_deinit_device(struct ath_softc *sc);
+ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
++void ath9k_reload_chainmask_settings(struct ath_softc *sc);
+ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
+ bool ath9k_uses_beacons(int type);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -280,6 +280,22 @@ static bool ath_complete_reset(struct at
+                       ath_start_ani(common);
+       }
++      if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) {
++              struct ath_hw_antcomb_conf div_ant_conf;
++              u8 lna_conf;
++
++              ath9k_hw_antdiv_comb_conf_get(ah, &div_ant_conf);
++
++              if (sc->ant_rx == 1)
++                      lna_conf = ATH_ANT_DIV_COMB_LNA1;
++              else
++                      lna_conf = ATH_ANT_DIV_COMB_LNA2;
++              div_ant_conf.main_lna_conf = lna_conf;
++              div_ant_conf.alt_lna_conf = lna_conf;
++
++              ath9k_hw_antdiv_comb_conf_set(ah, &div_ant_conf);
++      }
++
+       ieee80211_wake_queues(sc->hw);
+       return true;
+@@ -2385,6 +2401,59 @@ static int ath9k_get_stats(struct ieee80
+       return 0;
+ }
++static u32 fill_chainmask(u32 cap, u32 new)
++{
++      u32 filled = 0;
++      int i;
++
++      for (i = 0; cap && new; i++, cap >>= 1) {
++              if (!(cap & BIT(0)))
++                      continue;
++
++              if (new & BIT(0))
++                      filled |= BIT(i);
++
++              new >>= 1;
++      }
++
++      return filled;
++}
++
++static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
++{
++      struct ath_softc *sc = hw->priv;
++      struct ath_hw *ah = sc->sc_ah;
++
++      if (!rx_ant || !tx_ant)
++              return -EINVAL;
++
++      sc->ant_rx = rx_ant;
++      sc->ant_tx = tx_ant;
++
++      if (ah->caps.rx_chainmask == 1)
++              return 0;
++
++      /* AR9100 runs into calibration issues if not all rx chains are enabled */
++      if (AR_SREV_9100(ah))
++              ah->rxchainmask = 0x7;
++      else
++              ah->rxchainmask = fill_chainmask(ah->caps.rx_chainmask, rx_ant);
++
++      ah->txchainmask = fill_chainmask(ah->caps.tx_chainmask, tx_ant);
++      ath9k_reload_chainmask_settings(sc);
++
++      return 0;
++}
++
++static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
++{
++      struct ath_softc *sc = hw->priv;
++
++      *tx_ant = sc->ant_tx;
++      *rx_ant = sc->ant_rx;
++      return 0;
++}
++
+ struct ieee80211_ops ath9k_ops = {
+       .tx                 = ath9k_tx,
+       .start              = ath9k_start,
+@@ -2411,4 +2480,6 @@ struct ieee80211_ops ath9k_ops = {
+       .tx_frames_pending  = ath9k_tx_frames_pending,
+       .tx_last_beacon     = ath9k_tx_last_beacon,
+       .get_stats          = ath9k_get_stats,
++      .set_antenna        = ath9k_set_antenna,
++      .get_antenna        = ath9k_get_antenna,
+ };
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -1956,7 +1956,7 @@ int ath_rx_tasklet(struct ath_softc *sc,
+                       ath_rx_ps(sc, skb);
+               spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+-              if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
++              if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3)
+                       ath_ant_comb_scan(sc, &rs);
+               ieee80211_rx(hw, skb);
diff --git a/package/mac80211/patches/590-ath9k_fix_5ghz_adc_cal.patch b/package/mac80211/patches/590-ath9k_fix_5ghz_adc_cal.patch
new file mode 100644 (file)
index 0000000..79a2d35
--- /dev/null
@@ -0,0 +1,12 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+@@ -41,7 +41,8 @@ static bool ar9002_hw_is_cal_supported(s
+       case ADC_DC_CAL:
+               /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */
+               if (!IS_CHAN_B(chan) &&
+-                  !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
++                  !((IS_CHAN_2GHZ(chan) || IS_CHAN_A_FAST_CLOCK(ah, chan)) &&
++                    IS_CHAN_HT20(chan)))
+                       supported = true;
+               break;
+       }
diff --git a/package/mac80211/patches/591-ath9k_cleanup_rx_status_rate.patch b/package/mac80211/patches/591-ath9k_cleanup_rx_status_rate.patch
new file mode 100644 (file)
index 0000000..a6fddb3
--- /dev/null
@@ -0,0 +1,24 @@
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -596,7 +596,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))
diff --git a/package/mac80211/patches/592-ath9k_strip_initvals.patch b/package/mac80211/patches/592-ath9k_strip_initvals.patch
new file mode 100644 (file)
index 0000000..7ac3562
--- /dev/null
@@ -0,0 +1,4104 @@
+--- a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h
++++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h
+@@ -14,70 +14,71 @@
+  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  */
+-static const u32 ar5416Modes[][6] = {
+-      {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+-      {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+-      {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+-      {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
+-      {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+-      {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
+-      {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
+-      {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
+-      {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+-      {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+-      {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+-      {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+-      {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+-      {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+-      {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0},
+-      {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+-      {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+-      {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+-      {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de},
+-      {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+-      {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
+-      {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
+-      {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+-      {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
+-      {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+-      {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+-      {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134},
+-      {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
+-      {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+-      {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
+-      {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
+-      {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80},
+-      {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120},
+-      {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
+-      {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+-      {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+-      {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
+-      {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+-      {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+-      {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+-      {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
+-      {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
+-      {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
+-      {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120},
+-      {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+-      {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+-      {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
+-      {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+-      {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
+-      {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
+-      {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
+-      {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
+-      {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
+-      {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
+-      {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
+-      {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
+-      {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
+-      {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++static const u32 ar5416Modes[][5] = {
++      /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
++      {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
++      {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
++      {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
++      {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
++      {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
++      {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
++      {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
++      {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
++      {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
++      {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
++      {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
++      {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
++      {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
++      {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
++      {0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0},
++      {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
++      {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
++      {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
++      {0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de},
++      {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
++      {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
++      {0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18},
++      {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
++      {0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190},
++      {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
++      {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
++      {0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134},
++      {0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b},
++      {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
++      {0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
++      {0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
++      {0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80},
++      {0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120},
++      {0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00},
++      {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
++      {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
++      {0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c},
++      {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
++      {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
++      {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
++      {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
++      {0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
++      {0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
++      {0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120},
++      {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
++      {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
++      {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
++      {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
++      {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
++      {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
++      {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
++      {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
++      {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
++      {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
++      {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
++      {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
++      {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
++      {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
++      {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ };
+ static const u32 ar5416Common[][2] = {
+@@ -668,6 +669,6 @@ static const u32 ar5416Addac[][2] = {
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+       {0x0000989c, 0x00000000},
+-      {0x000098cc, 0x00000000},
++      {0x000098c4, 0x00000000},
+ };
+--- a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h
++++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h
+@@ -14,73 +14,74 @@
+  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  */
+-static const u32 ar5416Modes_9100[][6] = {
+-      {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+-      {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+-      {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+-      {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
+-      {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+-      {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
+-      {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
+-      {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
+-      {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+-      {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+-      {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+-      {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+-      {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+-      {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+-      {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
+-      {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+-      {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+-      {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+-      {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
+-      {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+-      {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
+-      {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
+-      {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+-      {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+-      {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+-      {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+-      {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
+-      {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
+-      {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204},
+-      {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
+-      {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e},
+-      {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff},
+-      {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+-      {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+-      {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
+-      {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+-      {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00},
+-      {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+-      {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+-      {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+-      {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+-      {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+-      {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+-      {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
+-      {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+-      {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+-      {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+-      {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+-      {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+-      {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
+-      {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+-      {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
+-      {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
+-      {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
+-      {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
+-      {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
+-      {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
+-      {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
+-      {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
+-      {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
+-      {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++static const u32 ar5416Modes_9100[][5] = {
++      /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
++      {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
++      {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
++      {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
++      {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
++      {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
++      {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
++      {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
++      {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
++      {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
++      {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
++      {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
++      {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
++      {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
++      {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
++      {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
++      {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
++      {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
++      {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
++      {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
++      {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
++      {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
++      {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
++      {0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
++      {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
++      {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
++      {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
++      {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
++      {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
++      {0x00009940, 0x00750604, 0x00754604, 0xfff81204, 0xfff81204},
++      {0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020},
++      {0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e},
++      {0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff},
++      {0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
++      {0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
++      {0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0},
++      {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
++      {0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00},
++      {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
++      {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
++      {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
++      {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
++      {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
++      {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
++      {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
++      {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
++      {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
++      {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
++      {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
++      {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
++      {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
++      {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
++      {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
++      {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
++      {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
++      {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
++      {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
++      {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
++      {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
++      {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
++      {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
++      {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
++      {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ };
+ static const u32 ar5416Common_9100[][2] = {
+@@ -666,71 +667,72 @@ static const u32 ar5416Addac_9100[][2] =
+       {0x000098cc, 0x00000000},
+ };
+-static const u32 ar5416Modes_9160[][6] = {
+-      {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+-      {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+-      {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+-      {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008},
+-      {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+-      {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf},
+-      {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
+-      {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
+-      {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+-      {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+-      {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+-      {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+-      {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+-      {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+-      {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
+-      {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+-      {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+-      {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68},
+-      {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2, 0x6c48b0e2},
+-      {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
+-      {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
+-      {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
+-      {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+-      {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
+-      {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
+-      {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+-      {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016},
+-      {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
+-      {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
+-      {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+-      {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+-      {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
+-      {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
+-      {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
+-      {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00},
+-      {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
+-      {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
+-      {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
+-      {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
+-      {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
+-      {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
+-      {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788},
+-      {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+-      {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+-      {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120},
+-      {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+-      {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+-      {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa},
+-      {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
+-      {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402},
+-      {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06},
+-      {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b},
+-      {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b},
+-      {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a},
+-      {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf},
+-      {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f},
+-      {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f},
+-      {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f},
+-      {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++static const u32 ar5416Modes_9160[][5] = {
++      /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
++      {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
++      {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
++      {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
++      {0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000},
++      {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
++      {0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab},
++      {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
++      {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
++      {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
++      {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
++      {0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
++      {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
++      {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
++      {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
++      {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
++      {0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
++      {0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
++      {0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68},
++      {0x00009850, 0x6c48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6c48b0e2},
++      {0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e},
++      {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
++      {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
++      {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
++      {0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0},
++      {0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081},
++      {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
++      {0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
++      {0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d},
++      {0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020},
++      {0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
++      {0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
++      {0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40},
++      {0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120},
++      {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
++      {0x000099bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00},
++      {0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be},
++      {0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77},
++      {0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329},
++      {0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8},
++      {0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384},
++      {0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880},
++      {0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788},
++      {0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
++      {0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
++      {0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120},
++      {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
++      {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
++      {0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa},
++      {0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000},
++      {0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402},
++      {0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06},
++      {0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b},
++      {0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b},
++      {0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a},
++      {0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf},
++      {0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f},
++      {0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f},
++      {0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f},
++      {0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000},
++      {0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ };
+ static const u32 ar5416Common_9160[][2] = {
+--- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
++++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h
+@@ -14,53 +14,54 @@
+  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  */
+-static const u32 ar9280Modes_9280_2[][6] = {
+-      {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0},
+-      {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0},
+-      {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180},
+-      {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008},
+-      {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0},
+-      {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f},
+-      {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810},
+-      {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a},
+-      {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880},
+-      {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303},
+-      {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
+-      {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+-      {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
+-      {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+-      {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
+-      {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e},
+-      {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0},
+-      {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2},
+-      {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e},
+-      {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e},
+-      {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18},
+-      {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
+-      {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+-      {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881},
+-      {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0},
+-      {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016},
+-      {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d},
+-      {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
+-      {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+-      {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
+-      {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
+-      {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce},
+-      {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
+-      {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00},
+-      {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+-      {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
+-      {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
+-      {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019},
+-      {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
+-      {0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000},
+-      {0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000},
+-      {0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000},
+-      {0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e},
+-      {0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000},
+-      {0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+-      {0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000},
++static const u32 ar9280Modes_9280_2[][5] = {
++      /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
++      {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
++      {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
++      {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
++      {0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
++      {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
++      {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
++      {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
++      {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
++      {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
++      {0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300},
++      {0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200},
++      {0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
++      {0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
++      {0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
++      {0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007},
++      {0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
++      {0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
++      {0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
++      {0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
++      {0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
++      {0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20},
++      {0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00},
++      {0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
++      {0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
++      {0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
++      {0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b},
++      {0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d},
++      {0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010},
++      {0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
++      {0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010},
++      {0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210},
++      {0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
++      {0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c},
++      {0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00},
++      {0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
++      {0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444},
++      {0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
++      {0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019},
++      {0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a},
++      {0x0000a230, 0x00000000, 0x00000000, 0x00000210,&nb