mac80211: backport from trunk
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Thu, 22 Dec 2011 06:05:25 +0000 (06:05 +0000)
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Thu, 22 Dec 2011 06:05:25 +0000 (06:05 +0000)
git-svn-id: svn://svn.openwrt.org/openwrt/branches/backfire@29599 3c298f89-4303-0410-b956-a3cf2f4a3e73

67 files changed:
package/mac80211/Makefile
package/mac80211/diff.txt [new file with mode: 0644]
package/mac80211/files/host_bin/b43-fwsquash.py
package/mac80211/files/lib/wifi/mac80211.sh
package/mac80211/patches/001-disable_b44.patch
package/mac80211/patches/002-disable_rfkill.patch
package/mac80211/patches/003-disable_bt.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/008-disable_mesh.patch [new file with mode: 0644]
package/mac80211/patches/009-remove_mac80211_module_dependence.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/016-remove_pid_algo.patch
package/mac80211/patches/017-remove_ath9k_rc.patch
package/mac80211/patches/019-remove_ath5k_pci_option.patch
package/mac80211/patches/021-add_include_for_bcma.patch
package/mac80211/patches/022-atomic64_backport.patch [deleted file]
package/mac80211/patches/050-compat_firmware.patch
package/mac80211/patches/051-compat_workqueue.patch [deleted file]
package/mac80211/patches/060-fix_compat_security.patch [new file with mode: 0644]
package/mac80211/patches/070-deactivate_mac80211_tracing.patch [new file with mode: 0644]
package/mac80211/patches/100-disable_pcmcia_compat.patch
package/mac80211/patches/110-disable_usb_compat.patch
package/mac80211/patches/120-pr_fmt_warnings.patch
package/mac80211/patches/130-fix_sublevel_check.patch
package/mac80211/patches/140-mesh_pathtbl_backport.patch
package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch
package/mac80211/patches/300-pending_work.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/510-ath9k_intr_mitigation_tweak.patch
package/mac80211/patches/513-ath9k_channelbw_debugfs.patch
package/mac80211/patches/520-mac80211_ht_change_rate_update.patch [moved from package/mac80211/patches/521-mac80211_ht_change_rate_update.patch with 87% similarity]
package/mac80211/patches/520-mac80211_minstrel_ht_aggr_delay.patch [deleted file]
package/mac80211/patches/522-mac80211_reduce_txqueuelen.patch
package/mac80211/patches/523-minstrel_ht_optimize.patch [deleted file]
package/mac80211/patches/530-mac80211_cur_txpower.patch
package/mac80211/patches/531-ath9k_cur_txpower.patch
package/mac80211/patches/542-ath9k_ar9280_cold_reset.patch
package/mac80211/patches/543-ath9k_enable_ar9100_ani.patch [deleted file]
package/mac80211/patches/543-ath9k_fix_half_quarter_rx_latency.patch [new file with mode: 0644]
package/mac80211/patches/544-ath9k_fix_half_quarter_sifs.patch [new file with mode: 0644]
package/mac80211/patches/544-ath9k_fix_sleep_mode_reg.patch [deleted file]
package/mac80211/patches/551-ath9k_per_chain_signal_strength.patch
package/mac80211/patches/560-ath9k_rework_send_bar.patch [new file with mode: 0644]
package/mac80211/patches/560-mac80211_fix_ap_vlan_aggr.patch [deleted file]
package/mac80211/patches/561-ath9k_reduce_indentation.patch [new file with mode: 0644]
package/mac80211/patches/562-ath9k_remove_seq_incr.patch [new file with mode: 0644]
package/mac80211/patches/563-ath9k_simplify_tx_locking.patch [new file with mode: 0644]
package/mac80211/patches/564-ath9k_track_last_bar.patch [new file with mode: 0644]
package/mac80211/patches/565-ath9k_fix_lockup.patch [new file with mode: 0644]
package/mac80211/patches/570-ath9k_mci_static.patch [new file with mode: 0644]
package/mac80211/patches/571-ath9k_btcoex_optional.patch [new file with mode: 0644]
package/mac80211/patches/580-ath9k_extra_leds.patch [new file with mode: 0644]
package/mac80211/patches/581-ath9k_extra_platform_leds.patch [new file with mode: 0644]
package/mac80211/patches/604-rt2x00-add-CONFIG_RT2X00_LIB_EEPROM-option.patch
package/mac80211/patches/850-p54spi-lock-fix.patch [deleted file]
package/mac80211/patches/851-p54spi-mutex-fix.patch [deleted file]
package/mac80211/patches/852-p54spi-cancel-workqueue-fix.patch [deleted file]
package/mac80211/patches/910-fix-reversed-warn-on-workqueue.patch [deleted file]
target/linux/ar71xx/files/include/linux/ath9k_platform.h

index 92ea370..1a06cef 100644 (file)
@@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=mac80211
 
-PKG_VERSION:=2011-11-15
+PKG_VERSION:=2011-12-01
 PKG_RELEASE:=1
 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
-PKG_MD5SUM:=0bb667c7fecbc244840d806df0604661
+PKG_MD5SUM:=8d1fe2fd6bbabc4fbbf31dfbf015c62c
 
 PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
@@ -32,6 +32,7 @@ PKG_CONFIG_DEPENDS:= \
        CONFIG_PACKAGE_kmod-mac80211 \
        $(patsubst %,CONFIG_PACKAGE_kmod-%,$(PKG_DRIVERS)) \
        CONFIG_PACKAGE_MAC80211_DEBUGFS \
+       CONFIG_PACKAGE_MAC80211_MESH \
        CONFIG_PACKAGE_ATH_DEBUG \
        CONFIG_PACKAGE_B43_DEBUG \
        CONFIG_PACKAGE_B43_PIO \
@@ -89,6 +90,10 @@ define KernelPackage/mac80211/config
 
                  Say N unless you know you need this.
 
+       config PACKAGE_MAC80211_MESH
+               bool "Enable 802.11s mesh support"
+               default y
+
        endmenu
 endef
 
@@ -704,7 +709,7 @@ define KernelPackage/iwl-legacy
   $(call KernelPackage/mac80211/Default)
   DEPENDS:= +kmod-mac80211 @PCI_SUPPORT
   TITLE:=Intel legacy Wireless support
-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwl-legacy.ko
+  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlegacy/iwlegacy.ko
   AUTOLOAD:=$(call AutoLoad,60,iwl-legacy)
 endef
 
@@ -766,6 +771,14 @@ ifneq ($(CONFIG_B43_FW_4_178),)
   PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
   PKG_B43_FWV4_SOURCE_URL:=http://mirror2.openwrt.org/sources/
   PKG_B43_FWV4_MD5SUM:=14477e8cbbb91b11896affac9b219fdb
+else
+ifneq ($(CONFIG_B43_FW_5_100_138),)
+  PKG_B43_FWV4_NAME:=broadcom-wl
+  PKG_B43_FWV4_VERSION:=5.100.138
+  PKG_B43_FWV4_OBJECT:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION)/linux/wl_apsta.o
+  PKG_B43_FWV4_SOURCE:=$(PKG_B43_FWV4_NAME)-$(PKG_B43_FWV4_VERSION).tar.bz2
+  PKG_B43_FWV4_SOURCE_URL:=http://www.lwfinger.com/b43-firmware/
+  PKG_B43_FWV4_MD5SUM:=f4e357b09eaf5d8b1f1920cf3493a555
 else
   PKG_B43_FWV4_NAME:=broadcom-wl
   PKG_B43_FWV4_VERSION:=4.150.10.5
@@ -775,6 +788,7 @@ else
   PKG_B43_FWV4_MD5SUM:=0c6ba9687114c6b598e8019e262d9a60
 endif
 endif
+endif
 ifneq ($(CONFIG_B43_OPENFIRMWARE),)
   PKG_B43_FWV4_NAME:=broadcom-wl
   PKG_B43_FWV4_VERSION:=5.2
@@ -801,11 +815,11 @@ ifeq ($(CONFIG_B43_OPENFIRMWARE),y)
   PKG_B43_FWCUTTER_OBJECT:=$(PKG_B43_FWCUTTER_NAME)-$(PKG_B43_FWCUTTER_VERSION)/fwcutter/
 else
   PKG_B43_FWCUTTER_NAME:=b43-fwcutter
-  PKG_B43_FWCUTTER_VERSION:=014
+  PKG_B43_FWCUTTER_VERSION:=015
   PKG_B43_FWCUTTER_SOURCE:=$(PKG_B43_FWCUTTER_NAME)-$(PKG_B43_FWCUTTER_VERSION).tar.bz2
   PKG_B43_FWCUTTER_PROTO:=default
   PKG_B43_FWCUTTER_SOURCE_URL:=http://bu3sch.de/b43/fwcutter/
-  PKG_B43_FWCUTTER_MD5SUM:=dd63f9149510bd6e01b89314e955083b
+  PKG_B43_FWCUTTER_MD5SUM:=628e030565222a107bc40300313cbe76
   PKG_B43_FWCUTTER_SUBDIR:=b43-fwcutter-$(PKG_B43_FWCUTTER_VERSION)
   PKG_B43_FWCUTTER_OBJECT:=$(PKG_B43_FWCUTTER_NAME)-$(PKG_B43_FWCUTTER_VERSION)/
 endif
@@ -886,6 +900,15 @@ define KernelPackage/b43/config
 
                  If unsure, select the "stable" firmware.
 
+       config B43_FW_5_100_138
+               bool "Firmware 666.2 from driver 5.100.138"
+               help
+                 Newer experimental firmware for BCM43xx devices.
+
+                 This firmware is mostly untested. It is needed for some N-PHY devices.
+
+                 If unsure, select the "stable" firmware.
+
        config B43_OPENFIRMWARE
                bool "Open FirmWare for WiFi networks"
                help
@@ -964,14 +987,33 @@ define KernelPackage/b43/config
 
        config PACKAGE_B43_PHY_N
                bool "Enable support for N-PHYs"
-               select B43_FW_5_10
-               depends BROKEN
-               default n
+               depends on BROKEN
+               select B43_FW_5_100_138
                help
                  Enable support for BCM4321 and BCM4322.
 
                  Currently only 11g speed is available.
 
+                 If unsure, say Y.
+
+       config PACKAGE_B43_PHY_HT
+               bool "Enable support for HT-PHYs"
+               depends on BROKEN
+               select B43_FW_5_100_138
+               default n
+               help
+                 Currently broken.
+
+                 If unsure, say N.
+
+       config PACKAGE_B43_PHY_LCN
+               bool "Enable support for LCN-PHYs"
+               depends on BROKEN
+               select B43_FW_5_100_138
+               default n
+               help
+                 Currently broken.
+
                  If unsure, say N.
 
        endmenu
@@ -1032,13 +1074,18 @@ BUILDFLAGS:= \
        $(if $(CONFIG_PCI),-DCONFIG_ATH9K_PCI) \
        $(if $(CONFIG_TARGET_ar71xx),-DCONFIG_ATH9K_AHB) \
        $(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS), -DCONFIG_CFG80211_DEBUGFS -DCONFIG_MAC80211_DEBUGFS -DCONFIG_ATH9K_DEBUGFS -DCONFIG_CARL9170_DEBUGFS -DCONFIG_ATH9K_HTC_DEBUGFS -DCONFIG_ATH5K_DEBUG) \
+       $(if $(CONFIG_PACKAGE_MAC80211_MESH),-DCONFIG_MAC80211_MESH) \
        $(if $(CONFIG_PACKAGE_ATH_DEBUG),-DCONFIG_ATH_DEBUG -DCONFIG_ATH9K_PKTLOG) \
        -D__CONFIG_MAC80211_RC_DEFAULT=minstrel \
        -DCONFIG_MAC80211_RC_MINSTREL_HT \
        $(if $(CONFIG_ATH_USER_REGD),-DATH_USER_REGD=1) \
        $(if $(CONFIG_PACKAGE_B43_DEBUG),-DCONFIG_B43_DEBUG) \
        $(if $(CONFIG_PACKAGE_B43_PIO),-DCONFIG_B43_PIO) \
+       $(if $(CONFIG_PACKAGE_B43_PIO),-DCONFIG_B43_BCMA_PIO) \
        $(if $(CONFIG_PACKAGE_B43_PHY_N),-DCONFIG_B43_PHY_N) \
+       $(if $(CONFIG_PACKAGE_B43_PHY_HT),-DCONFIG_B43_PHY_HT) \
+       $(if $(CONFIG_PACKAGE_B43_PHY_LCN),-DCONFIG_B43_PHY_LCN) \
+       -DCONFIG_B43_BCMA \
        -DCONFIG_B43_SSB \
        $(if $(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS),-DCONFIG_RT2X00_LIB_DEBUGFS) \
        $(if $(CONFIG_PACKAGE_RT2X00_DEBUG),-DCONFIG_RT2X00_DEBUG) \
@@ -1062,6 +1109,7 @@ MAKE_OPTS:= \
        CONFIG_CFG80211=$(if $(CONFIG_PACKAGE_kmod-cfg80211),m) \
        CONFIG_MAC80211=$(if $(CONFIG_PACKAGE_kmod-mac80211),m) \
        CONFIG_MAC80211_RC_MINSTREL=y \
+       CONFIG_MAC80211_MESH=$(CONFIG_PACKAGE_MAC80211_MESH) \
        CONFIG_MAC80211_LEDS=$(CONFIG_LEDS_TRIGGERS) \
        CONFIG_CFG80211_DEBUGFS=$(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS),y) \
        CONFIG_MAC80211_DEBUGFS=$(if $(CONFIG_PACKAGE_MAC80211_DEBUGFS),y) \
@@ -1076,7 +1124,11 @@ MAKE_OPTS:= \
        CONFIG_B43LEGACY=$(if $(CONFIG_PACKAGE_kmod-b43legacy),m) \
        CONFIG_B43_DEBUG=$(if $(CONFIG_PACKAGE_B43_DEBUG),y) \
        CONFIG_B43_PIO=$(if $(CONFIG_PACKAGE_B43_PIO),y) \
+       CONFIG_B43_BCMA_PIO=$(if $(CONFIG_PACKAGE_B43_PIO),y) \
        CONFIG_B43_PHY_N=$(if $(CONFIG_PACKAGE_B43_PHY_N),y) \
+       CONFIG_B43_PHY_HT=$(if $(CONFIG_PACKAGE_B43_PHY_HT),y) \
+       CONFIG_B43_PHY_LCN=$(if $(CONFIG_PACKAGE_B43_PHY_LCN),y) \
+       CONFIG_B43_BCMA=y \
        CONFIG_B43_SSB=y \
        CONFIG_ATH_COMMON=$(if $(CONFIG_PACKAGE_kmod-ath),m) \
        CONFIG_ATH_DEBUG=$(if $(CONFIG_PACKAGE_ATH_DEBUG),y) \
@@ -1142,7 +1194,7 @@ MAKE_OPTS:= \
        CONFIG_LIB80211_CRYPT_CCMP=$(if $(CONFIG_PACKAGE_kmod-lib80211),m) \
        CONFIG_LIB80211_CRYPT_TKIP=$(if $(CONFIG_PACKAGE_kmod-lib80211),m) \
        CONFIG_IWLWIFI=$(if $(CONFIG_PACKAGE_kmod-iwlagn),m) \
-       CONFIG_IWLWIFI_LEGACY=$(if $(CONFIG_PACKAGE_kmod-iwl-legacy),m) \
+       CONFIG_IWLEGACY=$(if $(CONFIG_PACKAGE_kmod-iwl-legacy),m) \
        CONFIG_COMPAT_IWL4965=$(if $(CONFIG_PACKAGE_kmod-iwl4965),m) \
        CONFIG_IWL3945=$(if $(CONFIG_PACKAGE_kmod-iwl3945),m) \
        CONFIG_MWL8K=$(if $(CONFIG_PACKAGE_kmod-mwl8k),m) \
diff --git a/package/mac80211/diff.txt b/package/mac80211/diff.txt
new file mode 100644 (file)
index 0000000..50afc0c
--- /dev/null
@@ -0,0 +1,89 @@
+--- Makefile   2011-12-22 06:58:51.000000000 +0100
++++ /Users/nbd/openwrt/package/mac80211/Makefile       2011-12-17 16:40:06.000000000 +0100
+@@ -49,7 +49,7 @@
+   SUBMENU:=$(WMENU)
+   URL:=http://linuxwireless.org/
+   MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
+-  DEPENDS:=@(!(TARGET_avr32||TARGET_ep93xx)||BROKEN) @!LINUX_2_4
++  DEPENDS:=@(!(TARGET_avr32||TARGET_ep93xx||TARGET_ps3||TARGET_pxcab||LINUX_3_2)||BROKEN)
+ endef
+ define KernelPackage/cfg80211
+@@ -164,7 +164,7 @@
+ define KernelPackage/p54-common
+   $(call KernelPackage/p54/Default)
+-  DEPENDS+= @PCI_SUPPORT||@USB_SUPPORT||@TARGET_omap24xx +kmod-mac80211 +kmod-crc-ccitt
++  DEPENDS+= @PCI_SUPPORT||@USB_SUPPORT||@TARGET_omap24xx +kmod-mac80211 +kmod-lib-crc-ccitt
+   TITLE+= (COMMON)
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/p54/p54common.ko
+   AUTOLOAD:=$(call AutoLoad,30,p54common)
+@@ -207,7 +207,7 @@
+ define KernelPackage/rt2x00-lib
+ $(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 +kmod-crc-itu-t
++  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-mac80211 +kmod-lib-crc-itu-t
+   TITLE+= (LIB)
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00lib.ko
+   AUTOLOAD:=$(call AutoLoad,25,rt2x00lib)
+@@ -308,7 +308,7 @@
+ define KernelPackage/rt2800-pci
+ $(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-crc-ccitt +TARGET_ramips:kmod-rt2x00-soc
++  DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-lib-crc-ccitt +TARGET_ramips:kmod-rt2x00-soc
+   TITLE+= (RT2860 PCI)
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800pci.ko
+   AUTOLOAD:=$(call AutoLoad,28,rt2800pci)
+@@ -316,7 +316,7 @@
+ define KernelPackage/rt2800-usb
+ $(call KernelPackage/rt2x00/Default)
+-  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-rt2800-lib +kmod-crc-ccitt
++  DEPENDS+= @USB_SUPPORT +kmod-rt2x00-usb +kmod-rt2800-lib +kmod-lib-crc-ccitt
+   TITLE+= (RT2870 USB)
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800usb.ko
+   AUTOLOAD:=$(call AutoLoad,28,rt2800usb)
+@@ -859,6 +859,7 @@
+ define KernelPackage/b43
+ $(call KernelPackage/b43-common)
++  DEPENDS+= +@DRIVER_11N_SUPPORT +!TARGET_brcm47xx:kmod-bcma
+   TITLE:=Broadcom 43xx wireless support
+   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/b43/b43.ko
+   AUTOLOAD:=$(call AutoLoad,30,b43)
+@@ -938,7 +939,7 @@
+       config B43_FW_SQUASH_COREREVS
+               string "Core revisions to include"
+               depends on B43_FW_SQUASH
+-              default "5,6,7,8,9,10,13,14,15"
++              default "5,6,7,8,9,10,11,13,14,15,16"
+               help
+                 This is a comma seperated list of core revision numbers.
+@@ -951,7 +952,7 @@
+       config B43_FW_SQUASH_PHYTYPES
+               string "PHY types to include"
+               depends on B43_FW_SQUASH
+-              default "G,LP"
++              default "G,LP,N"
+               help
+                 This is a comma seperated list of PHY types:
+                   A  => A-PHY
+@@ -977,7 +978,6 @@
+       config PACKAGE_B43_PIO
+               bool "Enable support for PIO transfer mode"
+-              depends BROKEN
+               default n
+               help
+                 Enable support for using PIO instead of DMA. Unless you have DMA
+@@ -1250,6 +1250,7 @@
+       $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2
+       $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_LINUX_FIRMWARE_SOURCE)
+       rm -rf $(PKG_BUILD_DIR)/include/linux/ssb
++      rm -rf $(PKG_BUILD_DIR)/include/linux/bcma
+       rm -f $(PKG_BUILD_DIR)/include/net/ieee80211.h
+ endef
index 1e36964..3a2ea13 100755 (executable)
@@ -70,6 +70,8 @@ revmapping = {
        "ucode14.fw"            : (14,),
        "ucode15.fw"            : (15,),
        "ucode16_mimo.fw"       : (16,),
+       "ucode24_mimo.fw"       : (24,),
+       "ucode29_mimo.fw"       : (29,),
        "pcm4.fw"               : (1,2,3,4,),
        "pcm5.fw"               : (5,6,7,8,9,10,),
 }
@@ -93,6 +95,8 @@ initvalmapping = {
        "lp0bsinitvals13.fw"    : ( (13,),              ("LP",), ),
        "lp0bsinitvals14.fw"    : ( (14,),              ("LP",), ),
        "lp0bsinitvals15.fw"    : ( (15,),              ("LP",), ),
+       "lcn0initvals24.fw"     : ( (24,),              ("LNC",), ),
+       "ht0initvals29.fw"      : ( (29,),              ("HT",), ),
 }
 
 for f in fwfiles:
index 738c2aa..974fe5f 100644 (file)
@@ -363,7 +363,7 @@ enable_mac80211() {
                                iw phy "$phy" interface add "$ifname" type managed $wdsflag
                                config_get_bool powersave "$vif" powersave 0
                                [ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
-                               iwconfig "$ifname" power "$powersave"
+                               iw "$ifname" set power_save "$powersave"
                        ;;
                esac
 
@@ -394,12 +394,6 @@ enable_mac80211() {
                        [ -n "$fixed" -a -n "$channel" ] && iw dev "$ifname" set channel "$channel"
                fi
 
-               config_get vif_txpower "$vif" txpower
-               # use vif_txpower (from wifi-iface) to override txpower (from
-               # wifi-device) if the latter doesn't exist
-               txpower="${txpower:-$vif_txpower}"
-               [ -z "$txpower" ] || iw dev "$ifname" set txpower fixed "${txpower%%.*}00"
-
                i=$(($i + 1))
        done
 
@@ -434,6 +428,12 @@ enable_mac80211() {
                [ ! "$mode" = "ap" ] || continue
                ifconfig "$ifname" up
 
+               config_get vif_txpower "$vif" txpower
+               # use vif_txpower (from wifi-iface) to override txpower (from
+               # wifi-device) if the latter doesn't exist
+               txpower="${txpower:-$vif_txpower}"
+               [ -z "$txpower" ] || iw dev "$ifname" set txpower fixed "${txpower%%.*}00"
+
                if [ ! "$mode" = "ap" ]; then
                        ifconfig "$ifname" up
                        case "$mode" in
index 547a453..52564d1 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -339,8 +339,8 @@ CONFIG_B43_BCMA_PIO=y
+@@ -378,8 +378,8 @@ CONFIG_B43_BCMA_PIO=y
  
  CONFIG_P54_PCI=m
  
index 4ba3047..82f31ae 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -87,7 +87,7 @@ endif # build check
+@@ -95,7 +95,7 @@ endif # build check
  endif # kernel Makefile check
  
  # These both are needed by compat-wireless || compat-bluetooth so enable them
@@ -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")
-@@ -632,10 +632,10 @@ endif #CONFIG_COMPAT_KERNEL_2_6_27
+@@ -671,10 +671,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 ebccddd..d93b0cd 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -109,8 +109,8 @@ ifndef CONFIG_COMPAT_KERNEL_2_6_27
+@@ -117,8 +117,8 @@ ifndef CONFIG_COMPAT_KERNEL_2_6_27
  ifeq ($(CONFIG_BT),y)
  # we'll ignore compiling bluetooth
  else
index ac95769..8e89814 100644 (file)
@@ -18,7 +18,7 @@
  else
  include $(KLIB_BUILD)/.config
  endif
-@@ -315,7 +314,8 @@ CONFIG_IPW2200_QOS=y
+@@ -354,7 +353,8 @@ CONFIG_IPW2200_QOS=y
  # % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
  endif #CONFIG_WIRELESS_EXT
  
@@ -28,7 +28,7 @@
  # Sonics Silicon Backplane
  CONFIG_SSB_SPROM=y
  
-@@ -328,7 +328,7 @@ endif #CONFIG_PCMCIA
+@@ -367,7 +367,7 @@ endif #CONFIG_PCMCIA
  # CONFIG_SSB_DEBUG=y
  CONFIG_SSB_DRIVER_PCICORE=y
  CONFIG_B43_SSB=y
@@ -37,7 +37,7 @@
  
  CONFIG_BCMA=m
  CONFIG_BCMA_BLOCKIO=y
-@@ -535,7 +535,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -574,7 +574,6 @@ endif #CONFIG_SPI_MASTER end of SPI driv
  
  ifdef CONFIG_MMC
  
index 8a82d7e..2d8cdd8 100644 (file)
@@ -10,7 +10,7 @@
  ifeq ($(CONFIG_STAGING_EXCLUDE_BUILD),)
 --- a/config.mk
 +++ b/config.mk
-@@ -330,12 +330,12 @@ CONFIG_SSB_DRIVER_PCICORE=y
+@@ -369,12 +369,12 @@ CONFIG_SSB_DRIVER_PCICORE=y
  CONFIG_B43_SSB=y
  endif #__CONFIG_SSB
  
index 0b4b26e..1181c42 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -213,7 +213,7 @@ $(warning "WARNING: CONFIG_CFG80211_WEXT
+@@ -252,7 +252,7 @@ $(warning "WARNING: CONFIG_CFG80211_WEXT
  endif #CONFIG_WIRELESS_EXT
  
  ifdef CONFIG_STAGING
@@ -9,7 +9,7 @@
  endif #CONFIG_STAGING
  
  # mac80211 test driver
-@@ -367,13 +367,13 @@ endif #CONFIG_CRC_ITU_T
+@@ -406,13 +406,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
-@@ -432,21 +432,21 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+@@ -471,21 +471,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
diff --git a/package/mac80211/patches/008-disable_mesh.patch b/package/mac80211/patches/008-disable_mesh.patch
new file mode 100644 (file)
index 0000000..3c00938
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/config.mk
++++ b/config.mk
+@@ -188,7 +188,7 @@ CONFIG_MAC80211_LEDS=y
+ endif #CONFIG_LEDS_TRIGGERS
+ # enable mesh networking too
+-CONFIG_MAC80211_MESH=y
++# CONFIG_MAC80211_MESH=y
+ CONFIG_CFG80211=m
+ CONFIG_CFG80211_DEFAULT_PS=y
index ed67de2..2e3753e 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -50,23 +50,6 @@ $(error "ERROR: Your 2.6.27 kernel has C
+@@ -58,23 +58,6 @@ $(error "ERROR: Your 2.6.27 kernel has C
  endif
  endif
  
index f6b89d8..4cb88a9 100644 (file)
@@ -9,7 +9,7 @@
  else
  include $(KLIB_BUILD)/.config
  endif
-@@ -247,7 +247,7 @@ CONFIG_B43=m
+@@ -286,7 +286,7 @@ CONFIG_B43=m
  CONFIG_B43_HWRNG=y
  CONFIG_B43_PCI_AUTOSELECT=y
  ifdef CONFIG_PCMCIA
index fc2e6d9..919f1ac 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -518,7 +518,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
+@@ -557,7 +557,7 @@ endif #CONFIG_SPI_MASTER end of SPI driv
  
  ifdef CONFIG_MMC
  
index f9f13e2..287285f 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -253,8 +253,8 @@ ifdef CONFIG_MAC80211_LEDS
+@@ -292,8 +292,8 @@ ifdef CONFIG_MAC80211_LEDS
  CONFIG_B43_LEDS=y
  endif #CONFIG_MAC80211_LEDS
  CONFIG_B43_PHY_LP=y
index 18490c5..fdf34c3 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -329,7 +329,7 @@ CONFIG_RTL8180=m
+@@ -368,7 +368,7 @@ CONFIG_RTL8180=m
  
  CONFIG_ADM8211=m
  
@@ -9,7 +9,7 @@
  CONFIG_RT2400PCI=m
  CONFIG_RT2500PCI=m
  ifdef CONFIG_CRC_CCITT
-@@ -467,7 +467,7 @@ CONFIG_RT2800USB_RT35XX=y
+@@ -506,7 +506,7 @@ CONFIG_RT2800USB_RT35XX=y
  # CONFIG_RT2800USB_RT53XX=y
  CONFIG_RT2800USB_UNKNOWN=y
  endif #CONFIG_CRC_CCITT
index b003f4c..9d22e75 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -124,7 +124,7 @@ CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+@@ -163,7 +163,7 @@ CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
  # This is the one used by our compat-wireless net/mac80211/rate.c
  # in case you have and old kernel which is overriding this to pid.
  CONFIG_COMPAT_MAC80211_RC_DEFAULT=minstrel_ht
index f341556..ad1f146 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -220,7 +220,7 @@ CONFIG_ATH9K_COMMON=m
+@@ -259,7 +259,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 9de0418..513d435 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -225,7 +225,7 @@ CONFIG_ATH9K_COMMON=m
+@@ -264,7 +264,7 @@ CONFIG_ATH9K_COMMON=m
  # PCI Drivers
  ifdef CONFIG_PCI
  
@@ -8,4 +8,4 @@
 +# CONFIG_ATH5K_PCI=y
  CONFIG_ATH9K_PCI=y
  
- CONFIG_IWLAGN=m
+ CONFIG_IWLWIFI=m
index 6d1bc64..21b624e 100644 (file)
@@ -1,8 +1,8 @@
 --- a/include/linux/compat-3.0.h
 +++ b/include/linux/compat-3.0.h
-@@ -5,6 +5,8 @@
+@@ -7,6 +7,8 @@
  
- #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))
+ #include <linux/rcupdate.h>
  
 +#include <linux/mod_devicetable.h>
 +
diff --git a/package/mac80211/patches/022-atomic64_backport.patch b/package/mac80211/patches/022-atomic64_backport.patch
deleted file mode 100644 (file)
index 673b7c3..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
---- a/compat/Makefile
-+++ b/compat/Makefile
-@@ -38,3 +38,8 @@ compat-$(CONFIG_COMPAT_KERNEL_3_1) += \
-       cordic.o \
-       crc8.o
-+ifndef CONFIG_64BIT
-+ifndef CONFIG_GENERIC_ATOMIC64
-+  compat-y += compat_atomic.o
-+endif
-+endif
---- a/include/linux/compat-2.6.31.h
-+++ b/include/linux/compat-2.6.31.h
-@@ -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
-+
-+typedef struct {
-+      long long counter;
-+} atomic64_t;
-+
-+extern long long atomic64_read(const atomic64_t *v);
-+extern long long atomic64_add_return(long long a, atomic64_t *v);
-+
-+#define atomic64_inc_return(v)          atomic64_add_return(1LL, (v))
-+
-+#endif
-+
-+
- #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)) */
- #endif /* LINUX_26_31_COMPAT_H */
---- /dev/null
-+++ b/compat/compat_atomic.c
-@@ -0,0 +1,33 @@
-+#include <linux/spinlock.h>
-+#include <linux/module.h>
-+
-+#if !((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)) && (defined(CONFIG_UML) || defined(CONFIG_X86))) && !((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) && defined(CONFIG_ARM) && !defined(CONFIG_GENERIC_ATOMIC64))
-+
-+static DEFINE_SPINLOCK(lock);
-+
-+long long atomic64_read(const atomic64_t *v)
-+{
-+    unsigned long flags;
-+    long long val;
-+
-+    spin_lock_irqsave(&lock, flags);
-+    val = v->counter;
-+    spin_unlock_irqrestore(&lock, flags);
-+    return val;
-+}
-+EXPORT_SYMBOL(atomic64_read);
-+
-+long long atomic64_add_return(long long a, atomic64_t *v)
-+{
-+    unsigned long flags;
-+    long long val;
-+
-+    spin_lock_irqsave(&lock, flags);
-+    val = v->counter += a;
-+    spin_unlock_irqrestore(&lock, flags);
-+    return val;
-+}
-+EXPORT_SYMBOL(atomic64_add_return);
-+
-+#endif
-+
---- a/include/linux/compat-3.1.h
-+++ b/include/linux/compat-3.1.h
-@@ -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
-+ * atomic64_t implementation, and do not include the software emulation from
-+ * asm-generic/atomic64_t.
-+ * Detect and handle this here.
-+ */
-+#include <asm/atomic.h>
-+
-+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)) && !defined(ATOMIC64_INIT) && !defined(CONFIG_X86) && !((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) && defined(CONFIG_ARM) && !defined(CONFIG_GENERIC_ATOMIC64))
-+#include <asm-generic/atomic64.h>
-+#endif
-+
- #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)) */
- #endif /* LINUX_3_1_COMPAT_H */
index c51c672..af7c4fe 100644 (file)
@@ -17,7 +17,7 @@
  compat-$(CONFIG_COMPAT_KERNEL_2_6_18) += compat-2.6.18.o
 --- a/compat/compat_firmware_class.c
 +++ b/compat/compat_firmware_class.c
-@@ -729,19 +729,16 @@ request_firmware_nowait(
+@@ -741,19 +741,16 @@ request_firmware_nowait(
        return 0;
  }
  
diff --git a/package/mac80211/patches/051-compat_workqueue.patch b/package/mac80211/patches/051-compat_workqueue.patch
deleted file mode 100644 (file)
index d94507d..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
---- a/compat/compat-2.6.36.c
-+++ b/compat/compat-2.6.36.c
-@@ -93,6 +93,8 @@ void compat_usb_scuttle_anchored_urbs(st
- }
- EXPORT_SYMBOL_GPL(compat_usb_scuttle_anchored_urbs);
-+#endif /* CONFIG_COMPAT_USB_URB_THREAD_FIX */
-+
- struct workqueue_struct *system_nrt_wq __read_mostly;
- EXPORT_SYMBOL_GPL(system_nrt_wq);
-@@ -106,6 +108,3 @@ void compat_system_workqueue_destroy()
- {
-       destroy_workqueue(system_nrt_wq);
- }
--
--#endif /* CONFIG_COMPAT_USB_URB_THREAD_FIX */
--
diff --git a/package/mac80211/patches/060-fix_compat_security.patch b/package/mac80211/patches/060-fix_compat_security.patch
new file mode 100644 (file)
index 0000000..1942499
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/include/linux/compat-3.1.h
++++ b/include/linux/compat-3.1.h
+@@ -5,6 +5,8 @@
+ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0))
++#include <linux/security.h>
++
+ #define genl_dump_check_consistent(cb, user_hdr, family)
+ #define IFF_TX_SKB_SHARING    0x10000 /* The interface supports sharing
diff --git a/package/mac80211/patches/070-deactivate_mac80211_tracing.patch b/package/mac80211/patches/070-deactivate_mac80211_tracing.patch
new file mode 100644 (file)
index 0000000..feff5eb
--- /dev/null
@@ -0,0 +1,44 @@
+Do not activate the mac80211 tracing by default as it does not work with 
+kernel <= 2.6.32. Compat also includes include/trace/define_trace.h over
+include/trace/events/module.h which makes this not compiling any more.
+
+--- a/net/mac80211/Makefile
++++ b/net/mac80211/Makefile
+@@ -24,8 +24,7 @@ mac80211-y := \
+       util.o \
+       wme.o \
+       event.o \
+-      chan.o \
+-      driver-trace.o
++      chan.o
+ mac80211-$(CONFIG_MAC80211_LEDS) += led.o
+ mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
+@@ -42,6 +41,7 @@ mac80211-$(CONFIG_MAC80211_MESH) += \
+ mac80211-$(CONFIG_PM) += pm.o
++mac80211-$(CONFIG_MAC80211_DRIVER_API_TRACER) += driver-trace.o
+ CFLAGS_driver-trace.o := -I$(src)
+ # objects for PID algorithm
+--- a/net/mac80211/driver-trace.h
++++ b/net/mac80211/driver-trace.h
+@@ -5,6 +5,17 @@
+ #include <net/mac80211.h>
+ #include "ieee80211_i.h"
++#if !defined(CONFIG_MAC80211_DRIVER_API_TRACER) || defined(__CHECKER__)
++#undef TRACE_EVENT
++#define TRACE_EVENT(name, proto, ...) \
++static inline void trace_ ## name(proto) {}
++#undef DECLARE_EVENT_CLASS
++#define DECLARE_EVENT_CLASS(...)
++#undef DEFINE_EVENT
++#define DEFINE_EVENT(evt_class, name, proto, ...) \
++static inline void trace_ ## name(proto) {}
++#endif
++
+ #undef TRACE_SYSTEM
+ #define TRACE_SYSTEM mac80211
index 52979ad..fb5ae7d 100644 (file)
@@ -51,7 +51,7 @@
  #include <pcmcia/cs_types.h>
  #include <pcmcia/cistpl.h>
  #include <pcmcia/ds.h>
-@@ -68,9 +68,9 @@ static inline struct sk_buff *netdev_all
+@@ -74,9 +74,9 @@ static inline struct sk_buff *netdev_all
        return skb;
  }
  
index 7318cf9..67a5527 100644 (file)
@@ -33,7 +33,7 @@
  #endif
 --- a/config.mk
 +++ b/config.mk
-@@ -453,7 +453,7 @@ endif #CONFIG_COMPAT_KERNEL_2_6_29
+@@ -492,7 +492,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 53add82..44c1f3c 100644 (file)
@@ -1,5 +1,5 @@
---- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
-+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
+--- a/drivers/net/wireless/iwlegacy/3945-mac.c
++++ b/drivers/net/wireless/iwlegacy/3945-mac.c
 @@ -27,6 +27,7 @@
   *
   *****************************************************************************/
@@ -78,8 +78,8 @@
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/kernel.h>
---- a/drivers/net/wireless/iwlegacy/iwl4965-base.c
-+++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
+--- a/drivers/net/wireless/iwlegacy/4965-mac.c
++++ b/drivers/net/wireless/iwlegacy/4965-mac.c
 @@ -27,6 +27,7 @@
   *
   *****************************************************************************/
index b233311..9dfa90a 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -20,16 +20,16 @@ COMPAT_LATEST_VERSION = 1
+@@ -20,16 +20,16 @@ COMPAT_LATEST_VERSION = 3
  KERNEL_VERSION := $(shell $(MAKE) -C $(KLIB_BUILD) kernelversion | sed -n 's/^\([0-9]\)\..*/\1/p')
  
  ifneq ($(KERNEL_VERSION),2)
@@ -19,4 +19,4 @@
 +COMPAT_VERSIONS := $(shell I=$(COMPAT_LATEST_VERSION); while [ "$$I" -gt $(COMPAT_KERNEL_SUBLEVEL) ]; do echo $$I; I=$$(($$I - 1)); done)
  $(foreach ver,$(COMPAT_VERSIONS),$(eval CONFIG_COMPAT_KERNEL_3_$(ver)=y))
  
- ifdef CONFIG_COMPAT_KERNEL_2_6_24
+ RHEL_MAJOR := $(shell grep ^RHEL_MAJOR $(KLIB_BUILD)/Makefile | sed -n 's/.*= *\(.*\)/\1/p')
index 2a35913..817060d 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/mac80211/mesh_pathtbl.c
 +++ b/net/mac80211/mesh_pathtbl.c
-@@ -841,7 +841,6 @@ static void table_flush_by_iface(struct 
+@@ -826,7 +826,6 @@ static void table_flush_by_iface(struct 
        struct hlist_node *p;
        int i;
  
index c1f18af..72274ee 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath5k/initvals.c
 +++ b/drivers/net/wireless/ath/ath5k/initvals.c
-@@ -57,8 +57,14 @@ static const struct ath5k_ini ar5210_ini
+@@ -60,8 +60,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
-@@ -786,10 +786,18 @@ void ath5k_hw_dma_init(struct ath5k_hw *
+@@ -858,10 +858,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
         * guess we can tweak it and see how it goes ;-)
         */
        if (ah->ah_version != AR5K_AR5210) {
index e865053..1b7f41b 100644 (file)
@@ -1,3 +1,59 @@
+--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+@@ -203,7 +203,7 @@ static void ar9002_hw_iqcalibrate(struct
+                       i);
+               ath_dbg(common, ATH_DBG_CALIBRATE,
+-                      "Orignal: Chn %diq_corr_meas = 0x%08x\n",
++                      "Original: Chn %d iq_corr_meas = 0x%08x\n",
+                       i, ah->totalIqCorrMeas[i]);
+               iqCorrNeg = 0;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+@@ -226,7 +226,7 @@ static void ar9003_hw_iqcalibrate(struct
+                       i);
+               ath_dbg(common, ATH_DBG_CALIBRATE,
+-                      "Orignal: Chn %diq_corr_meas = 0x%08x\n",
++                      "Original: Chn %d iq_corr_meas = 0x%08x\n",
+                       i, ah->totalIqCorrMeas[i]);
+               iqCorrNeg = 0;
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+@@ -808,7 +808,8 @@ void ath9k_htc_ani_work(struct work_stru
+       }
+       /* Verify whether we must check ANI */
+-      if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
++      if (ah->config.enable_ani &&
++          (timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
+               aniflag = true;
+               common->ani.checkani_timer = timestamp;
+       }
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -504,7 +504,7 @@ static int ath9k_hw_post_init(struct ath
+               return ecode;
+       }
+-      if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) {
++      if (ah->config.enable_ani) {
+               ath9k_hw_ani_setup(ah);
+               ath9k_hw_ani_init(ah);
+       }
+@@ -610,6 +610,10 @@ static int __ath9k_hw_init(struct ath_hw
+       if (!AR_SREV_9300_20_OR_LATER(ah))
+               ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
++      /* disable ANI for 9340 */
++      if (AR_SREV_9340(ah))
++              ah->config.enable_ani = false;
++
+       ath9k_hw_init_mode_regs(ah);
+       if (!ah->is_pciexpress)
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
 @@ -118,7 +118,7 @@ void ath9k_ps_restore(struct ath_softc *
@@ -9,6 +65,15 @@
                mode = ATH9K_PM_FULL_SLEEP;
        else if (sc->ps_enabled &&
                 !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
+@@ -286,7 +286,7 @@ static bool ath_complete_reset(struct at
+                       ath_start_ani(common);
+       }
+-      if (ath9k_hw_ops(ah)->antdiv_comb_conf_get && sc->ant_rx != 3) {
++      if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) {
+               struct ath_hw_antcomb_conf div_ant_conf;
+               u8 lna_conf;
 @@ -332,7 +332,8 @@ static int ath_reset_internal(struct ath
                hchan = ah->curchan;
        }
                fastcc = false;
  
        if (!ath_prepare_reset(sc, retry_tx, flush))
-@@ -882,82 +883,6 @@ chip_reset:
+@@ -561,7 +562,6 @@ void ath_ani_calibrate(unsigned long dat
+       /* Long calibration runs independently of short calibration. */
+       if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
+               longcal = true;
+-              ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
+               common->ani.longcal_timer = timestamp;
+       }
+@@ -569,8 +569,6 @@ void ath_ani_calibrate(unsigned long dat
+       if (!common->ani.caldone) {
+               if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
+                       shortcal = true;
+-                      ath_dbg(common, ATH_DBG_ANI,
+-                              "shortcal @%lu\n", jiffies);
+                       common->ani.shortcal_timer = timestamp;
+                       common->ani.resetcal_timer = timestamp;
+               }
+@@ -584,8 +582,9 @@ void ath_ani_calibrate(unsigned long dat
+       }
+       /* Verify whether we must check ANI */
+-      if ((timestamp - common->ani.checkani_timer) >=
+-           ah->config.ani_poll_interval) {
++      if (sc->sc_ah->config.enable_ani
++          && (timestamp - common->ani.checkani_timer) >=
++          ah->config.ani_poll_interval) {
+               aniflag = true;
+               common->ani.checkani_timer = timestamp;
+       }
+@@ -605,6 +604,11 @@ void ath_ani_calibrate(unsigned long dat
+                                               ah->rxchainmask, longcal);
+       }
++      ath_dbg(common, ATH_DBG_ANI,
++              "Calibration @%lu finished: %s %s %s, caldone: %s\n", jiffies,
++              longcal ? "long" : "", shortcal ? "short" : "",
++              aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
++
+       ath9k_ps_restore(sc);
+ set_timer:
+@@ -886,82 +890,6 @@ chip_reset:
  #undef SCHED_INTR
  }
  
  static int ath_reset(struct ath_softc *sc, bool retry_tx)
  {
        int r;
-@@ -1093,6 +1018,9 @@ static int ath9k_start(struct ieee80211_
+@@ -1097,6 +1025,9 @@ static int ath9k_start(struct ieee80211_
         * and then setup of the interrupt mask.
         */
        spin_lock_bh(&sc->sc_pcu_lock);
        r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
        if (r) {
                ath_err(common,
-@@ -1131,6 +1059,18 @@ static int ath9k_start(struct ieee80211_
+@@ -1138,6 +1069,18 @@ static int ath9k_start(struct ieee80211_
                goto mutex_unlock;
        }
  
        spin_unlock_bh(&sc->sc_pcu_lock);
  
        if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
-@@ -1176,6 +1116,13 @@ static void ath9k_tx(struct ieee80211_hw
+@@ -1183,6 +1126,13 @@ static void ath9k_tx(struct ieee80211_hw
                }
        }
  
        if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) {
                /*
                 * We are using PS-Poll and mac80211 can request TX while in
-@@ -1222,6 +1169,7 @@ static void ath9k_stop(struct ieee80211_
+@@ -1229,6 +1179,7 @@ static void ath9k_stop(struct ieee80211_
        struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
  
        mutex_lock(&sc->mutex);
  
-@@ -1252,35 +1200,45 @@ static void ath9k_stop(struct ieee80211_
+@@ -1259,35 +1210,45 @@ static void ath9k_stop(struct ieee80211_
         * before setting the invalid flag. */
        ath9k_hw_disable_interrupts(ah);
  
  
        mutex_unlock(&sc->mutex);
  
-@@ -1620,8 +1578,8 @@ static int ath9k_config(struct ieee80211
+@@ -1627,8 +1588,8 @@ static int ath9k_config(struct ieee80211
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_conf *conf = &hw->conf;
        mutex_lock(&sc->mutex);
  
        /*
-@@ -1632,13 +1590,8 @@ static int ath9k_config(struct ieee80211
+@@ -1639,13 +1600,8 @@ static int ath9k_config(struct ieee80211
         */
        if (changed & IEEE80211_CONF_CHANGE_IDLE) {
                sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
        }
  
        /*
-@@ -1745,18 +1698,12 @@ static int ath9k_config(struct ieee80211
+@@ -1752,18 +1708,12 @@ static int ath9k_config(struct ieee80211
                ath_dbg(common, ATH_DBG_CONFIG,
                        "Set power: %d\n", conf->power_level);
                sc->config.txpowlimit = 2 * conf->power_level;
  
        return 0;
  }
-@@ -2324,9 +2271,6 @@ static void ath9k_flush(struct ieee80211
+@@ -2331,9 +2281,6 @@ static void ath9k_flush(struct ieee80211
                return;
        }
  
        for (j = 0; j < timeout; j++) {
                bool npend = false;
  
-@@ -2344,21 +2288,22 @@ static void ath9k_flush(struct ieee80211
+@@ -2351,21 +2298,22 @@ static void ath9k_flush(struct ieee80211
                }
  
                if (!npend)
  
 --- a/drivers/net/wireless/ath/ath9k/xmit.c
 +++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -179,6 +179,11 @@ static void ath_tx_flush_tid(struct ath_
-               spin_lock_bh(&txq->axq_lock);
-       }
-+      if (tid->baw_head == tid->baw_tail) {
-+              tid->state &= ~AGGR_ADDBA_COMPLETE;
-+              tid->state &= ~AGGR_CLEANUP;
-+      }
-+
-       spin_unlock_bh(&txq->axq_lock);
- }
-@@ -556,15 +561,9 @@ static void ath_tx_complete_aggr(struct 
-               spin_unlock_bh(&txq->axq_lock);
-       }
--      if (tid->state & AGGR_CLEANUP) {
-+      if (tid->state & AGGR_CLEANUP)
-               ath_tx_flush_tid(sc, tid);
--              if (tid->baw_head == tid->baw_tail) {
--                      tid->state &= ~AGGR_ADDBA_COMPLETE;
--                      tid->state &= ~AGGR_CLEANUP;
--              }
--      }
--
-       rcu_read_unlock();
-       if (needreset) {
-@@ -1955,7 +1954,7 @@ static void ath_tx_complete(struct ath_s
+@@ -1954,7 +1954,7 @@ static void ath_tx_complete(struct ath_s
                skb_pull(skb, padsize);
        }
  
                sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK;
                ath_dbg(common, ATH_DBG_PS,
                        "Going back to sleep after having received TX status (0x%lx)\n",
+--- a/include/linux/nl80211.h
++++ b/include/linux/nl80211.h
+@@ -2785,9 +2785,11 @@ enum nl80211_ap_sme_features {
+  * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back
+  *    TX status to the socket error queue when requested with the
+  *    socket option.
++ * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.
+  */
+ enum nl80211_feature_flags {
+       NL80211_FEATURE_SK_TX_STATUS    = 1 << 0,
++      NL80211_FEATURE_HT_IBSS         = 1 << 1,
+ };
+ /**
 --- a/include/net/cfg80211.h
 +++ b/include/net/cfg80211.h
-@@ -1130,6 +1130,7 @@ struct cfg80211_ibss_params {
+@@ -1149,6 +1149,7 @@ struct cfg80211_ibss_params {
        u8 *ssid;
        u8 *bssid;
        struct ieee80211_channel *channel;
        u8 *ie;
        u8 ssid_len, ie_len;
        u16 beacon_interval;
-@@ -3292,6 +3293,16 @@ void cfg80211_report_obss_beacon(struct 
+@@ -3270,6 +3271,16 @@ void cfg80211_report_obss_beacon(struct 
                                 const u8 *frame, size_t len,
                                 int freq, gfp_t gfp);
  
-+/**
-+ * cfg80211_can_use_ext_chan - test if ht40 on extension channel can be used
++/*
++ * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
 + * @wiphy: the wiphy
 + * @chan: main channel
 + * @channel_type: HT mode
 + */
-+bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
-+                                struct ieee80211_channel *chan,
-+                                enum nl80211_channel_type channel_type);
++int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
++                               struct ieee80211_channel *chan,
++                               enum nl80211_channel_type channel_type);
 +
  /* Logging, debugging and troubleshooting/diagnostic helpers. */
  
  /* wiphy_printk helpers, similar to dev_printk */
 --- a/net/mac80211/agg-rx.c
 +++ b/net/mac80211/agg-rx.c
-@@ -182,6 +182,10 @@ static void ieee80211_send_addba_resp(st
+@@ -185,6 +185,10 @@ static void ieee80211_send_addba_resp(st
                memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
                memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-+      else if (sdata->vif.type == NL80211_IFTYPE_WDS)
-+              memcpy(mgmt->bssid, da, ETH_ALEN);
 +      else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
 +              memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
++      else if (sdata->vif.type == NL80211_IFTYPE_WDS)
++              memcpy(mgmt->bssid, da, 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
-@@ -79,10 +79,13 @@ static void ieee80211_send_addba_request
+@@ -55,6 +55,8 @@
+  * @ampdu_action function will be called with the action
+  * %IEEE80211_AMPDU_TX_STOP. In this case, the call must not fail,
+  * and the driver must later call ieee80211_stop_tx_ba_cb_irqsafe().
++ * Note that the sta can get destroyed before the BA tear down is
++ * complete.
+  */
+ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
+@@ -79,10 +81,13 @@ static void ieee80211_send_addba_request
        memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        if (sdata->vif.type == NL80211_IFTYPE_AP ||
            sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
  
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                          IEEE80211_STYPE_ACTION);
-@@ -394,7 +397,9 @@ int ieee80211_start_tx_ba_session(struct
+@@ -319,6 +324,38 @@ ieee80211_wake_queue_agg(struct ieee8021
+       __release(agg_queue);
+ }
++/*
++ * splice packets from the STA's pending to the local pending,
++ * requires a call to ieee80211_agg_splice_finish later
++ */
++static void __acquires(agg_queue)
++ieee80211_agg_splice_packets(struct ieee80211_local *local,
++                           struct tid_ampdu_tx *tid_tx, u16 tid)
++{
++      int queue = ieee80211_ac_from_tid(tid);
++      unsigned long flags;
++
++      ieee80211_stop_queue_agg(local, tid);
++
++      if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
++                        " from the pending queue\n", tid))
++              return;
++
++      if (!skb_queue_empty(&tid_tx->pending)) {
++              spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
++              /* copy over remaining packets */
++              skb_queue_splice_tail_init(&tid_tx->pending,
++                                         &local->pending[queue]);
++              spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
++      }
++}
++
++static void __releases(agg_queue)
++ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
++{
++      ieee80211_wake_queue_agg(local, tid);
++}
++
+ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
+ {
+       struct tid_ampdu_tx *tid_tx;
+@@ -330,19 +367,17 @@ void ieee80211_tx_ba_session_handle_star
+       tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
+       /*
+-       * While we're asking the driver about the aggregation,
+-       * stop the AC queue so that we don't have to worry
+-       * about frames that came in while we were doing that,
+-       * which would require us to put them to the AC pending
+-       * afterwards which just makes the code more complex.
++       * Start queuing up packets for this aggregation session.
++       * We're going to release them once the driver is OK with
++       * that.
+        */
+-      ieee80211_stop_queue_agg(local, tid);
+-
+       clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
+       /*
+-       * make sure no packets are being processed to get
+-       * valid starting sequence number
++       * Make sure no packets are being processed. This ensures that
++       * we have a valid starting sequence number and that in-flight
++       * packets have been flushed out and no packets for this TID
++       * will go into the driver during the ampdu_action call.
+        */
+       synchronize_net();
+@@ -356,10 +391,11 @@ void ieee80211_tx_ba_session_handle_star
+                                       " tid %d\n", tid);
+ #endif
+               spin_lock_bh(&sta->lock);
++              ieee80211_agg_splice_packets(local, tid_tx, tid);
+               ieee80211_assign_tid_tx(sta, tid, NULL);
++              ieee80211_agg_splice_finish(local, tid);
+               spin_unlock_bh(&sta->lock);
+-              ieee80211_wake_queue_agg(local, tid);
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,40))
+               kfree_rcu(tid_tx, rcu_head);
+ #else
+@@ -368,9 +404,6 @@ void ieee80211_tx_ba_session_handle_star
+               return;
+       }
+-      /* we can take packets again now */
+-      ieee80211_wake_queue_agg(local, tid);
+-
+       /* activate the timer for the recipient's addBA response */
+       mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
+ #ifdef CONFIG_MAC80211_HT_DEBUG
+@@ -437,7 +470,9 @@ int ieee80211_start_tx_ba_session(struct
        if (sdata->vif.type != NL80211_IFTYPE_STATION &&
            sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
            sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 -          sdata->vif.type != NL80211_IFTYPE_AP)
 +          sdata->vif.type != NL80211_IFTYPE_AP &&
-+          sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-+          sdata->vif.type != NL80211_IFTYPE_WDS)
++          sdata->vif.type != NL80211_IFTYPE_WDS &&
++          sdata->vif.type != NL80211_IFTYPE_ADHOC)
                return -EINVAL;
  
        if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
+@@ -448,6 +483,27 @@ int ieee80211_start_tx_ba_session(struct
+               return -EINVAL;
+       }
++      /*
++       * 802.11n-2009 11.5.1.1: If the initiating STA is an HT STA, is a
++       * member of an IBSS, and has no other existing Block Ack agreement
++       * with the recipient STA, then the initiating STA shall transmit a
++       * Probe Request frame to the recipient STA and shall not transmit an
++       * ADDBA Request frame unless it receives a Probe Response frame
++       * from the recipient within dot11ADDBAFailureTimeout.
++       *
++       * The probe request mechanism for ADDBA is currently not implemented,
++       * but we only build up Block Ack session with HT STAs. This information
++       * is set when we receive a bss info from a probe response or a beacon.
++       */
++      if (sta->sdata->vif.type == NL80211_IFTYPE_ADHOC &&
++          !sta->sta.ht_cap.ht_supported) {
++#ifdef CONFIG_MAC80211_HT_DEBUG
++              printk(KERN_DEBUG "BA request denied - IBSS STA %pM"
++                     "does not advertise HT support\n", pubsta->addr);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++              return -EINVAL;
++      }
++
+       spin_lock_bh(&sta->lock);
+       /* we have tried too many times, receiver does not want A-MPDU */
+@@ -508,38 +564,6 @@ int ieee80211_start_tx_ba_session(struct
+ }
+ EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
+-/*
+- * splice packets from the STA's pending to the local pending,
+- * requires a call to ieee80211_agg_splice_finish later
+- */
+-static void __acquires(agg_queue)
+-ieee80211_agg_splice_packets(struct ieee80211_local *local,
+-                           struct tid_ampdu_tx *tid_tx, u16 tid)
+-{
+-      int queue = ieee80211_ac_from_tid(tid);
+-      unsigned long flags;
+-
+-      ieee80211_stop_queue_agg(local, tid);
+-
+-      if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
+-                        " from the pending queue\n", tid))
+-              return;
+-
+-      if (!skb_queue_empty(&tid_tx->pending)) {
+-              spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+-              /* copy over remaining packets */
+-              skb_queue_splice_tail_init(&tid_tx->pending,
+-                                         &local->pending[queue]);
+-              spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+-      }
+-}
+-
+-static void __releases(agg_queue)
+-ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
+-{
+-      ieee80211_wake_queue_agg(local, tid);
+-}
+-
+ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
+                                        struct sta_info *sta, u16 tid)
+ {
 --- a/net/mac80211/debugfs_sta.c
 +++ b/net/mac80211/debugfs_sta.c
 @@ -63,11 +63,11 @@ static ssize_t sta_flags_read(struct fil
        test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
  
        int res = scnprintf(buf, sizeof(buf),
--                          "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
-+                          "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+-                          "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
++                          "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                            TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
                            TEST(PS_DRIVER), TEST(AUTHORIZED),
-                           TEST(SHORT_PREAMBLE), TEST(ASSOC_AP),
+                           TEST(SHORT_PREAMBLE),
 -                          TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
 +                          TEST(WME), TEST(CLEAR_PS_FILT),
                            TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
                            TEST(TDLS_PEER_AUTH));
 --- a/net/mac80211/ht.c
 +++ b/net/mac80211/ht.c
-@@ -201,6 +201,8 @@ void ieee80211_send_delba(struct ieee802
+@@ -47,7 +47,9 @@ void ieee80211_apply_htcap_overrides(str
+       int i;
+       if (sdata->vif.type != NL80211_IFTYPE_STATION) {
+-              WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
++              /* AP interfaces call this code when adding new stations,
++               * so just silently ignore non station interfaces.
++               */
+               return;
+       }
+@@ -282,6 +284,8 @@ void ieee80211_send_delba(struct ieee802
                memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
                memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
        ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
  
        sband = local->hw.wiphy->bands[chan->band];
-@@ -172,6 +181,18 @@ static void __ieee80211_sta_join_ibss(st
+@@ -172,6 +181,19 @@ static void __ieee80211_sta_join_ibss(st
                memcpy(skb_put(skb, ifibss->ie_len),
                       ifibss->ie, ifibss->ie_len);
  
 +              pos = skb_put(skb, 4 +
 +                                 sizeof(struct ieee80211_ht_cap) +
 +                                 sizeof(struct ieee80211_ht_info));
-+              pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
++              pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
++                                              sband->ht_cap.cap);
 +              pos = ieee80211_ie_build_ht_info(pos,
 +                                               &sband->ht_cap,
 +                                               chan,
        if (local->hw.queues >= 4) {
                pos = skb_put(skb, 9);
                *pos++ = WLAN_EID_VENDOR_SPECIFIC;
-@@ -195,6 +216,7 @@ static void __ieee80211_sta_join_ibss(st
+@@ -195,6 +217,7 @@ static void __ieee80211_sta_join_ibss(st
        bss_change |= BSS_CHANGED_BEACON;
        bss_change |= BSS_CHANGED_BEACON_ENABLED;
        bss_change |= BSS_CHANGED_BASIC_RATES;
        bss_change |= BSS_CHANGED_IBSS;
        sdata->vif.bss_conf.ibss_joined = true;
        ieee80211_bss_info_change_notify(sdata, bss_change);
-@@ -268,6 +290,7 @@ static void ieee80211_rx_bss_info(struct
+@@ -268,6 +291,8 @@ static void ieee80211_rx_bss_info(struct
        u64 beacon_timestamp, rx_timestamp;
        u32 supp_rates = 0;
        enum ieee80211_band band = rx_status->band;
 +      struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
++      bool rates_updated = false;
  
        if (elems->ds_params && elems->ds_params_len == 1)
                freq = ieee80211_channel_to_frequency(elems->ds_params[0],
-@@ -277,7 +300,10 @@ static void ieee80211_rx_bss_info(struct
-       channel = ieee80211_get_channel(local->hw.wiphy, freq);
--      if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
-+      if (!channel ||
-+          channel->flags & (IEEE80211_CHAN_DISABLED ||
-+                            IEEE80211_CHAN_NO_IBSS ||
-+                            IEEE80211_CHAN_RADAR))
-               return;
-       if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
-@@ -315,8 +341,41 @@ static void ieee80211_rx_bss_info(struct
-                                               GFP_ATOMIC);
-               }
--              if (sta && elems->wmm_info)
--                      set_sta_flag(sta, WLAN_STA_WME);
-+              if (sta) {
-+                      if (elems->wmm_info)
-+                              set_sta_flag(sta, WLAN_STA_WME);
-+
+@@ -307,7 +332,7 @@ static void ieee80211_rx_bss_info(struct
+                                               prev_rates,
+                                               sta->sta.supp_rates[band]);
+ #endif
+-                                      rate_control_rate_init(sta);
++                                      rates_updated = true;
+                               }
+                       } else
+                               sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
+@@ -318,6 +343,39 @@ static void ieee80211_rx_bss_info(struct
+               if (sta && elems->wmm_info)
+                       set_sta_flag(sta, WLAN_STA_WME);
++              if (sta && elems->ht_info_elem && elems->ht_cap_elem &&
++                  sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) {
 +                      /* we both use HT */
-+                      if (elems->ht_info_elem && elems->ht_cap_elem &&
-+                          sdata->u.ibss.channel_type) {
-+                              enum nl80211_channel_type channel_type =
-+                                      ieee80211_ht_info_to_channel_type(
-+                                                         elems->ht_info_elem);
-+                              struct ieee80211_sta_ht_cap sta_ht_cap_new;
-+
-+                              /*
-+                               * fall back to HT20 if we don't use or use
-+                               * the other extension channel
-+                               */
-+                              if (channel_type > NL80211_CHAN_HT20 &&
-+                                  channel_type != sdata->u.ibss.channel_type)
-+                                      channel_type = NL80211_CHAN_HT20;
-+
-+                              ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
-+                                              elems->ht_cap_elem,
-+                                              &sta_ht_cap_new);
-+                              if (memcmp(&sta->sta.ht_cap, &sta_ht_cap_new,
-+                                         sizeof(sta_ht_cap_new))) {
-+                                      memcpy(&sta->sta.ht_cap,
-+                                             &sta_ht_cap_new,
-+                                             sizeof(sta_ht_cap_new));
-+                                      rate_control_rate_update(local, sband,
-+                                                      sta,
-+                                                      IEEE80211_RC_HT_CHANGED,
-+                                                      channel_type);
-+                              }
++                      struct ieee80211_sta_ht_cap sta_ht_cap_new;
++                      enum nl80211_channel_type channel_type =
++                              ieee80211_ht_info_to_channel_type(
++                                                      elems->ht_info_elem);
++
++                      ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
++                                                        elems->ht_cap_elem,
++                                                        &sta_ht_cap_new);
++
++                      /*
++                       * fall back to HT20 if we don't use or use
++                       * the other extension channel
++                       */
++                      if ((channel_type == NL80211_CHAN_HT40MINUS ||
++                           channel_type == NL80211_CHAN_HT40PLUS) &&
++                          channel_type != sdata->u.ibss.channel_type)
++                              sta_ht_cap_new.cap &=
++                                      ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
++
++                      if (memcmp(&sta->sta.ht_cap, &sta_ht_cap_new,
++                                 sizeof(sta_ht_cap_new))) {
++                              memcpy(&sta->sta.ht_cap, &sta_ht_cap_new,
++                                     sizeof(sta_ht_cap_new));
++                              rates_updated = true;
 +                      }
 +              }
++
++              if (sta && rates_updated)
++                      rate_control_rate_init(sta);
++
                rcu_read_unlock();
        }
-@@ -898,10 +957,15 @@ int ieee80211_ibss_join(struct ieee80211
+@@ -896,12 +954,18 @@ int ieee80211_ibss_join(struct ieee80211
+                       struct cfg80211_ibss_params *params)
+ {
        struct sk_buff *skb;
++      u32 changed = 0;
  
        skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
 -                          36 /* bitrates */ +
        }
  
        if (params->ie) {
+@@ -951,6 +1017,23 @@ int ieee80211_ibss_join(struct ieee80211
+       ieee80211_recalc_idle(sdata->local);
+       mutex_unlock(&sdata->local->mtx);
++      /*
++       * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is
++       * reserved, but an HT STA shall protect HT transmissions as though
++       * the HT Protection field were set to non-HT mixed mode.
++       *
++       * In an IBSS, the RIFS Mode field of the HT Operation element is
++       * also reserved, but an HT STA shall operate as though this field
++       * were set to 1.
++       */
++
++      sdata->vif.bss_conf.ht_operation_mode |=
++                IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED
++              | IEEE80211_HT_PARAM_RIFS_MODE;
++
++      changed |= BSS_CHANGED_HT;
++      ieee80211_bss_info_change_notify(sdata, changed);
++
+       ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+       return 0;
 --- a/net/mac80211/ieee80211_i.h
 +++ b/net/mac80211/ieee80211_i.h
-@@ -470,6 +470,7 @@ struct ieee80211_if_ibss {
+@@ -474,6 +474,7 @@ struct ieee80211_if_ibss {
        u8 ssid_len, ie_len;
        u8 *ie;
        struct ieee80211_channel *channel;
   err_stop:
        if (!local->open_count)
                drv_stop(local);
-@@ -732,6 +709,70 @@ static void ieee80211_if_setup(struct ne
+@@ -719,6 +696,70 @@ static void ieee80211_if_setup(struct ne
        dev->destructor = free_netdev;
  }
  
 +      sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
 +
 +      if (elems.ht_cap_elem)
-+              ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
++              ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
 +                              elems.ht_cap_elem, &sta->sta.ht_cap);
 +
 +      if (elems.wmm_param)
  static void ieee80211_iface_work(struct work_struct *work)
  {
        struct ieee80211_sub_if_data *sdata =
-@@ -836,6 +877,9 @@ static void ieee80211_iface_work(struct 
+@@ -823,6 +864,9 @@ static void ieee80211_iface_work(struct 
                                break;
                        ieee80211_mesh_rx_queued_mgmt(sdata, skb);
                        break;
                default:
                        WARN(1, "frame for unexpected interface type");
                        break;
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -1359,9 +1359,6 @@ static void __ieee80211_connection_loss(
-       ieee80211_set_disassoc(sdata, true, true);
-       mutex_unlock(&ifmgd->mtx);
--      mutex_lock(&local->mtx);
--      ieee80211_recalc_idle(local);
--      mutex_unlock(&local->mtx);
-       /*
-        * must be outside lock due to cfg80211,
-        * but that's not a problem.
-@@ -1370,6 +1367,10 @@ static void __ieee80211_connection_loss(
-                                      IEEE80211_STYPE_DEAUTH,
-                                      WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
-                                      NULL, true);
-+
-+      mutex_lock(&local->mtx);
-+      ieee80211_recalc_idle(local);
-+      mutex_unlock(&local->mtx);
- }
- void ieee80211_beacon_connection_loss_work(struct work_struct *work)
-@@ -2136,9 +2137,6 @@ static void ieee80211_sta_connection_los
-       ieee80211_set_disassoc(sdata, true, true);
-       mutex_unlock(&ifmgd->mtx);
--      mutex_lock(&local->mtx);
--      ieee80211_recalc_idle(local);
--      mutex_unlock(&local->mtx);
-       /*
-        * must be outside lock due to cfg80211,
-        * but that's not a problem.
-@@ -2146,6 +2144,11 @@ static void ieee80211_sta_connection_los
-       ieee80211_send_deauth_disassoc(sdata, bssid,
-                       IEEE80211_STYPE_DEAUTH, reason,
-                       NULL, true);
-+
-+      mutex_lock(&local->mtx);
-+      ieee80211_recalc_idle(local);
-+      mutex_unlock(&local->mtx);
-+
-       mutex_lock(&ifmgd->mtx);
- }
---- a/net/mac80211/offchannel.c
-+++ b/net/mac80211/offchannel.c
-@@ -212,8 +212,6 @@ static void ieee80211_hw_roc_start(struc
-               return;
-       }
--      ieee80211_recalc_idle(local);
--
-       if (local->hw_roc_skb) {
-               sdata = IEEE80211_DEV_TO_SUB_IF(local->hw_roc_dev);
-               ieee80211_tx_skb(sdata, local->hw_roc_skb);
-@@ -227,6 +225,8 @@ static void ieee80211_hw_roc_start(struc
-                                         GFP_KERNEL);
-       }
-+      ieee80211_recalc_idle(local);
-+
-       mutex_unlock(&local->mtx);
- }
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -574,7 +574,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(
+                       WIPHY_FLAG_OFFCHAN_TX |
+                       WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+-      wiphy->features = NL80211_FEATURE_SK_TX_STATUS;
++      wiphy->features = NL80211_FEATURE_SK_TX_STATUS |
++                        NL80211_FEATURE_HT_IBSS;
+       if (!ops->set_key)
+               wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
 --- a/net/mac80211/rx.c
 +++ b/net/mac80211/rx.c
-@@ -2250,7 +2250,9 @@ ieee80211_rx_h_action(struct ieee80211_r
+@@ -2237,7 +2237,9 @@ ieee80211_rx_h_action(struct ieee80211_r
                if (sdata->vif.type != NL80211_IFTYPE_STATION &&
                    sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
                    sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 -                  sdata->vif.type != NL80211_IFTYPE_AP)
 +                  sdata->vif.type != NL80211_IFTYPE_AP &&
-+                  sdata->vif.type != NL80211_IFTYPE_ADHOC &&
-+                  sdata->vif.type != NL80211_IFTYPE_WDS)
++                  sdata->vif.type != NL80211_IFTYPE_WDS &&
++                  sdata->vif.type != NL80211_IFTYPE_ADHOC)
                        break;
  
                /* verify action_code is present */
-@@ -2465,13 +2467,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
+@@ -2452,13 +2454,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):
-@@ -2818,10 +2821,16 @@ static int prepare_for_handlers(struct i
+@@ -2796,19 +2799,32 @@ static int prepare_for_handlers(struct i
+                               return 0;
+               } else if (!ieee80211_bssid_match(bssid,
+                                       sdata->vif.addr)) {
++                      /*
++                       * Accept public action frames even when the
++                       * BSSID doesn't match, this is used for P2P
++                       * and location updates. Note that mac80211
++                       * itself never looks at these frames.
++                       */
+                       if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
+-                          !ieee80211_is_beacon(hdr->frame_control) &&
+-                          !(ieee80211_is_action(hdr->frame_control) &&
+-                            sdata->vif.p2p))
++                          ieee80211_is_public_action(hdr, skb->len))
++                              return 1;
++                      if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
++                          !ieee80211_is_beacon(hdr->frame_control))
+                               return 0;
+                       status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
                }
                break;
        case NL80211_IFTYPE_WDS:
                /* should never get here */
 --- a/net/mac80211/sta_info.h
 +++ b/net/mac80211/sta_info.h
-@@ -32,7 +32,6 @@
+@@ -31,7 +31,6 @@
+  * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
   *    frames.
-  * @WLAN_STA_ASSOC_AP: We're associated to that station, it is an AP.
   * @WLAN_STA_WME: Station is a QoS-STA.
 - * @WLAN_STA_WDS: Station is one of our WDS peers.
   * @WLAN_STA_CLEAR_PS_FILT: Clear PS filter in hardware (using the
   *    IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next
   *    frame to this station is transmitted.
-@@ -62,7 +61,6 @@ enum ieee80211_sta_info_flags {
+@@ -60,7 +59,6 @@ enum ieee80211_sta_info_flags {
+       WLAN_STA_AUTHORIZED,
        WLAN_STA_SHORT_PREAMBLE,
-       WLAN_STA_ASSOC_AP,
        WLAN_STA_WME,
 -      WLAN_STA_WDS,
        WLAN_STA_CLEAR_PS_FILT,
        WLAN_STA_MFP,
        WLAN_STA_BLOCK_BA,
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -1612,6 +1612,11 @@ u8 *ieee80211_ie_build_ht_info(u8 *pos,
+       }
+       if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+               ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
++
++      /*
++       * Note: According to 802.11n-2009 9.13.3.1, HT Protection field and
++       * RIFS Mode are reserved in IBSS mode, therefore keep them at 0
++       */
+       ht_info->operation_mode = 0x0000;
+       ht_info->stbc_param = 0x0000;
 --- a/net/wireless/chan.c
 +++ b/net/wireless/chan.c
-@@ -44,9 +44,9 @@ rdev_freq_to_chan(struct cfg80211_regist
+@@ -6,6 +6,7 @@
+  * Copyright 2009     Johannes Berg <johannes@sipsolutions.net>
+  */
++#include <linux/export.h>
+ #include <net/cfg80211.h>
+ #include "core.h"
+@@ -44,9 +45,9 @@ rdev_freq_to_chan(struct cfg80211_regist
        return chan;
  }
  
 -static bool can_beacon_sec_chan(struct wiphy *wiphy,
 -                              struct ieee80211_channel *chan,
 -                              enum nl80211_channel_type channel_type)
-+bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
++int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
 +                                struct ieee80211_channel *chan,
 +                                enum nl80211_channel_type channel_type)
  {
        struct ieee80211_channel *sec_chan;
        int diff;
-@@ -75,6 +75,7 @@ static bool can_beacon_sec_chan(struct w
+@@ -75,6 +76,7 @@ static bool can_beacon_sec_chan(struct w
  
        return true;
  }
  
  int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
                      struct wireless_dev *wdev, int freq,
-@@ -109,8 +110,8 @@ int cfg80211_set_freq(struct cfg80211_re
+@@ -109,8 +111,8 @@ int cfg80211_set_freq(struct cfg80211_re
                switch (channel_type) {
                case NL80211_CHAN_HT40PLUS:
                case NL80211_CHAN_HT40MINUS:
                                       "allowed to initiate communication\n");
 --- a/net/wireless/nl80211.c
 +++ b/net/wireless/nl80211.c
-@@ -4604,13 +4604,34 @@ static int nl80211_join_ibss(struct sk_b
+@@ -4684,13 +4684,41 @@ static int nl80211_join_ibss(struct sk_b
                ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        }
  
 +
 +              channel_type = nla_get_u32(
 +                              info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
-+              if (channel_type > NL80211_CHAN_HT40PLUS)
++              if (channel_type != NL80211_CHAN_NO_HT &&
++                  channel_type != NL80211_CHAN_HT20 &&
++                  channel_type != NL80211_CHAN_HT40MINUS &&
++                  channel_type != NL80211_CHAN_HT40PLUS)
++                      return -EINVAL;
++
++              if (channel_type != NL80211_CHAN_NO_HT &&
++                  !(wiphy->features & NL80211_FEATURE_HT_IBSS))
 +                      return -EINVAL;
++
 +              ibss.channel_type = channel_type;
 +      } else {
 +              ibss.channel_type = NL80211_CHAN_NO_HT;
 +              nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
 +              ibss.channel_type);
        if (!ibss.channel ||
-+          ibss.channel->flags & IEEE80211_CHAN_RADAR ||
            ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
            ibss.channel->flags & IEEE80211_CHAN_DISABLED)
                return -EINVAL;
        ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
        ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
  
+--- a/include/linux/ieee80211.h
++++ b/include/linux/ieee80211.h
+@@ -1695,6 +1695,23 @@ static inline bool ieee80211_is_robust_m
+ }
+ /**
++ * ieee80211_is_public_action - check if frame is a public action frame
++ * @hdr: the frame
++ * @len: length of the frame
++ */
++static inline bool ieee80211_is_public_action(struct ieee80211_hdr *hdr,
++                                            size_t len)
++{
++      struct ieee80211_mgmt *mgmt = (void *)hdr;
++
++      if (len < 25)
++              return false;
++      if (!ieee80211_is_action(hdr->frame_control))
++              return false;
++      return mgmt->u.action.category == WLAN_CATEGORY_PUBLIC;
++}
++
++/**
+  * ieee80211_fhss_chan_to_freq - get channel frequency
+  * @channel: the FHSS channel
+  *
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -1332,8 +1332,11 @@ static int invoke_tx_handlers(struct iee
+       if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
+               CALL_TXH(ieee80211_tx_h_rate_ctrl);
+-      if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION))
++      if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
++              __skb_queue_tail(&tx->skbs, tx->skb);
++              tx->skb = NULL;
+               goto txh_done;
++      }
+       CALL_TXH(ieee80211_tx_h_michael_mic_add);
+       CALL_TXH(ieee80211_tx_h_sequence);
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -851,6 +851,7 @@ static int __must_check __sta_info_destr
+       struct ieee80211_sub_if_data *sdata;
+       unsigned long flags;
+       int ret, i, ac;
++      struct tid_ampdu_tx *tid_tx;
+       might_sleep();
+@@ -949,6 +950,30 @@ static int __must_check __sta_info_destr
+       }
+ #endif
++      /* There could be some memory leaks because of ampdu tx pending queue
++       * not being freed before destroying the station info.
++       *
++       * Make sure that such queues are purged before freeing the station
++       * info.
++       * TODO: We have to somehow postpone the full destruction
++       * until the aggregation stop completes. Refer
++       * http://thread.gmane.org/gmane.linux.kernel.wireless.general/81936
++       */
++      for (i = 0; i < STA_TID_NUM; i++) {
++              if (!sta->ampdu_mlme.tid_tx[i])
++                      continue;
++              tid_tx = sta->ampdu_mlme.tid_tx[i];
++              if (skb_queue_len(&tid_tx->pending)) {
++#ifdef CONFIG_MAC80211_HT_DEBUG
++                      wiphy_debug(local->hw.wiphy, "TX A-MPDU  purging %d "
++                              "packets for tid=%d\n",
++                              skb_queue_len(&tid_tx->pending), i);
++#endif /* CONFIG_MAC80211_HT_DEBUG */
++                      __skb_queue_purge(&tid_tx->pending);
++              }
++              kfree_rcu(tid_tx, rcu_head);
++      }
++
+       __sta_info_free(local, sta);
+       return 0;
index 1933683..8ed03c6 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/wireless/reg.c
 +++ b/net/wireless/reg.c
-@@ -1656,6 +1656,8 @@ void regulatory_hint_11d(struct wiphy *w
+@@ -1672,6 +1672,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))
-@@ -1862,6 +1864,8 @@ static void restore_regulatory_settings(
+@@ -1878,6 +1880,8 @@ static void restore_regulatory_settings(
  
  void regulatory_hint_disconnect(void)
  {
index 0dbb950..09522cd 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1448,15 +1448,6 @@ static int ath9k_add_interface(struct ie
+@@ -1458,15 +1458,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);
  
-@@ -1482,15 +1473,6 @@ static int ath9k_change_interface(struct
+@@ -1492,15 +1483,6 @@ static int ath9k_change_interface(struct
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
  
index a964e70..29a7956 100644 (file)
@@ -18,7 +18,7 @@
                goto end;
 --- a/drivers/net/wireless/ath/ath5k/base.c
 +++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1860,7 +1860,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+@@ -1867,7 +1867,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
                ah->bmisscount = 0;
        }
  
@@ -27,7 +27,7 @@
                        ah->opmode == NL80211_IFTYPE_MESH_POINT) {
                u64 tsf = ath5k_hw_get_tsf64(ah);
                u32 tsftu = TSF_TO_TU(tsf);
-@@ -1945,7 +1945,7 @@ ath5k_beacon_update_timers(struct ath5k_
+@@ -1952,7 +1952,7 @@ ath5k_beacon_update_timers(struct ath5k_
        u64 hw_tsf;
  
        intval = ah->bintval & AR5K_BEACON_PERIOD;
index 8ca821c..1948714 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath5k/reset.c
 +++ b/drivers/net/wireless/ath/ath5k/reset.c
-@@ -1040,6 +1040,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, 
+@@ -1152,6 +1152,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
        tsf_lo = 0;
        mode = 0;
  
@@ -8,7 +8,7 @@
        /*
         * Sanity check for fast flag
         * Fast channel change only available
-@@ -1047,6 +1048,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, 
+@@ -1159,6 +1160,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
         */
        if (fast && (ah->ah_radio != AR5K_RF2413) &&
        (ah->ah_radio != AR5K_RF5413))
index 72da8d8..87e695b 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1715,8 +1715,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1795,8 +1795,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
        REG_WRITE(ah, AR_OBS, 8);
  
        if (ah->config.rx_intr_mitigation) {
index ef568dc..c5ca0e2 100644 (file)
@@ -8,7 +8,7 @@
        int chan_idx;
        int chan_is_ht;
        struct survey_info *cur_survey;
-@@ -654,6 +655,7 @@ struct ath_softc {
+@@ -655,6 +656,7 @@ struct ath_softc {
        u8 ant_tx, ant_rx;
  };
  
@@ -81,7 +81,7 @@
        sc->debug.sampidx = 0;
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1554,7 +1554,7 @@ static void ath9k_disable_ps(struct ath_
+@@ -1564,7 +1564,7 @@ static void ath9k_disable_ps(struct ath_
  
  }
  
@@ -90,7 +90,7 @@
  {
        struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
-@@ -1606,9 +1606,10 @@ static int ath9k_config(struct ieee80211
+@@ -1616,9 +1616,10 @@ static int ath9k_config(struct ieee80211
  
        if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
                struct ieee80211_channel *curchan = hw->conf.channel;
                unsigned long flags;
  
                if (ah->curchan)
-@@ -1661,7 +1662,23 @@ static int ath9k_config(struct ieee80211
+@@ -1671,7 +1672,23 @@ static int ath9k_config(struct ieee80211
                        memset(&sc->survey[pos], 0, sizeof(struct survey_info));
                }
  
                        return -EINVAL;
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1549,6 +1549,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+@@ -1609,6 +1609,10 @@ int ath9k_hw_reset(struct ath_hw *ah, st
            caldata->rtt_hist.num_readings)
                allow_fbs = true;
  
@@ -1,6 +1,6 @@
 --- a/net/mac80211/main.c
 +++ b/net/mac80211/main.c
-@@ -237,7 +237,9 @@ void ieee80211_bss_info_change_notify(st
+@@ -196,7 +196,9 @@ void ieee80211_bss_info_change_notify(st
                                      u32 changed)
  {
        struct ieee80211_local *local = sdata->local;
@@ -10,7 +10,7 @@
  
        if (!changed)
                return;
-@@ -267,6 +269,22 @@ void ieee80211_bss_info_change_notify(st
+@@ -226,6 +228,22 @@ void ieee80211_bss_info_change_notify(st
  
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_AP:
diff --git a/package/mac80211/patches/520-mac80211_minstrel_ht_aggr_delay.patch b/package/mac80211/patches/520-mac80211_minstrel_ht_aggr_delay.patch
deleted file mode 100644 (file)
index 8f074f0..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -357,10 +357,12 @@ minstrel_downgrade_rate(struct minstrel_
- }
- static void
--minstrel_aggr_check(struct minstrel_priv *mp, struct ieee80211_sta *pubsta, struct sk_buff *skb)
-+minstrel_aggr_check(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+                  struct ieee80211_sta *pubsta, struct sk_buff *skb)
- {
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
-+      unsigned long t1, t2;
-       u16 tid;
-       if (unlikely(!ieee80211_is_data_qos(hdr->frame_control)))
-@@ -376,6 +378,12 @@ minstrel_aggr_check(struct minstrel_priv
-       if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
-               return;
-+      t1 = mi->last_aggr_start_time[tid];
-+      t2 = t1 + msecs_to_jiffies(5000);
-+      if (unlikely(time_in_range(jiffies, t1, t2)))
-+              return;
-+
-+      mi->last_aggr_start_time[tid] = jiffies;
-       ieee80211_start_tx_ba_session(pubsta, tid, 5000);
- }
-@@ -455,7 +463,7 @@ minstrel_ht_tx_status(void *priv, struct
-       if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
-               minstrel_ht_update_stats(mp, mi);
-               if (!(info->flags & IEEE80211_TX_CTL_AMPDU))
--                      minstrel_aggr_check(mp, sta, skb);
-+                      minstrel_aggr_check(mp, mi, sta, skb);
-       }
- }
---- a/net/mac80211/rc80211_minstrel_ht.h
-+++ b/net/mac80211/rc80211_minstrel_ht.h
-@@ -109,6 +109,8 @@ struct minstrel_ht_sta {
-       /* MCS rate group info and statistics */
-       struct minstrel_mcs_group_data groups[MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS];
-+
-+      unsigned long last_aggr_start_time[IEEE80211_QOS_CTL_TID_MASK + 1];
- };
- struct minstrel_ht_sta_priv {
index 51e649e..4e4dcb8 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/mac80211/iface.c
 +++ b/net/mac80211/iface.c
-@@ -699,6 +699,7 @@ static const struct net_device_ops ieee8
+@@ -686,6 +686,7 @@ static const struct net_device_ops ieee8
  static void ieee80211_if_setup(struct net_device *dev)
  {
        ether_setup(dev);
diff --git a/package/mac80211/patches/523-minstrel_ht_optimize.patch b/package/mac80211/patches/523-minstrel_ht_optimize.patch
deleted file mode 100644 (file)
index 8e804ca..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
---- a/net/mac80211/rc80211_minstrel_ht.h
-+++ b/net/mac80211/rc80211_minstrel_ht.h
-@@ -70,6 +70,8 @@ struct minstrel_mcs_group_data {
- };
- struct minstrel_ht_sta {
-+      struct ieee80211_tx_rate tx_rates[3];
-+
-       /* ampdu length (average, per sampling interval) */
-       unsigned int ampdu_len;
-       unsigned int ampdu_packets;
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -87,6 +87,10 @@ const struct mcs_group minstrel_mcs_grou
- static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES];
-+static void
-+minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+                     struct ieee80211_tx_rate *rate, int index,
-+                     bool sample, bool rtscts);
- /*
-  * Perform EWMA (Exponentially Weighted Moving Average) calculation
-  */
-@@ -174,6 +178,17 @@ minstrel_ht_calc_tp(struct minstrel_priv
-       mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);
- }
-+static void
-+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
-+{
-+      minstrel_ht_set_rate(mp, mi, &mi->tx_rates[0], mi->max_tp_rate,
-+                           false, false);
-+      minstrel_ht_set_rate(mp, mi, &mi->tx_rates[1], mi->max_tp_rate2,
-+                           false, true);
-+      minstrel_ht_set_rate(mp, mi, &mi->tx_rates[2], mi->max_prob_rate,
-+                           false, true);
-+}
-+
- /*
-  * Update rate statistics and select new primary rates
-  *
-@@ -294,6 +309,7 @@ minstrel_ht_update_stats(struct minstrel
-               }
-       }
-+      minstrel_ht_update_rates(mp, mi);
-       mi->stats_update = jiffies;
- }
-@@ -332,8 +348,8 @@ minstrel_next_sample_idx(struct minstrel
- }
- static void
--minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
--                      bool primary)
-+minstrel_downgrade_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+                      unsigned int *idx, bool primary)
- {
-       int group, orig_group;
-@@ -352,6 +368,7 @@ minstrel_downgrade_rate(struct minstrel_
-                       *idx = mi->groups[group].max_tp_rate;
-               else
-                       *idx = mi->groups[group].max_tp_rate2;
-+              minstrel_ht_update_rates(mp, mi);
-               break;
-       }
- }
-@@ -452,13 +469,13 @@ minstrel_ht_tx_status(void *priv, struct
-       if (rate->attempts > 30 &&
-           MINSTREL_FRAC(rate->success, rate->attempts) <
-           MINSTREL_FRAC(20, 100))
--              minstrel_downgrade_rate(mi, &mi->max_tp_rate, true);
-+              minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate, true);
-       rate2 = minstrel_get_ratestats(mi, mi->max_tp_rate2);
-       if (rate2->attempts > 30 &&
-           MINSTREL_FRAC(rate2->success, rate2->attempts) <
-           MINSTREL_FRAC(20, 100))
--              minstrel_downgrade_rate(mi, &mi->max_tp_rate2, false);
-+              minstrel_downgrade_rate(mp, mi, &mi->max_tp_rate2, false);
-       if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
-               minstrel_ht_update_stats(mp, mi);
-@@ -523,7 +540,6 @@ minstrel_calc_retransmit(struct minstrel
- static void
- minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-                      struct ieee80211_tx_rate *rate, int index,
--                     struct ieee80211_tx_rate_control *txrc,
-                      bool sample, bool rtscts)
- {
-       const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
-@@ -611,6 +627,7 @@ minstrel_ht_get_rate(void *priv, struct 
-       struct minstrel_priv *mp = priv;
-       int sample_idx;
-       bool sample = false;
-+      int last = 0;
-       if (rate_control_send_low(sta, priv_sta, txrc))
-               return;
-@@ -636,11 +653,10 @@ minstrel_ht_get_rate(void *priv, struct 
-       if (sample_idx >= 0) {
-               sample = true;
-               minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
--                      txrc, true, false);
-+                      true, false);
-               info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-       } else {
--              minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
--                      txrc, false, false);
-+              ar[0] = mi->tx_rates[0];
-       }
-       if (mp->hw->max_rates >= 3) {
-@@ -650,33 +666,27 @@ minstrel_ht_get_rate(void *priv, struct 
-                * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
-                */
-               if (sample_idx >= 0)
--                      minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
--                              txrc, false, false);
-+                      ar[1] = mi->tx_rates[0];
-               else
--                      minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
--                              txrc, false, true);
--
--              minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
--                                   txrc, false, !sample);
-+                      ar[1] = mi->tx_rates[1];
--              ar[3].count = 0;
--              ar[3].idx = -1;
-+              ar[2] = mi->tx_rates[2];
-+              last = 3;
-       } else if (mp->hw->max_rates == 2) {
-               /*
-                * Only 2 tx rates supported, use
-                * sample_rate -> max_prob_rate for sampling and
-                * max_tp_rate -> max_prob_rate by default.
-                */
--              minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
--                                   txrc, false, !sample);
--
--              ar[2].count = 0;
--              ar[2].idx = -1;
-+              ar[1] = mi->tx_rates[2];
-+              last = 2;
-       } else {
-               /* Not using MRR, only use the first rate */
--              ar[1].count = 0;
--              ar[1].idx = -1;
-+              last = 1;
-+
-       }
-+      ar[last].count = 0;
-+      ar[last].idx = -1;
-       mi->total_packets++;
-@@ -768,6 +778,7 @@ minstrel_ht_update_caps(void *priv, stru
-       if (!n_supported)
-               goto use_legacy;
-+      minstrel_ht_update_rates(mp, mi);
-       return;
- use_legacy:
index 0fa6a22..8ed9216 100644 (file)
@@ -11,7 +11,7 @@
        u16 listen_interval;
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -1677,7 +1677,7 @@ static int ieee80211_get_tx_power(struct
+@@ -1696,7 +1696,7 @@ static int ieee80211_get_tx_power(struct
  {
        struct ieee80211_local *local = wiphy_priv(wiphy);
  
@@ -22,7 +22,7 @@
  }
 --- a/net/mac80211/main.c
 +++ b/net/mac80211/main.c
-@@ -208,6 +208,7 @@ int ieee80211_hw_config(struct ieee80211
+@@ -167,6 +167,7 @@ int ieee80211_hw_config(struct ieee80211
  
        if (local->hw.conf.power_level != power) {
                changed |= IEEE80211_CONF_CHANGE_POWER;
index 760f4d7..bedfef8 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1684,6 +1684,8 @@ int ath9k_config(struct ieee80211_hw *hw
+@@ -1694,6 +1694,8 @@ int ath9k_config(struct ieee80211_hw *hw
                        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
-@@ -1699,6 +1701,7 @@ int ath9k_config(struct ieee80211_hw *hw
+@@ -1709,6 +1711,7 @@ int ath9k_config(struct ieee80211_hw *hw
                sc->config.txpowlimit = 2 * conf->power_level;
                ath9k_cmn_update_txpow(ah, sc->curtxpow,
                                       sc->config.txpowlimit, &sc->curtxpow);
index fe7afde..70889d6 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1382,10 +1382,16 @@ static bool ath9k_hw_set_reset_reg(struc
+@@ -1394,10 +1394,16 @@ static bool ath9k_hw_set_reset_reg(struc
  static bool ath9k_hw_chip_reset(struct ath_hw *ah,
                                struct ath9k_channel *chan)
  {
diff --git a/package/mac80211/patches/543-ath9k_enable_ar9100_ani.patch b/package/mac80211/patches/543-ath9k_enable_ar9100_ani.patch
deleted file mode 100644 (file)
index 80b8d2e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -513,7 +513,7 @@ static int ath9k_hw_post_init(struct ath
-               return ecode;
-       }
--      if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) {
-+      if (!AR_SREV_9340(ah)) {
-               ath9k_hw_ani_setup(ah);
-               ath9k_hw_ani_init(ah);
-       }
diff --git a/package/mac80211/patches/543-ath9k_fix_half_quarter_rx_latency.patch b/package/mac80211/patches/543-ath9k_fix_half_quarter_rx_latency.patch
new file mode 100644 (file)
index 0000000..45246ea
--- /dev/null
@@ -0,0 +1,32 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1006,16 +1006,26 @@ void ath9k_hw_init_global_settings(struc
+       if (IS_CHAN_HALF_RATE(chan)) {
+               eifs = 175;
+-              rx_lat *= 2;
++
++              if (!AR_SREV_9300_20_OR_LATER(ah))
++                      rx_lat = 10;
++              else
++                      rx_lat *= 2;
++
+               tx_lat *= 2;
+               if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+-                  tx_lat += 11;
++                      tx_lat += 11;
+               slottime = 13;
+               sifstime = 32;
+       } else if (IS_CHAN_QUARTER_RATE(chan)) {
+               eifs = 340;
+-              rx_lat = (rx_lat * 4) - 1;
++
++              if (!AR_SREV_9300_20_OR_LATER(ah))
++                      rx_lat = 20;
++              else
++                      rx_lat = (rx_lat * 4) - 1;
++
+               tx_lat *= 4;
+               if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+                   tx_lat += 22;
diff --git a/package/mac80211/patches/544-ath9k_fix_half_quarter_sifs.patch b/package/mac80211/patches/544-ath9k_fix_half_quarter_sifs.patch
new file mode 100644 (file)
index 0000000..6bde765
--- /dev/null
@@ -0,0 +1,44 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1007,31 +1007,35 @@ void ath9k_hw_init_global_settings(struc
+       if (IS_CHAN_HALF_RATE(chan)) {
+               eifs = 175;
+-              if (!AR_SREV_9300_20_OR_LATER(ah))
++              if (!AR_SREV_9300_20_OR_LATER(ah)) {
+                       rx_lat = 10;
+-              else
++                      sifstime = 8;
++              } else {
+                       rx_lat *= 2;
++                      sifstime = 32;
++              }
+               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;
+-              if (!AR_SREV_9300_20_OR_LATER(ah))
++              if (!AR_SREV_9300_20_OR_LATER(ah)) {
+                       rx_lat = 20;
+-              else
++                      sifstime = 8;
++              } else {
+                       rx_lat = (rx_lat * 4) - 1;
++                      sifstime = 64;
++              }
+               tx_lat *= 4;
+               if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+                   tx_lat += 22;
+               slottime = 21;
+-              sifstime = 64;
+       } else {
+               if (AR_SREV_9287(ah) && AR_SREV_9287_13_OR_LATER(ah)) {
+                       eifs = AR_D_GBL_IFS_EIFS_ASYNC_FIFO;
diff --git a/package/mac80211/patches/544-ath9k_fix_sleep_mode_reg.patch b/package/mac80211/patches/544-ath9k_fix_sleep_mode_reg.patch
deleted file mode 100644 (file)
index 2231b44..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1846,7 +1846,8 @@ static void ath9k_set_power_sleep(struct
-       }
-       /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
--      REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
-+      if (AR_SREV_9300_20_OR_LATER(ah))
-+              REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
- }
- /*
index 378fb09..4040f86 100644 (file)
        u8 rs_num_delims;
 --- a/drivers/net/wireless/ath/ath9k/recv.c
 +++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -981,6 +981,7 @@ static int ath9k_rx_skb_preprocess(struc
+@@ -980,6 +980,7 @@ static int ath9k_rx_skb_preprocess(struc
                                   bool *decrypt_error)
  {
        struct ath_hw *ah = common->ah;
  
        memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
  
-@@ -1006,6 +1007,20 @@ static int ath9k_rx_skb_preprocess(struc
+@@ -1005,6 +1006,20 @@ static int ath9k_rx_skb_preprocess(struc
        rx_status->antenna = rx_stats->rs_antenna;
        rx_status->flag |= RX_FLAG_MACTIME_MPDU;
  
        return 0;
  }
  
-@@ -1536,14 +1551,14 @@ static void ath_ant_comb_scan(struct ath
+@@ -1535,14 +1550,14 @@ static void ath_ant_comb_scan(struct ath
        struct ath_ant_comb *antcomb = &sc->ant_comb;
        int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
        int curr_main_set;
        /* Record packet only when both main_rssi and  alt_rssi is positive */
 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
 +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -452,12 +452,12 @@ int ath9k_hw_process_rxdesc_edma(struct 
+@@ -484,12 +484,12 @@ int ath9k_hw_process_rxdesc_edma(struct 
  
        /* XXX: Keycache */
        rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
        RX_SAMP_DBG(rate) = rs->rs_rate;
 --- a/include/linux/nl80211.h
 +++ b/include/linux/nl80211.h
-@@ -1621,6 +1621,8 @@ enum nl80211_sta_bss_param {
+@@ -1651,6 +1651,8 @@ enum nl80211_sta_bss_param {
   *     containing info as possible, see &enum nl80211_sta_bss_param
   * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected
   * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update.
   * @__NL80211_STA_INFO_AFTER_LAST: internal
   * @NL80211_STA_INFO_MAX: highest possible station info attribute
   */
-@@ -1643,6 +1645,8 @@ enum nl80211_sta_info {
+@@ -1673,6 +1675,8 @@ enum nl80211_sta_info {
        NL80211_STA_INFO_BSS_PARAM,
        NL80211_STA_INFO_CONNECTED_TIME,
        NL80211_STA_INFO_STA_FLAGS,
        __NL80211_STA_INFO_AFTER_LAST,
 --- a/net/wireless/nl80211.c
 +++ b/net/wireless/nl80211.c
-@@ -2287,6 +2287,33 @@ nla_put_failure:
+@@ -2322,6 +2322,33 @@ nla_put_failure:
        return false;
  }
  
  static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
                                int flags, struct net_device *dev,
                                const u8 *mac_addr, struct station_info *sinfo)
-@@ -2333,6 +2360,18 @@ static int nl80211_send_station(struct s
+@@ -2368,6 +2395,18 @@ static int nl80211_send_station(struct s
        if (sinfo->filled & STATION_INFO_SIGNAL_AVG)
                NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
                           sinfo->signal_avg);
                                          NL80211_STA_INFO_TX_BITRATE))
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -330,6 +330,7 @@ static void sta_set_sinfo(struct sta_inf
+@@ -340,6 +340,7 @@ static void sta_set_sinfo(struct sta_inf
  {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        struct timespec uptime;
  
        sinfo->generation = sdata->local->sta_generation;
  
-@@ -365,6 +366,17 @@ static void sta_set_sinfo(struct sta_inf
+@@ -375,6 +376,17 @@ static void sta_set_sinfo(struct sta_inf
                sinfo->signal = (s8)sta->last_signal;
                sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
        }
diff --git a/package/mac80211/patches/560-ath9k_rework_send_bar.patch b/package/mac80211/patches/560-ath9k_rework_send_bar.patch
new file mode 100644 (file)
index 0000000..9176713
--- /dev/null
@@ -0,0 +1,240 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -159,6 +159,9 @@ void ath_descdma_cleanup(struct ath_soft
+ /* return block-ack bitmap index given sequence and starting sequence */
+ #define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
++/* return the seqno for _start + _offset */
++#define ATH_BA_INDEX2SEQ(_seq, _offset) (((_seq) + (_offset)) & (IEEE80211_SEQ_MAX - 1))
++
+ /* returns delimiter padding required given the packet length */
+ #define ATH_AGGR_GET_NDELIM(_len)                                     \
+        (((_len) >= ATH_AGGR_MINPLEN) ? 0 :                             \
+@@ -253,9 +256,9 @@ struct ath_atx_tid {
+ struct ath_node {
+ #ifdef CONFIG_ATH9K_DEBUGFS
+       struct list_head list; /* for sc->nodes */
++#endif
+       struct ieee80211_sta *sta; /* station struct we're part of */
+       struct ieee80211_vif *vif; /* interface with which we're associated */
+-#endif
+       struct ath_atx_tid tid[WME_NUM_TID];
+       struct ath_atx_ac ac[WME_NUM_AC];
+       int ps_key;
+@@ -277,7 +280,6 @@ struct ath_tx_control {
+ };
+ #define ATH_TX_ERROR        0x01
+-#define ATH_TX_BAR          0x02
+ /**
+  * @txq_map:  Index is mac80211 queue number.  This is
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -644,9 +644,9 @@ static void ath_node_attach(struct ath_s
+       spin_lock(&sc->nodes_lock);
+       list_add(&an->list, &sc->nodes);
+       spin_unlock(&sc->nodes_lock);
++#endif
+       an->sta = sta;
+       an->vif = vif;
+-#endif
+       if (sc->sc_flags & SC_OP_TXAGGR) {
+               ath_tx_node_init(sc, an);
+               an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -53,7 +53,7 @@ static void ath_tx_complete(struct ath_s
+                           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);
++                              struct ath_tx_status *ts, int txok);
+ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+                            struct list_head *head, bool internal);
+ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+@@ -150,6 +150,12 @@ static struct ath_frame_info *get_frame_
+       return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
+ }
++static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
++{
++      ieee80211_send_bar(tid->an->vif, tid->an->sta->addr, tid->tidno,
++                         seqno << IEEE80211_SEQ_SEQ_SHIFT);
++}
++
+ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+ {
+       struct ath_txq *txq = tid->ac->txq;
+@@ -158,6 +164,7 @@ static void ath_tx_flush_tid(struct ath_
+       struct list_head bf_head;
+       struct ath_tx_status ts;
+       struct ath_frame_info *fi;
++      bool sendbar = false;
+       INIT_LIST_HEAD(&bf_head);
+@@ -172,7 +179,8 @@ static void ath_tx_flush_tid(struct ath_
+               if (bf && fi->retries) {
+                       list_add_tail(&bf->list, &bf_head);
+                       ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
+-                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
++                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
++                      sendbar = true;
+               } else {
+                       ath_tx_send_normal(sc, txq, NULL, skb);
+               }
+@@ -185,6 +193,9 @@ static void ath_tx_flush_tid(struct ath_
+       }
+       spin_unlock_bh(&txq->axq_lock);
++
++      if (sendbar)
++              ath_send_bar(tid, tid->seq_start);
+ }
+ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+@@ -255,7 +266,7 @@ static void ath_tid_drain(struct ath_sof
+                       ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
+               spin_unlock(&txq->axq_lock);
+-              ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
++              ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+               spin_lock(&txq->axq_lock);
+       }
+@@ -381,7 +392,7 @@ static void ath_tx_complete_aggr(struct 
+       struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
+       struct list_head bf_head;
+       struct sk_buff_head bf_pending;
+-      u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0;
++      u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
+       u32 ba[WME_BA_BMP_SIZE >> 5];
+       int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
+       bool rc_update = true;
+@@ -391,6 +402,7 @@ static void ath_tx_complete_aggr(struct 
+       u8 tidno;
+       bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
+       int i, retries;
++      int bar_index = -1;
+       skb = bf->bf_mpdu;
+       hdr = (struct ieee80211_hdr *)skb->data;
+@@ -416,8 +428,7 @@ static void ath_tx_complete_aggr(struct 
+                       if (!bf->bf_stale || bf_next != NULL)
+                               list_move_tail(&bf->list, &bf_head);
+-                      ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+-                              0, 0);
++                      ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0);
+                       bf = bf_next;
+               }
+@@ -427,6 +438,7 @@ static void ath_tx_complete_aggr(struct 
+       an = (struct ath_node *)sta->drv_priv;
+       tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
+       tid = ATH_AN_2_TID(an, tidno);
++      seq_first = tid->seq_start;
+       /*
+        * The hardware occasionally sends a tx status for the wrong TID.
+@@ -495,8 +507,9 @@ static void ath_tx_complete_aggr(struct 
+                               txpending = 1;
+                       } else {
+                               txfail = 1;
+-                              sendbar = 1;
+                               txfail_cnt++;
++                              bar_index = max_t(int, bar_index,
++                                      ATH_BA_INDEX(seq_first, seqno));
+                       }
+               }
+@@ -525,7 +538,7 @@ static void ath_tx_complete_aggr(struct 
+                       }
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
+-                              !txfail, sendbar);
++                              !txfail);
+               } else {
+                       /* retry the un-acked ones */
+                       if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
+@@ -545,8 +558,10 @@ static void ath_tx_complete_aggr(struct 
+                                               ath_tx_complete_buf(sc, bf, txq,
+                                                                   &bf_head,
+-                                                                  ts, 0,
+-                                                                  !flush);
++                                                                  ts, 0);
++                                              bar_index = max_t(int, bar_index,
++                                                      ATH_BA_INDEX(seq_first,
++                                                              seqno));
+                                               break;
+                                       }
+@@ -564,6 +579,9 @@ static void ath_tx_complete_aggr(struct 
+               bf = bf_next;
+       }
++      if (bar_index >= 0)
++              ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
++
+       /* prepend un-acked frames to the beginning of the pending frame queue */
+       if (!skb_queue_empty(&bf_pending)) {
+               if (an->sleeping)
+@@ -1452,7 +1470,7 @@ static void ath_drain_txq_list(struct at
+                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
+                                            retry_tx);
+               else
+-                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
++                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+               spin_lock_bh(&txq->axq_lock);
+       }
+ }
+@@ -1967,9 +1985,6 @@ static void ath_tx_complete(struct ath_s
+       ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
+-      if (tx_flags & ATH_TX_BAR)
+-              tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+-
+       if (!(tx_flags & ATH_TX_ERROR))
+               /* Frame was ACKed */
+               tx_info->flags |= IEEE80211_TX_STAT_ACK;
+@@ -2013,16 +2028,13 @@ static void ath_tx_complete(struct ath_s
+ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+                               struct ath_txq *txq, struct list_head *bf_q,
+-                              struct ath_tx_status *ts, int txok, int sendbar)
++                              struct ath_tx_status *ts, int txok)
+ {
+       struct sk_buff *skb = bf->bf_mpdu;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       unsigned long flags;
+       int tx_flags = 0;
+-      if (sendbar)
+-              tx_flags = ATH_TX_BAR;
+-
+       if (!txok)
+               tx_flags |= ATH_TX_ERROR;
+@@ -2129,7 +2141,7 @@ static void ath_tx_process_buffer(struct
+       if (!bf_isampdu(bf)) {
+               ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
+-              ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok, 0);
++              ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
+       } else
+               ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -856,7 +856,7 @@ void ath_debug_stat_tx(struct ath_softc 
+       sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
+       if (bf_isampdu(bf)) {
+-              if (flags & ATH_TX_BAR)
++              if (flags & ATH_TX_ERROR)
+                       TX_STAT_INC(qnum, a_xretries);
+               else
+                       TX_STAT_INC(qnum, a_completed);
diff --git a/package/mac80211/patches/560-mac80211_fix_ap_vlan_aggr.patch b/package/mac80211/patches/560-mac80211_fix_ap_vlan_aggr.patch
deleted file mode 100644 (file)
index 051f1a9..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
---- a/net/mac80211/driver-ops.h
-+++ b/net/mac80211/driver-ops.h
-@@ -10,6 +10,16 @@ static inline void check_sdata_in_driver
-       WARN_ON(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER));
- }
-+static inline struct ieee80211_sub_if_data *
-+get_bss_sdata(struct ieee80211_sub_if_data *sdata)
-+{
-+      if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
-+              sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
-+                                   u.ap);
-+
-+      return sdata;
-+}
-+
- static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
- {
-       local->ops->tx(&local->hw, skb);
-@@ -427,6 +437,7 @@ static inline void drv_sta_notify(struct
-                                 enum sta_notify_cmd cmd,
-                                 struct ieee80211_sta *sta)
- {
-+      sdata = get_bss_sdata(sdata);
-       check_sdata_in_driver(sdata);
-       trace_drv_sta_notify(local, sdata, cmd, sta);
-@@ -443,6 +454,7 @@ static inline int drv_sta_add(struct iee
-       might_sleep();
-+      sdata = get_bss_sdata(sdata);
-       check_sdata_in_driver(sdata);
-       trace_drv_sta_add(local, sdata, sta);
-@@ -460,6 +472,7 @@ static inline void drv_sta_remove(struct
- {
-       might_sleep();
-+      sdata = get_bss_sdata(sdata);
-       check_sdata_in_driver(sdata);
-       trace_drv_sta_remove(local, sdata, sta);
-@@ -553,6 +566,7 @@ static inline int drv_ampdu_action(struc
-       might_sleep();
-+      sdata = get_bss_sdata(sdata);
-       check_sdata_in_driver(sdata);
-       trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
---- a/net/mac80211/sta_info.c
-+++ b/net/mac80211/sta_info.c
-@@ -353,10 +353,6 @@ static int sta_info_finish_insert(struct
-       if (!sta->dummy || dummy_reinsert) {
-               /* notify driver */
--              if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
--                      sdata = container_of(sdata->bss,
--                                           struct ieee80211_sub_if_data,
--                                           u.ap);
-               err = drv_sta_add(local, sdata, &sta->sta);
-               if (err) {
-                       if (!async)
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -550,7 +550,7 @@ void ieee80211_start_tx_ba_cb(struct iee
-       }
-       mutex_lock(&local->sta_mtx);
--      sta = sta_info_get(sdata, ra);
-+      sta = sta_info_get_bss(sdata, ra);
-       if (!sta) {
-               mutex_unlock(&local->sta_mtx);
- #ifdef CONFIG_MAC80211_HT_DEBUG
-@@ -679,7 +679,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee
-       mutex_lock(&local->sta_mtx);
--      sta = sta_info_get(sdata, ra);
-+      sta = sta_info_get_bss(sdata, ra);
-       if (!sta) {
- #ifdef CONFIG_MAC80211_HT_DEBUG
-               printk(KERN_DEBUG "Could not find station: %pM\n", ra);
---- a/net/mac80211/agg-rx.c
-+++ b/net/mac80211/agg-rx.c
-@@ -109,7 +109,7 @@ void ieee80211_stop_rx_ba_session(struct
-       int i;
-       rcu_read_lock();
--      sta = sta_info_get(sdata, addr);
-+      sta = sta_info_get_bss(sdata, addr);
-       if (!sta) {
-               rcu_read_unlock();
-               return;
diff --git a/package/mac80211/patches/561-ath9k_reduce_indentation.patch b/package/mac80211/patches/561-ath9k_reduce_indentation.patch
new file mode 100644 (file)
index 0000000..08ff157
--- /dev/null
@@ -0,0 +1,159 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -490,27 +490,25 @@ static void ath_tx_complete_aggr(struct 
+               } else if (!isaggr && txok) {
+                       /* transmit completion */
+                       acked_cnt++;
++              } else if ((tid->state & AGGR_CLEANUP) || !retry) {
++                      /*
++                       * cleanup in progress, just fail
++                       * the un-acked sub-frames
++                       */
++                      txfail = 1;
++              } else if (flush) {
++                      txpending = 1;
++              } else if (fi->retries < ATH_MAX_SW_RETRIES) {
++                      if (txok || !an->sleeping)
++                              ath_tx_set_retry(sc, txq, bf->bf_mpdu,
++                                               retries);
++
++                      txpending = 1;
+               } else {
+-                      if ((tid->state & AGGR_CLEANUP) || !retry) {
+-                              /*
+-                               * cleanup in progress, just fail
+-                               * the un-acked sub-frames
+-                               */
+-                              txfail = 1;
+-                      } else if (flush) {
+-                              txpending = 1;
+-                      } else if (fi->retries < ATH_MAX_SW_RETRIES) {
+-                              if (txok || !an->sleeping)
+-                                      ath_tx_set_retry(sc, txq, bf->bf_mpdu,
+-                                                       retries);
+-
+-                              txpending = 1;
+-                      } else {
+-                              txfail = 1;
+-                              txfail_cnt++;
+-                              bar_index = max_t(int, bar_index,
+-                                      ATH_BA_INDEX(seq_first, seqno));
+-                      }
++                      txfail = 1;
++                      txfail_cnt++;
++                      bar_index = max_t(int, bar_index,
++                              ATH_BA_INDEX(seq_first, seqno));
+               }
+               /*
+@@ -541,32 +539,29 @@ static void ath_tx_complete_aggr(struct 
+                               !txfail);
+               } else {
+                       /* retry the un-acked ones */
+-                      if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
+-                              if (bf->bf_next == NULL && bf_last->bf_stale) {
+-                                      struct ath_buf *tbf;
+-
+-                                      tbf = ath_clone_txbuf(sc, bf_last);
+-                                      /*
+-                                       * Update tx baw and complete the
+-                                       * frame with failed status if we
+-                                       * run out of tx buf.
+-                                       */
+-                                      if (!tbf) {
+-                                              spin_lock_bh(&txq->axq_lock);
+-                                              ath_tx_update_baw(sc, tid, seqno);
+-                                              spin_unlock_bh(&txq->axq_lock);
+-
+-                                              ath_tx_complete_buf(sc, bf, txq,
+-                                                                  &bf_head,
+-                                                                  ts, 0);
+-                                              bar_index = max_t(int, bar_index,
+-                                                      ATH_BA_INDEX(seq_first,
+-                                                              seqno));
+-                                              break;
+-                                      }
++                      if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
++                          bf->bf_next == NULL && bf_last->bf_stale) {
++                              struct ath_buf *tbf;
+-                                      fi->bf = tbf;
++                              tbf = ath_clone_txbuf(sc, bf_last);
++                              /*
++                               * Update tx baw and complete the
++                               * frame with failed status if we
++                               * run out of tx buf.
++                               */
++                              if (!tbf) {
++                                      spin_lock_bh(&txq->axq_lock);
++                                      ath_tx_update_baw(sc, tid, seqno);
++                                      spin_unlock_bh(&txq->axq_lock);
++
++                                      ath_tx_complete_buf(sc, bf, txq,
++                                                          &bf_head, ts, 0);
++                                      bar_index = max_t(int, bar_index,
++                                              ATH_BA_INDEX(seq_first, seqno));
++                                      break;
+                               }
++
++                              fi->bf = tbf;
+                       }
+                       /*
+@@ -654,24 +649,26 @@ static u32 ath_lookup_rate(struct ath_so
+       max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
+       for (i = 0; i < 4; i++) {
+-              if (rates[i].count) {
+-                      int modeidx;
+-                      if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
+-                              legacy = 1;
+-                              break;
+-                      }
+-
+-                      if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+-                              modeidx = MCS_HT40;
+-                      else
+-                              modeidx = MCS_HT20;
++              int modeidx;
+-                      if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
+-                              modeidx++;
++              if (!rates[i].count)
++                      continue;
+-                      frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
+-                      max_4ms_framelen = min(max_4ms_framelen, frmlen);
++              if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
++                      legacy = 1;
++                      break;
+               }
++
++              if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
++                      modeidx = MCS_HT40;
++              else
++                      modeidx = MCS_HT20;
++
++              if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
++                      modeidx++;
++
++              frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
++              max_4ms_framelen = min(max_4ms_framelen, frmlen);
+       }
+       /*
+@@ -1598,11 +1595,9 @@ void ath_txq_schedule(struct ath_softc *
+                               break;
+               }
+-              if (!list_empty(&ac->tid_q)) {
+-                      if (!ac->sched) {
+-                              ac->sched = true;
+-                              list_add_tail(&ac->list, &txq->axq_acq);
+-                      }
++              if (!list_empty(&ac->tid_q) && !ac->sched) {
++                      ac->sched = true;
++                      list_add_tail(&ac->list, &txq->axq_acq);
+               }
+               if (ac == last_ac ||
diff --git a/package/mac80211/patches/562-ath9k_remove_seq_incr.patch b/package/mac80211/patches/562-ath9k_remove_seq_incr.patch
new file mode 100644 (file)
index 0000000..a89d0a5
--- /dev/null
@@ -0,0 +1,13 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1742,10 +1742,6 @@ static void ath_tx_send_normal(struct at
+       list_add_tail(&bf->list, &bf_head);
+       bf->bf_state.bf_type = 0;
+-      /* update starting sequence number for subsequent ADDBA request */
+-      if (tid)
+-              INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+-
+       bf->bf_lastbf = bf;
+       ath_tx_fill_desc(sc, bf, txq, fi->framelen);
+       ath_tx_txqaddbuf(sc, txq, &bf_head, false);
diff --git a/package/mac80211/patches/563-ath9k_simplify_tx_locking.patch b/package/mac80211/patches/563-ath9k_simplify_tx_locking.patch
new file mode 100644 (file)
index 0000000..93aa33d
--- /dev/null
@@ -0,0 +1,214 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -169,13 +169,11 @@ static void ath_tx_flush_tid(struct ath_
+       INIT_LIST_HEAD(&bf_head);
+       memset(&ts, 0, sizeof(ts));
+-      spin_lock_bh(&txq->axq_lock);
+       while ((skb = __skb_dequeue(&tid->buf_q))) {
+               fi = get_frame_info(skb);
+               bf = fi->bf;
+-              spin_unlock_bh(&txq->axq_lock);
+               if (bf && fi->retries) {
+                       list_add_tail(&bf->list, &bf_head);
+                       ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
+@@ -184,7 +182,6 @@ static void ath_tx_flush_tid(struct ath_
+               } else {
+                       ath_tx_send_normal(sc, txq, NULL, skb);
+               }
+-              spin_lock_bh(&txq->axq_lock);
+       }
+       if (tid->baw_head == tid->baw_tail) {
+@@ -192,8 +189,6 @@ static void ath_tx_flush_tid(struct ath_
+               tid->state &= ~AGGR_CLEANUP;
+       }
+-      spin_unlock_bh(&txq->axq_lock);
+-
+       if (sendbar)
+               ath_send_bar(tid, tid->seq_start);
+ }
+@@ -254,9 +249,7 @@ static void ath_tid_drain(struct ath_sof
+               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;
+               }
+@@ -265,9 +258,7 @@ static void ath_tid_drain(struct ath_sof
+               if (fi->retries)
+                       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);
+-              spin_lock(&txq->axq_lock);
+       }
+       tid->seq_next = tid->seq_start;
+@@ -525,9 +516,7 @@ static void ath_tx_complete_aggr(struct 
+                        * complete the acked-ones/xretried ones; update
+                        * block-ack window
+                        */
+-                      spin_lock_bh(&txq->axq_lock);
+                       ath_tx_update_baw(sc, tid, seqno);
+-                      spin_unlock_bh(&txq->axq_lock);
+                       if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+                               memcpy(tx_info->control.rates, rates, sizeof(rates));
+@@ -550,9 +539,7 @@ static void ath_tx_complete_aggr(struct 
+                                * run out of tx buf.
+                                */
+                               if (!tbf) {
+-                                      spin_lock_bh(&txq->axq_lock);
+                                       ath_tx_update_baw(sc, tid, seqno);
+-                                      spin_unlock_bh(&txq->axq_lock);
+                                       ath_tx_complete_buf(sc, bf, txq,
+                                                           &bf_head, ts, 0);
+@@ -582,7 +569,6 @@ static void ath_tx_complete_aggr(struct 
+               if (an->sleeping)
+                       ieee80211_sta_set_buffered(sta, tid->tidno, true);
+-              spin_lock_bh(&txq->axq_lock);
+               skb_queue_splice(&bf_pending, &tid->buf_q);
+               if (!an->sleeping) {
+                       ath_tx_queue_tid(txq, tid);
+@@ -590,7 +576,6 @@ static void ath_tx_complete_aggr(struct 
+                       if (ts->ts_status & ATH9K_TXERR_FILT)
+                               tid->ac->clear_ps_filter = true;
+               }
+-              spin_unlock_bh(&txq->axq_lock);
+       }
+       if (tid->state & AGGR_CLEANUP)
+@@ -1190,9 +1175,9 @@ void ath_tx_aggr_stop(struct ath_softc *
+               txtid->state |= AGGR_CLEANUP;
+       else
+               txtid->state &= ~AGGR_ADDBA_COMPLETE;
+-      spin_unlock_bh(&txq->axq_lock);
+       ath_tx_flush_tid(sc, txtid);
++      spin_unlock_bh(&txq->axq_lock);
+ }
+ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
+@@ -1434,8 +1419,6 @@ static bool bf_is_ampdu_not_probing(stru
+ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
+                              struct list_head *list, bool retry_tx)
+-      __releases(txq->axq_lock)
+-      __acquires(txq->axq_lock)
+ {
+       struct ath_buf *bf, *lastbf;
+       struct list_head bf_head;
+@@ -1462,13 +1445,11 @@ static void ath_drain_txq_list(struct at
+               if (bf_is_ampdu_not_probing(bf))
+                       txq->axq_ampdu_depth--;
+-              spin_unlock_bh(&txq->axq_lock);
+               if (bf_isampdu(bf))
+                       ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
+                                            retry_tx);
+               else
+                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+-              spin_lock_bh(&txq->axq_lock);
+       }
+ }
+@@ -1847,8 +1828,6 @@ static void ath_tx_start_dma(struct ath_
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ath_buf *bf;
+-      spin_lock_bh(&txctl->txq->axq_lock);
+-
+       if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
+               /*
+                * Try aggregation if it's a unicast data frame
+@@ -1858,7 +1837,7 @@ static void ath_tx_start_dma(struct ath_
+       } else {
+               bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+               if (!bf)
+-                      goto out;
++                      return;
+               bf->bf_state.bfs_paprd = txctl->paprd;
+@@ -1867,9 +1846,6 @@ static void ath_tx_start_dma(struct ath_
+               ath_tx_send_normal(sc, txctl->txq, tid, skb);
+       }
+-
+-out:
+-      spin_unlock_bh(&txctl->txq->axq_lock);
+ }
+ /* Upon failure caller should free skb */
+@@ -1949,15 +1925,19 @@ int ath_tx_start(struct ieee80211_hw *hw
+        */
+       q = skb_get_queue_mapping(skb);
++
+       spin_lock_bh(&txq->axq_lock);
++
+       if (txq == sc->tx.txq_map[q] &&
+           ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
+               ieee80211_stop_queue(sc->hw, q);
+               txq->stopped = 1;
+       }
+-      spin_unlock_bh(&txq->axq_lock);
+       ath_tx_start_dma(sc, skb, txctl, tid);
++
++      spin_unlock_bh(&txq->axq_lock);
++
+       return 0;
+ }
+@@ -2003,7 +1983,6 @@ static void ath_tx_complete(struct ath_s
+       q = skb_get_queue_mapping(skb);
+       if (txq == sc->tx.txq_map[q]) {
+-              spin_lock_bh(&txq->axq_lock);
+               if (WARN_ON(--txq->pending_frames < 0))
+                       txq->pending_frames = 0;
+@@ -2011,7 +1990,6 @@ static void ath_tx_complete(struct ath_s
+                       ieee80211_wake_queue(sc->hw, q);
+                       txq->stopped = 0;
+               }
+-              spin_unlock_bh(&txq->axq_lock);
+       }
+       ieee80211_tx_status(hw, skb);
+@@ -2117,8 +2095,6 @@ static void ath_tx_rc_status(struct ath_
+ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
+                                 struct ath_tx_status *ts, struct ath_buf *bf,
+                                 struct list_head *bf_head)
+-      __releases(txq->axq_lock)
+-      __acquires(txq->axq_lock)
+ {
+       int txok;
+@@ -2128,16 +2104,12 @@ static void ath_tx_process_buffer(struct
+       if (bf_is_ampdu_not_probing(bf))
+               txq->axq_ampdu_depth--;
+-      spin_unlock_bh(&txq->axq_lock);
+-
+       if (!bf_isampdu(bf)) {
+               ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
+               ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
+       } else
+               ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
+-      spin_lock_bh(&txq->axq_lock);
+-
+       if (sc->sc_flags & SC_OP_TXAGGR)
+               ath_txq_schedule(sc, txq);
+ }
diff --git a/package/mac80211/patches/564-ath9k_track_last_bar.patch b/package/mac80211/patches/564-ath9k_track_last_bar.patch
new file mode 100644 (file)
index 0000000..34a4dd1
--- /dev/null
@@ -0,0 +1,82 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -242,6 +242,7 @@ struct ath_atx_tid {
+       struct ath_atx_ac *ac;
+       unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
+       int buf_pending;
++      int bar_index;
+       u16 seq_start;
+       u16 seq_next;
+       u16 baw_size;
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -206,6 +206,8 @@ static void ath_tx_update_baw(struct ath
+       while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) {
+               INCR(tid->seq_start, IEEE80211_SEQ_MAX);
+               INCR(tid->baw_head, ATH_TID_MAX_BUFS);
++              if (tid->bar_index >= 0)
++                      tid->bar_index--;
+       }
+ }
+@@ -263,6 +265,7 @@ static void ath_tid_drain(struct ath_sof
+       tid->seq_next = tid->seq_start;
+       tid->baw_tail = tid->baw_head;
++      tid->bar_index = -1;
+ }
+ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
+@@ -561,8 +564,12 @@ static void ath_tx_complete_aggr(struct 
+               bf = bf_next;
+       }
+-      if (bar_index >= 0)
++      if (bar_index >= 0) {
++              u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
+               ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
++              if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
++                      tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
++      }
+       /* prepend un-acked frames to the beginning of the pending frame queue */
+       if (!skb_queue_empty(&bf_pending)) {
+@@ -789,8 +796,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+               bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
+               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, seqno)) {
+@@ -798,6 +803,21 @@ static enum ATH_AGGR_STATUS ath_tx_form_
+                       break;
+               }
++              if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) {
++                      struct ath_tx_status ts = {};
++                      struct list_head bf_head;
++
++                      INIT_LIST_HEAD(&bf_head);
++                      list_add(&bf->list, &bf_head);
++                      __skb_unlink(skb, &tid->buf_q);
++                      ath_tx_update_baw(sc, tid, seqno);
++                      ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
++                      continue;
++              }
++
++              if (!bf_first)
++                      bf_first = bf;
++
+               if (!rl) {
+                       aggr_limit = ath_lookup_rate(sc, bf, tid);
+                       rl = 1;
+@@ -1141,6 +1161,7 @@ int ath_tx_aggr_start(struct ath_softc *
+       txtid->state |= AGGR_ADDBA_PROGRESS;
+       txtid->paused = true;
+       *ssn = txtid->seq_start = txtid->seq_next;
++      txtid->bar_index = -1;
+       memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
+       txtid->baw_head = txtid->baw_tail = 0;
diff --git a/package/mac80211/patches/565-ath9k_fix_lockup.patch b/package/mac80211/patches/565-ath9k_fix_lockup.patch
new file mode 100644 (file)
index 0000000..6bc9171
--- /dev/null
@@ -0,0 +1,299 @@
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -104,6 +104,29 @@ static int ath_max_4ms_framelen[4][32] =
+ /* Aggregation logic */
+ /*********************/
++static void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq)
++{
++      spin_lock_bh(&txq->axq_lock);
++}
++
++static void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq)
++{
++      spin_unlock_bh(&txq->axq_lock);
++}
++
++static void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq)
++{
++      struct sk_buff_head q;
++      struct sk_buff *skb;
++
++      __skb_queue_head_init(&q);
++      skb_queue_splice_init(&txq->complete_q, &q);
++      spin_unlock_bh(&txq->axq_lock);
++
++      while ((skb = __skb_dequeue(&q)))
++              ieee80211_tx_status(sc->hw, skb);
++}
++
+ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
+ {
+       struct ath_atx_ac *ac = tid->ac;
+@@ -130,7 +153,7 @@ static void ath_tx_resume_tid(struct ath
+       WARN_ON(!tid->paused);
+-      spin_lock_bh(&txq->axq_lock);
++      ath_txq_lock(sc, txq);
+       tid->paused = false;
+       if (skb_queue_empty(&tid->buf_q))
+@@ -139,7 +162,7 @@ static void ath_tx_resume_tid(struct ath
+       ath_tx_queue_tid(txq, tid);
+       ath_txq_schedule(sc, txq);
+ unlock:
+-      spin_unlock_bh(&txq->axq_lock);
++      ath_txq_unlock_complete(sc, txq);
+ }
+ static struct ath_frame_info *get_frame_info(struct sk_buff *skb)
+@@ -189,8 +212,11 @@ static void ath_tx_flush_tid(struct ath_
+               tid->state &= ~AGGR_CLEANUP;
+       }
+-      if (sendbar)
++      if (sendbar) {
++              ath_txq_unlock(sc, txq);
+               ath_send_bar(tid, tid->seq_start);
++              ath_txq_lock(sc, txq);
++      }
+ }
+ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+@@ -564,13 +590,6 @@ static void ath_tx_complete_aggr(struct 
+               bf = bf_next;
+       }
+-      if (bar_index >= 0) {
+-              u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
+-              ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
+-              if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
+-                      tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
+-      }
+-
+       /* prepend un-acked frames to the beginning of the pending frame queue */
+       if (!skb_queue_empty(&bf_pending)) {
+               if (an->sleeping)
+@@ -585,6 +604,17 @@ static void ath_tx_complete_aggr(struct 
+               }
+       }
++      if (bar_index >= 0) {
++              u16 bar_seq = ATH_BA_INDEX2SEQ(seq_first, bar_index);
++
++              if (BAW_WITHIN(tid->seq_start, tid->baw_size, bar_seq))
++                      tid->bar_index = ATH_BA_INDEX(tid->seq_start, bar_seq);
++
++              ath_txq_unlock(sc, txq);
++              ath_send_bar(tid, ATH_BA_INDEX2SEQ(seq_first, bar_index + 1));
++              ath_txq_lock(sc, txq);
++      }
++
+       if (tid->state & AGGR_CLEANUP)
+               ath_tx_flush_tid(sc, tid);
+@@ -1183,7 +1213,7 @@ void ath_tx_aggr_stop(struct ath_softc *
+               return;
+       }
+-      spin_lock_bh(&txq->axq_lock);
++      ath_txq_lock(sc, txq);
+       txtid->paused = true;
+       /*
+@@ -1198,7 +1228,7 @@ void ath_tx_aggr_stop(struct ath_softc *
+               txtid->state &= ~AGGR_ADDBA_COMPLETE;
+       ath_tx_flush_tid(sc, txtid);
+-      spin_unlock_bh(&txq->axq_lock);
++      ath_txq_unlock_complete(sc, txq);
+ }
+ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
+@@ -1219,7 +1249,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
+               ac = tid->ac;
+               txq = ac->txq;
+-              spin_lock_bh(&txq->axq_lock);
++              ath_txq_lock(sc, txq);
+               buffered = !skb_queue_empty(&tid->buf_q);
+@@ -1231,7 +1261,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
+                       list_del(&ac->list);
+               }
+-              spin_unlock_bh(&txq->axq_lock);
++              ath_txq_unlock(sc, txq);
+               ieee80211_sta_set_buffered(sta, tidno, buffered);
+       }
+@@ -1250,7 +1280,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
+               ac = tid->ac;
+               txq = ac->txq;
+-              spin_lock_bh(&txq->axq_lock);
++              ath_txq_lock(sc, txq);
+               ac->clear_ps_filter = true;
+               if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
+@@ -1258,7 +1288,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
+                       ath_txq_schedule(sc, txq);
+               }
+-              spin_unlock_bh(&txq->axq_lock);
++              ath_txq_unlock_complete(sc, txq);
+       }
+ }
+@@ -1358,6 +1388,7 @@ struct ath_txq *ath_txq_setup(struct ath
+               txq->axq_qnum = axq_qnum;
+               txq->mac80211_qnum = -1;
+               txq->axq_link = NULL;
++              __skb_queue_head_init(&txq->complete_q);
+               INIT_LIST_HEAD(&txq->axq_q);
+               INIT_LIST_HEAD(&txq->axq_acq);
+               spin_lock_init(&txq->axq_lock);
+@@ -1482,7 +1513,8 @@ static void ath_drain_txq_list(struct at
+  */
+ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
+ {
+-      spin_lock_bh(&txq->axq_lock);
++      ath_txq_lock(sc, txq);
++
+       if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+               int idx = txq->txq_tailidx;
+@@ -1503,7 +1535,7 @@ void ath_draintxq(struct ath_softc *sc, 
+       if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx)
+               ath_txq_drain_pending_buffers(sc, txq);
+-      spin_unlock_bh(&txq->axq_lock);
++      ath_txq_unlock_complete(sc, txq);
+ }
+ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
+@@ -1947,7 +1979,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+       q = skb_get_queue_mapping(skb);
+-      spin_lock_bh(&txq->axq_lock);
++      ath_txq_lock(sc, txq);
+       if (txq == sc->tx.txq_map[q] &&
+           ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
+@@ -1957,7 +1989,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+       ath_tx_start_dma(sc, skb, txctl, tid);
+-      spin_unlock_bh(&txq->axq_lock);
++      ath_txq_unlock(sc, txq);
+       return 0;
+ }
+@@ -1969,7 +2001,6 @@ int ath_tx_start(struct ieee80211_hw *hw
+ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+                           int tx_flags, struct ath_txq *txq)
+ {
+-      struct ieee80211_hw *hw = sc->hw;
+       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
+@@ -2013,7 +2044,7 @@ static void ath_tx_complete(struct ath_s
+               }
+       }
+-      ieee80211_tx_status(hw, skb);
++      __skb_queue_tail(&txq->complete_q, skb);
+ }
+ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+@@ -2149,7 +2180,7 @@ static void ath_tx_processq(struct ath_s
+               txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
+               txq->axq_link);
+-      spin_lock_bh(&txq->axq_lock);
++      ath_txq_lock(sc, txq);
+       for (;;) {
+               if (work_pending(&sc->hw_reset_work))
+                       break;
+@@ -2208,7 +2239,7 @@ static void ath_tx_processq(struct ath_s
+               ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
+       }
+-      spin_unlock_bh(&txq->axq_lock);
++      ath_txq_unlock_complete(sc, txq);
+ }
+ static void ath_tx_complete_poll_work(struct work_struct *work)
+@@ -2225,17 +2256,17 @@ static void ath_tx_complete_poll_work(st
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+               if (ATH_TXQ_SETUP(sc, i)) {
+                       txq = &sc->tx.txq[i];
+-                      spin_lock_bh(&txq->axq_lock);
++                      ath_txq_lock(sc, txq);
+                       if (txq->axq_depth) {
+                               if (txq->axq_tx_inprogress) {
+                                       needreset = true;
+-                                      spin_unlock_bh(&txq->axq_lock);
++                                      ath_txq_unlock(sc, txq);
+                                       break;
+                               } else {
+                                       txq->axq_tx_inprogress = true;
+                               }
+                       }
+-                      spin_unlock_bh(&txq->axq_lock);
++                      ath_txq_unlock_complete(sc, txq);
+               }
+       if (needreset) {
+@@ -2293,10 +2324,10 @@ void ath_tx_edma_tasklet(struct ath_soft
+               txq = &sc->tx.txq[ts.qid];
+-              spin_lock_bh(&txq->axq_lock);
++              ath_txq_lock(sc, txq);
+               if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
+-                      spin_unlock_bh(&txq->axq_lock);
++                      ath_txq_unlock(sc, txq);
+                       return;
+               }
+@@ -2322,7 +2353,7 @@ void ath_tx_edma_tasklet(struct ath_soft
+               }
+               ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
+-              spin_unlock_bh(&txq->axq_lock);
++              ath_txq_unlock_complete(sc, txq);
+       }
+ }
+@@ -2460,7 +2491,7 @@ void ath_tx_node_cleanup(struct ath_soft
+               ac = tid->ac;
+               txq = ac->txq;
+-              spin_lock_bh(&txq->axq_lock);
++              ath_txq_lock(sc, txq);
+               if (tid->sched) {
+                       list_del(&tid->list);
+@@ -2476,6 +2507,6 @@ void ath_tx_node_cleanup(struct ath_soft
+               tid->state &= ~AGGR_ADDBA_COMPLETE;
+               tid->state &= ~AGGR_CLEANUP;
+-              spin_unlock_bh(&txq->axq_lock);
++              ath_txq_unlock(sc, txq);
+       }
+ }
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -196,6 +196,7 @@ struct ath_txq {
+       u8 txq_headidx;
+       u8 txq_tailidx;
+       int pending_frames;
++      struct sk_buff_head complete_q;
+ };
+ struct ath_atx_ac {
diff --git a/package/mac80211/patches/570-ath9k_mci_static.patch b/package/mac80211/patches/570-ath9k_mci_static.patch
new file mode 100644 (file)
index 0000000..9a337c0
--- /dev/null
@@ -0,0 +1,37 @@
+--- a/drivers/net/wireless/ath/ath9k/mci.c
++++ b/drivers/net/wireless/ath/ath9k/mci.c
+@@ -234,8 +234,8 @@ static void ath_mci_cal_msg(struct ath_s
+       }
+ }
+-void ath_mci_process_profile(struct ath_softc *sc,
+-                           struct ath_mci_profile_info *info)
++static void ath_mci_process_profile(struct ath_softc *sc,
++                                  struct ath_mci_profile_info *info)
+ {
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_btcoex *btcoex = &sc->btcoex;
+@@ -261,8 +261,8 @@ void ath_mci_process_profile(struct ath_
+       ath_mci_update_scheme(sc);
+ }
+-void ath_mci_process_status(struct ath_softc *sc,
+-                          struct ath_mci_profile_status *status)
++static void ath_mci_process_status(struct ath_softc *sc,
++                                 struct ath_mci_profile_status *status)
+ {
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_btcoex *btcoex = &sc->btcoex;
+--- a/drivers/net/wireless/ath/ath9k/mci.h
++++ b/drivers/net/wireless/ath/ath9k/mci.h
+@@ -128,10 +128,6 @@ struct ath_mci_coex {
+ };
+ void ath_mci_flush_profile(struct ath_mci_profile *mci);
+-void ath_mci_process_profile(struct ath_softc *sc,
+-                           struct ath_mci_profile_info *info);
+-void ath_mci_process_status(struct ath_softc *sc,
+-                          struct ath_mci_profile_status *status);
+ int ath_mci_setup(struct ath_softc *sc);
+ void ath_mci_cleanup(struct ath_softc *sc);
+ void ath_mci_intr(struct ath_softc *sc);
diff --git a/package/mac80211/patches/571-ath9k_btcoex_optional.patch b/package/mac80211/patches/571-ath9k_btcoex_optional.patch
new file mode 100644 (file)
index 0000000..c73ad1a
--- /dev/null
@@ -0,0 +1,544 @@
+--- a/drivers/net/wireless/ath/ath9k/Kconfig
++++ b/drivers/net/wireless/ath/ath9k/Kconfig
+@@ -59,6 +59,14 @@ config ATH9K_RATE_CONTROL
+         Say Y, if you want to use the ath9k specific rate control
+         module instead of minstrel_ht.
++config ATH9K_BTCOEX_SUPPORT
++      bool "Atheros ath9k bluetooth coexistence support"
++      depends on ATH9K
++      default y
++      ---help---
++        Say Y, if you want to use the ath9k radios together with
++        Bluetooth modules in the same system.
++
+ config ATH9K_HTC
+        tristate "Atheros HTC based wireless cards support"
+        depends on USB && MAC80211
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -210,7 +210,11 @@ enum ath9k_hw_caps {
+       ATH9K_HW_CAP_5GHZ                       = BIT(14),
+       ATH9K_HW_CAP_APM                        = BIT(15),
+       ATH9K_HW_CAP_RTT                        = BIT(16),
++#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+       ATH9K_HW_CAP_MCI                        = BIT(17),
++#else
++      ATH9K_HW_CAP_MCI                        = 0,
++#endif
+ };
+ struct ath9k_hw_capabilities {
+@@ -1229,6 +1233,16 @@ void ar9003_mci_sync_bt_state(struct ath
+ void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
+                             u32 *rx_msg_intr);
++#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
++static inline enum ath_btcoex_scheme
++ath9k_hw_get_btcoex_scheme(struct ath_hw *ah)
++{
++      return ah->btcoex_hw.scheme;
++}
++#else
++#define ath9k_hw_get_btcoex_scheme(...) ATH_BTCOEX_CFG_NONE
++#endif
++
+ #define ATH9K_CLOCK_RATE_CCK          22
+ #define ATH9K_CLOCK_RATE_5GHZ_OFDM    40
+ #define ATH9K_CLOCK_RATE_2GHZ_OFDM    44
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -411,7 +411,7 @@ static int ath9k_init_btcoex(struct ath_
+       struct ath_hw *ah = sc->sc_ah;
+       int r;
+-      switch (sc->sc_ah->btcoex_hw.scheme) {
++      switch (ath9k_hw_get_btcoex_scheme(sc->sc_ah)) {
+       case ATH_BTCOEX_CFG_NONE:
+               break;
+       case ATH_BTCOEX_CFG_2WIRE:
+@@ -866,10 +866,10 @@ static void ath9k_deinit_softc(struct at
+               kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
+         if ((sc->btcoex.no_stomp_timer) &&
+-          sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
++          ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE)
+               ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer);
+-      if (sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_MCI)
++      if (ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_MCI)
+               ath_mci_cleanup(sc);
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -121,7 +121,7 @@ static void ath_pci_aspm_init(struct ath
+       if (!parent)
+               return;
+-      if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) {
++      if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
+               /* Bluetooth coexistance requires disabling ASPM. */
+               pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
+               aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -610,7 +610,7 @@ static void ath9k_init_btcoex(struct ath
+ {
+       int qnum;
+-      switch (priv->ah->btcoex_hw.scheme) {
++      switch (ath9k_hw_get_btcoex_scheme(priv->ah)) {
+       case ATH_BTCOEX_CFG_NONE:
+               break;
+       case ATH_BTCOEX_CFG_3WIRE:
+@@ -704,7 +704,8 @@ static int ath9k_init_priv(struct ath9k_
+       if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
+               ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
+-              ath9k_init_btcoex(priv);
++              if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE)
++                      ath9k_init_btcoex(priv);
+       }
+       return 0;
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+@@ -958,7 +958,7 @@ static int ath9k_htc_start(struct ieee80
+       mod_timer(&priv->tx.cleanup_timer,
+                 jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));
+-      if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) {
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) {
+               ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+                                          AR_STOMP_LOW_WLAN_WGHT);
+               ath9k_hw_btcoex_enable(ah);
+@@ -1010,7 +1010,8 @@ static void ath9k_htc_stop(struct ieee80
+       mutex_lock(&priv->mutex);
+-      if (ah->btcoex_hw.enabled) {
++      if (ah->btcoex_hw.enabled &&
++          ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
+               ath9k_hw_btcoex_disable(ah);
+               if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
+                       ath_htc_cancel_btcoex_work(priv);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -742,11 +742,11 @@ void ath9k_tasklet(unsigned long data)
+                       ath_tx_tasklet(sc);
+       }
+-      if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
+               if (status & ATH9K_INT_GENTIMER)
+                       ath_gen_timer_isr(sc->sc_ah);
+-      if (status & ATH9K_INT_MCI)
++      if ((status & ATH9K_INT_MCI) && ATH9K_HW_CAP_MCI)
+               ath_mci_intr(sc);
+ out:
+@@ -1083,14 +1083,14 @@ static int ath9k_start(struct ieee80211_
+       spin_unlock_bh(&sc->sc_pcu_lock);
+-      if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
++      if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
+           !ah->btcoex_hw.enabled) {
+               if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
+                       ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+                                                  AR_STOMP_LOW_WLAN_WGHT);
+               ath9k_hw_btcoex_enable(ah);
+-              if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
++              if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
+                       ath9k_btcoex_timer_resume(sc);
+       }
+@@ -1194,9 +1194,10 @@ static void ath9k_stop(struct ieee80211_
+       /* Ensure HW is awake when we try to shut it down. */
+       ath9k_ps_wakeup(sc);
+-      if (ah->btcoex_hw.enabled) {
++      if (ah->btcoex_hw.enabled &&
++          ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
+               ath9k_hw_btcoex_disable(ah);
+-              if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
++              if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
+                       ath9k_btcoex_timer_pause(sc);
+               ath_mci_flush_profile(&sc->btcoex.mci);
+       }
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -253,6 +253,9 @@ int ath_init_btcoex_timer(struct ath_sof
+ {
+       struct ath_btcoex *btcoex = &sc->btcoex;
++      if (ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_NONE)
++              return 0;
++
+       btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
+       btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
+               btcoex->btcoex_period / 100;
+@@ -286,6 +289,9 @@ void ath9k_btcoex_timer_resume(struct at
+       ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
+               "Starting btcoex timers\n");
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       /* make sure duty cycle timer is also stopped when resuming */
+       if (btcoex->hw_timer_enabled)
+               ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+@@ -306,6 +312,9 @@ void ath9k_btcoex_timer_pause(struct ath
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_hw *ah = sc->sc_ah;
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       del_timer_sync(&btcoex->period_timer);
+       if (btcoex->hw_timer_enabled)
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1929,7 +1929,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ #endif
+       }
+-      if (ah->btcoex_hw.enabled)
++      if (ah->btcoex_hw.enabled &&
++          ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE)
+               ath9k_hw_btcoex_enable(ah);
+       if (mci && mci_hw->ready) {
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+@@ -116,6 +116,9 @@ void ath_htc_init_btcoex_work(struct ath
+ {
+       struct ath_btcoex *btcoex = &priv->btcoex;
++      if (ath9k_hw_get_btcoex_scheme(priv->ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
+       btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
+               btcoex->btcoex_period / 100;
+@@ -134,6 +137,9 @@ void ath_htc_resume_btcoex_work(struct a
+       struct ath_btcoex *btcoex = &priv->btcoex;
+       struct ath_hw *ah = priv->ah;
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, "Starting btcoex work\n");
+       btcoex->bt_priority_cnt = 0;
+@@ -148,6 +154,9 @@ void ath_htc_resume_btcoex_work(struct a
+  */
+ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
+ {
++      if (ath9k_hw_get_btcoex_scheme(priv->ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       cancel_delayed_work_sync(&priv->coex_period_work);
+       cancel_delayed_work_sync(&priv->duty_cycle_work);
+ }
+--- a/drivers/net/wireless/ath/ath9k/btcoex.c
++++ b/drivers/net/wireless/ath/ath9k/btcoex.c
+@@ -68,6 +68,9 @@ void ath9k_hw_init_btcoex_hw(struct ath_
+       u32 i, idx;
+       bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               rxclear_polarity = !ath_bt_config.bt_rxclear_polarity;
+@@ -99,6 +102,9 @@ void ath9k_hw_btcoex_init_2wire(struct a
+ {
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       /* connect bt_active to baseband */
+       REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+                   (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
+@@ -121,6 +127,9 @@ void ath9k_hw_btcoex_init_3wire(struct a
+ {
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       /* btcoex 3-wire */
+       REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+                       (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
+@@ -147,6 +156,9 @@ static void ath9k_hw_btcoex_enable_2wire
+ {
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       /* Configure the desired GPIO port for TX_FRAME output */
+       ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
+                           AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
+@@ -158,6 +170,9 @@ void ath9k_hw_btcoex_set_weight(struct a
+ {
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       btcoex_hw->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
+                                    SM(wlan_weight, AR_BTCOEX_WL_WGHT);
+ }
+@@ -219,9 +234,9 @@ void ath9k_hw_btcoex_enable(struct ath_h
+ {
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+-      switch (btcoex_hw->scheme) {
++      switch (ath9k_hw_get_btcoex_scheme(ah)) {
+       case ATH_BTCOEX_CFG_NONE:
+-              break;
++              return;
+       case ATH_BTCOEX_CFG_2WIRE:
+               ath9k_hw_btcoex_enable_2wire(ah);
+               break;
+@@ -246,6 +261,9 @@ void ath9k_hw_btcoex_disable(struct ath_
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+       int i;
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       btcoex_hw->enabled = false;
+       if (btcoex_hw->scheme == ATH_BTCOEX_CFG_MCI) {
+               ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
+@@ -294,6 +312,9 @@ static void ar9003_btcoex_bt_stomp(struc
+ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
+                             enum ath_stomp_type stomp_type)
+ {
++      if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
++              return;
++
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               ar9003_btcoex_bt_stomp(ah, stomp_type);
+               return;
+--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+@@ -85,6 +85,9 @@ void ar9003_mci_remote_reset(struct ath_
+ {
+       u32 payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00};
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16,
+                               wait_done, false);
+       udelay(5);
+@@ -94,6 +97,9 @@ void ar9003_mci_send_lna_transfer(struct
+ {
+       u32 payload = 0x00000000;
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       ar9003_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1,
+                               wait_done, false);
+ }
+@@ -107,6 +113,9 @@ static void ar9003_mci_send_req_wake(str
+ void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done)
+ {
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       ar9003_mci_send_message(ah, MCI_SYS_WAKING, MCI_FLAG_DISABLE_TIMESTAMP,
+                               NULL, 0, wait_done, false);
+ }
+@@ -221,6 +230,9 @@ void ar9003_mci_send_coex_halt_bt_gpm(st
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 payload[4] = {0, 0, 0, 0};
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       ath_dbg(common, ATH_DBG_MCI, "MCI Send Coex %s BT GPM.\n",
+               (halt) ? "halt" : "unhalt");
+@@ -381,12 +393,17 @@ static void ar9003_mci_prep_interface(st
+ void ar9003_mci_disable_interrupt(struct ath_hw *ah)
+ {
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
+ }
+ void ar9003_mci_enable_interrupt(struct ath_hw *ah)
+ {
++      if (!ATH9K_HW_CAP_MCI)
++              return;
+       REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT);
+       REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
+@@ -397,6 +414,9 @@ bool ar9003_mci_check_int(struct ath_hw 
+ {
+       u32 intr;
++      if (!ATH9K_HW_CAP_MCI)
++              return false;
++
+       intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
+       return ((intr & ints) == ints);
+ }
+@@ -405,6 +425,10 @@ void ar9003_mci_get_interrupt(struct ath
+                             u32 *rx_msg_intr)
+ {
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
++
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       *raw_intr = mci->raw_intr;
+       *rx_msg_intr = mci->rx_msg_intr;
+@@ -418,6 +442,9 @@ void ar9003_mci_2g5g_changed(struct ath_
+ {
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       if (!mci->update_2g5g &&
+           (mci->is_2g != is_2g))
+               mci->update_2g5g = true;
+@@ -531,6 +558,9 @@ void ar9003_mci_reset(struct ath_hw *ah,
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 regval, thresh;
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       ath_dbg(common, ATH_DBG_MCI, "MCI full_sleep = %d, is_2g = %d\n",
+               is_full_sleep, is_2g);
+@@ -661,6 +691,9 @@ void ar9003_mci_mute_bt(struct ath_hw *a
+ {
+       struct ath_common *common = ath9k_hw_common(ah);
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       /* disable all MCI messages */
+       REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
+       REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);
+@@ -693,6 +726,9 @@ void ar9003_mci_sync_bt_state(struct ath
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       u32 cur_bt_state;
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL);
+       if (mci->bt_state != cur_bt_state) {
+@@ -857,6 +893,9 @@ void ar9003_mci_2g5g_switch(struct ath_h
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       if (mci->update_2g5g) {
+               if (mci->is_2g) {
+@@ -908,6 +947,9 @@ bool ar9003_mci_send_message(struct ath_
+       u32 saved_mci_int_en;
+       int i;
++      if (!ATH9K_HW_CAP_MCI)
++              return false;
++
+       saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);
+       regval = REG_READ(ah, AR_BTCOEX_CTRL);
+@@ -973,6 +1015,9 @@ void ar9003_mci_setup(struct ath_hw *ah,
+       struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
+       void *sched_buf = (void *)((char *) gpm_buf + (sched_addr - gpm_addr));
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       mci->gpm_addr = gpm_addr;
+       mci->gpm_buf = gpm_buf;
+       mci->gpm_len = len;
+@@ -987,6 +1032,9 @@ void ar9003_mci_cleanup(struct ath_hw *a
+ {
+       struct ath_common *common = ath9k_hw_common(ah);
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       /* Turn off MCI and Jupiter mode. */
+       REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);
+       ath_dbg(common, ATH_DBG_MCI, "MCI ar9003_mci_cleanup\n");
+@@ -1056,6 +1104,9 @@ u32 ar9003_mci_wait_for_gpm(struct ath_h
+       u8 recv_type = 0, recv_opcode = 0;
+       bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE);
++      if (!ATH9K_HW_CAP_MCI)
++              return 0;
++
+       more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE;
+       while (time_out > 0) {
+@@ -1188,6 +1239,9 @@ u32 ar9003_mci_state(struct ath_hw *ah, 
+       u32 value = 0, more_gpm = 0, gpm_ptr;
+       u8 query_type;
++      if (!ATH9K_HW_CAP_MCI)
++              return 0;
++
+       switch (state_type) {
+       case MCI_STATE_ENABLE:
+               if (mci->ready) {
+--- a/drivers/net/wireless/ath/ath9k/mci.c
++++ b/drivers/net/wireless/ath/ath9k/mci.c
+@@ -425,6 +425,9 @@ int ath_mci_setup(struct ath_softc *sc)
+       struct ath_mci_coex *mci = &sc->mci_coex;
+       int error = 0;
++      if (!ATH9K_HW_CAP_MCI)
++              return 0;
++
+       mci->sched_buf.bf_len = ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE;
+       if (ath_mci_buf_alloc(sc, &mci->sched_buf)) {
+@@ -458,6 +461,9 @@ void ath_mci_cleanup(struct ath_softc *s
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_mci_coex *mci = &sc->mci_coex;
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       /*
+        * both schedule and gpm buffers will be released
+        */
+@@ -476,6 +482,9 @@ void ath_mci_intr(struct ath_softc *sc)
+       u32 more_data = MCI_GPM_MORE;
+       bool skip_gpm = false;
++      if (!ATH9K_HW_CAP_MCI)
++              return;
++
+       ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg);
+       if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) == 0) {
diff --git a/package/mac80211/patches/580-ath9k_extra_leds.patch b/package/mac80211/patches/580-ath9k_extra_leds.patch
new file mode 100644 (file)
index 0000000..a079607
--- /dev/null
@@ -0,0 +1,258 @@
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -474,6 +474,9 @@ void ath9k_btcoex_timer_pause(struct ath
+ #ifdef CONFIG_MAC80211_LEDS
+ void ath_init_leds(struct ath_softc *sc);
+ void ath_deinit_leds(struct ath_softc *sc);
++int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
++                        const char *trigger, bool active_low);
++
+ #else
+ static inline void ath_init_leds(struct ath_softc *sc)
+ {
+@@ -594,6 +597,13 @@ struct ath9k_vif_iter_data {
+       int nothers;   /* number of vifs not specified above. */
+ };
++struct ath_led {
++      struct list_head list;
++      struct ath_softc *sc;
++      const struct gpio_led *gpio;
++      struct led_classdev cdev;
++};
++
+ struct ath_softc {
+       struct ieee80211_hw *hw;
+       struct device *dev;
+@@ -637,9 +647,8 @@ struct ath_softc {
+       struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
+ #ifdef CONFIG_MAC80211_LEDS
+-      bool led_registered;
+-      char led_name[32];
+-      struct led_classdev led_cdev;
++      const char *led_default_trigger;
++      struct list_head leds;
+ #endif
+       struct ath9k_hw_cal_data caldata;
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -24,22 +24,89 @@
+ static void ath_led_brightness(struct led_classdev *led_cdev,
+                              enum led_brightness brightness)
+ {
+-      struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
+-      ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF));
++      struct ath_led *led = container_of(led_cdev, struct ath_led, cdev);
++      struct ath_softc *sc = led->sc;
++
++      ath9k_ps_wakeup(sc);
++      ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio,
++                        (brightness != LED_OFF) ^ led->gpio->active_low);
++      ath9k_ps_restore(sc);
++}
++
++static int ath_add_led(struct ath_softc *sc, struct ath_led *led)
++{
++      const struct gpio_led *gpio = led->gpio;
++      int ret;
++
++      led->cdev.name = gpio->name;
++      led->cdev.default_trigger = gpio->default_trigger;
++      led->cdev.brightness_set = ath_led_brightness;
++
++      ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev);
++      if (ret < 0)
++              return ret;
++
++      led->sc = sc;
++      list_add(&led->list, &sc->leds);
++
++      /* Configure gpio for output */
++      ath9k_hw_cfg_output(sc->sc_ah, gpio->gpio,
++                          AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++
++      /* LED off */
++      ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
++
++      return 0;
++}
++
++int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name,
++                      const char *trigger, bool active_low)
++{
++      struct ath_led *led;
++      struct gpio_led *gpio;
++      char *_name;
++      int ret;
++
++      led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1,
++                    GFP_KERNEL);
++      if (!led)
++              return -ENOMEM;
++
++      led->gpio = gpio = (struct gpio_led *) (led + 1);
++      _name = (char *) (led->gpio + 1);
++
++      strcpy(_name, name);
++      gpio->name = _name;
++      gpio->gpio = gpio_num;
++      gpio->active_low = active_low;
++      gpio->default_trigger = trigger;
++
++      ret = ath_add_led(sc, led);
++      if (unlikely(ret < 0))
++              kfree(led);
++
++      return ret;
+ }
+ void ath_deinit_leds(struct ath_softc *sc)
+ {
+-      if (!sc->led_registered)
+-              return;
++      struct ath_led *led;
+-      ath_led_brightness(&sc->led_cdev, LED_OFF);
+-      led_classdev_unregister(&sc->led_cdev);
++      while (!list_empty(&sc->leds)) {
++              led = list_first_entry(&sc->leds, struct ath_led, list);
++              list_del(&led->list);
++              ath_led_brightness(&led->cdev, LED_OFF);
++              led_classdev_unregister(&led->cdev);
++              kfree(led);
++      }
+ }
+ void ath_init_leds(struct ath_softc *sc)
+ {
+-      int ret;
++      char led_name[32];
++      const char *trigger;
++
++      INIT_LIST_HEAD(&sc->leds);
+       if (AR_SREV_9100(sc->sc_ah))
+               return;
+@@ -57,26 +124,15 @@ void ath_init_leds(struct ath_softc *sc)
+                       sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
+       }
+-      /* Configure gpio 1 for output */
+-      ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
+-                          AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+-      /* LED off, active low */
+-      ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+-
+-      if (!led_blink)
+-              sc->led_cdev.default_trigger =
+-                      ieee80211_get_radio_led_name(sc->hw);
+-
+-      snprintf(sc->led_name, sizeof(sc->led_name),
+-              "ath9k-%s", wiphy_name(sc->hw->wiphy));
+-      sc->led_cdev.name = sc->led_name;
+-      sc->led_cdev.brightness_set = ath_led_brightness;
++      snprintf(led_name, sizeof(led_name), "ath9k-%s",
++               wiphy_name(sc->hw->wiphy));
+-      ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
+-      if (ret < 0)
+-              return;
++      if (led_blink)
++              trigger = sc->led_default_trigger;
++      else
++              trigger = ieee80211_get_radio_led_name(sc->hw);
+-      sc->led_registered = true;
++      ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, 1);
+ }
+ #endif
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -803,7 +803,7 @@ int ath9k_init_device(u16 devid, struct 
+ #ifdef CONFIG_MAC80211_LEDS
+       /* must be initialized before ieee80211_register_hw */
+-      sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
++      sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
+               IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
+               ARRAY_SIZE(ath9k_tpt_blink));
+ #endif
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1304,6 +1304,61 @@ static const struct file_operations fops
+       .llseek = default_llseek,
+ };
++#ifdef CONFIG_MAC80211_LEDS
++
++static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf,
++                                 size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      char buf[32], *str, *name, *c;
++      ssize_t len;
++      unsigned int gpio;
++      bool active_low = false;
++
++      len = min(count, sizeof(buf) - 1);
++      if (copy_from_user(buf, ubuf, len))
++              return -EFAULT;
++
++      buf[len] = '\0';
++      name = strchr(buf, ',');
++      if (!name)
++              return -EINVAL;
++
++      *(name++) = 0;
++      if (!*name)
++              return -EINVAL;
++
++      c = strchr(name, '\n');
++      if (c)
++              *c = 0;
++
++      str = buf;
++      if (*str == '!') {
++              str++;
++              active_low = true;
++      }
++
++      if (kstrtouint(str, 0, &gpio) < 0)
++              return -EINVAL;
++
++      if (gpio >= sc->sc_ah->caps.num_gpio_pins)
++              return -EINVAL;
++
++      if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0)
++              return -EINVAL;
++
++      return count;
++}
++
++static const struct file_operations fops_gpio_led = {
++      .write = write_file_gpio_led,
++      .open = ath9k_debugfs_open,
++      .owner = THIS_MODULE,
++      .llseek = default_llseek,
++};
++
++#endif
++
+ void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
+ {
+ #define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c)
+@@ -1725,6 +1780,11 @@ int ath9k_init_debug(struct ath_hw *ah)
+       debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
+                           &fops_samps);
++#ifdef CONFIG_MAC80211_LEDS
++      debugfs_create_file("gpio_led", S_IWUSR,
++                         sc->debug.debugfs_phy, sc, &fops_gpio_led);
++#endif
++
+       debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
+                          sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
diff --git a/package/mac80211/patches/581-ath9k_extra_platform_leds.patch b/package/mac80211/patches/581-ath9k_extra_platform_leds.patch
new file mode 100644 (file)
index 0000000..3834d43
--- /dev/null
@@ -0,0 +1,71 @@
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -32,6 +32,9 @@ struct ath9k_platform_data {
+       bool is_clk_25mhz;
+       int (*get_mac_revision)(void);
+       int (*external_reset)(void);
++
++      int num_leds;
++      const struct gpio_led *leds;
+ };
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -14,6 +14,7 @@
+  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+  */
++#include <linux/ath9k_platform.h>
+ #include "ath9k.h"
+ /********************************/
+@@ -88,6 +89,24 @@ int ath_create_gpio_led(struct ath_softc
+       return ret;
+ }
++static int ath_create_platform_led(struct ath_softc *sc,
++                                 const struct gpio_led *gpio)
++{
++      struct ath_led *led;
++      int ret;
++
++      led = kzalloc(sizeof(*led), GFP_KERNEL);
++      if (!led)
++              return -ENOMEM;
++
++      led->gpio = gpio;
++      ret = ath_add_led(sc, led);
++      if (ret < 0)
++              kfree(led);
++
++      return ret;
++}
++
+ void ath_deinit_leds(struct ath_softc *sc)
+ {
+       struct ath_led *led;
+@@ -103,8 +122,10 @@ void ath_deinit_leds(struct ath_softc *s
+ void ath_init_leds(struct ath_softc *sc)
+ {
++      struct ath9k_platform_data *pdata = sc->dev->platform_data;
+       char led_name[32];
+       const char *trigger;
++      int i;
+       INIT_LIST_HEAD(&sc->leds);
+@@ -133,6 +154,12 @@ void ath_init_leds(struct ath_softc *sc)
+               trigger = ieee80211_get_radio_led_name(sc->hw);
+       ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, 1);
++
++      if (!pdata)
++              return;
++
++      for (i = 0; i < pdata->num_leds; i++)
++              ath_create_platform_led(sc, &pdata->leds[i]);
+ }
+ #endif
index 25709b8..3d2b9b8 100644 (file)
@@ -1,6 +1,6 @@
 --- a/config.mk
 +++ b/config.mk
-@@ -567,6 +567,7 @@ CONFIG_RT2X00=y
+@@ -606,6 +606,7 @@ CONFIG_RT2X00=y
  CONFIG_RT2X00_LIB=m
  CONFIG_RT2800_LIB=m
  CONFIG_RT2X00_LIB_FIRMWARE=y
diff --git a/package/mac80211/patches/850-p54spi-lock-fix.patch b/package/mac80211/patches/850-p54spi-lock-fix.patch
deleted file mode 100644 (file)
index d19ba61..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/drivers/net/wireless/p54/p54spi.c
-+++ b/drivers/net/wireless/p54/p54spi.c
-@@ -656,6 +656,7 @@ static int __devinit p54spi_probe(struct
-       init_completion(&priv->fw_comp);
-       INIT_LIST_HEAD(&priv->tx_pending);
-       mutex_init(&priv->mutex);
-+      spin_lock_init(&priv->tx_lock);
-       SET_IEEE80211_DEV(hw, &spi->dev);
-       priv->common.open = p54spi_op_start;
-       priv->common.stop = p54spi_op_stop;
diff --git a/package/mac80211/patches/851-p54spi-mutex-fix.patch b/package/mac80211/patches/851-p54spi-mutex-fix.patch
deleted file mode 100644 (file)
index e974e9d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
---- a/drivers/net/wireless/p54/p54spi.c
-+++ b/drivers/net/wireless/p54/p54spi.c
-@@ -581,11 +581,7 @@ static void p54spi_op_stop(struct ieee80
-       struct p54s_priv *priv = dev->priv;
-       unsigned long flags;
--      if (mutex_lock_interruptible(&priv->mutex)) {
--              /* FIXME: how to handle this error? */
--              return;
--      }
--
-+      mutex_lock(&priv->mutex);
-       WARN_ON(priv->fw_state != FW_STATE_READY);
-       cancel_work_sync(&priv->work);
diff --git a/package/mac80211/patches/852-p54spi-cancel-workqueue-fix.patch b/package/mac80211/patches/852-p54spi-cancel-workqueue-fix.patch
deleted file mode 100644 (file)
index f8d36ca..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
---- a/drivers/net/wireless/p54/p54spi.c
-+++ b/drivers/net/wireless/p54/p54spi.c
-@@ -584,8 +584,6 @@ static void p54spi_op_stop(struct ieee80
-       mutex_lock(&priv->mutex);
-       WARN_ON(priv->fw_state != FW_STATE_READY);
--      cancel_work_sync(&priv->work);
--
-       p54spi_power_off(priv);
-       spin_lock_irqsave(&priv->tx_lock, flags);
-       INIT_LIST_HEAD(&priv->tx_pending);
-@@ -593,6 +591,8 @@ static void p54spi_op_stop(struct ieee80
-       priv->fw_state = FW_STATE_OFF;
-       mutex_unlock(&priv->mutex);
-+
-+      cancel_work_sync(&priv->work);
- }
- static int __devinit p54spi_probe(struct spi_device *spi)
diff --git a/package/mac80211/patches/910-fix-reversed-warn-on-workqueue.patch b/package/mac80211/patches/910-fix-reversed-warn-on-workqueue.patch
deleted file mode 100644 (file)
index b598574..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/compat/compat-2.6.36.c
-+++ b/compat/compat-2.6.36.c
-@@ -101,7 +101,7 @@ EXPORT_SYMBOL_GPL(system_nrt_wq);
- void compat_system_workqueue_create()
- {
-       system_nrt_wq = create_singlethread_workqueue("events_nrt");
--      WARN_ON(system_nrt_wq);
-+      WARN_ON(!system_nrt_wq);
- }
- void compat_system_workqueue_destroy()
index 020387a..b37d23d 100644 (file)
@@ -28,6 +28,13 @@ struct ath9k_platform_data {
        int led_pin;
        u32 gpio_mask;
        u32 gpio_val;
+
+       bool is_clk_25mhz;
+       int (*get_mac_revision)(void);
+       int (*external_reset)(void);
+
+       int num_leds;
+       const struct gpio_led *leds;
 };
 
 #endif /* _LINUX_ATH9K_PLATFORM_H */