AA: mac80211: backport package from trunk r39886
authorFelix Fietkau <nbd@openwrt.org>
Fri, 14 Mar 2014 10:53:42 +0000 (10:53 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Fri, 14 Mar 2014 10:53:42 +0000 (10:53 +0000)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
SVN-Revision: 39928

92 files changed:
package/mac80211/Makefile
package/mac80211/files/lib/wifi/mac80211.sh
package/mac80211/files/regdb.txt
package/mac80211/patches/001-fix_build.patch
package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch [new file with mode: 0644]
package/mac80211/patches/020-disable_tty_set_termios.patch
package/mac80211/patches/030-rt2x00_options.patch
package/mac80211/patches/060-no_local_ssb_bcma.patch
package/mac80211/patches/100-revert_aes_ccm_port.patch [new file with mode: 0644]
package/mac80211/patches/150-disable_addr_notifier.patch
package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch
package/mac80211/patches/300-pending_work.patch
package/mac80211/patches/310-ap_scan.patch
package/mac80211/patches/400-ath_move_debug_code.patch
package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch
package/mac80211/patches/403-ath_regd_optional.patch
package/mac80211/patches/404-world_regd_fixup.patch
package/mac80211/patches/405-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/440-ath5k_channel_bw_debugfs.patch
package/mac80211/patches/500-ath9k_eeprom_debugfs.patch
package/mac80211/patches/501-ath9k-eeprom_endianess.patch
package/mac80211/patches/502-ath9k_ahb_init.patch
package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch
package/mac80211/patches/511-ath9k_reduce_rxbuf.patch
package/mac80211/patches/512-ath9k_channelbw_debugfs.patch
package/mac80211/patches/513-ath9k_add_pci_ids.patch [new file with mode: 0644]
package/mac80211/patches/520-mac80211_cur_txpower.patch
package/mac80211/patches/521-ath9k_cur_txpower.patch
package/mac80211/patches/522-ath9k_per_chain_signal_strength.patch [deleted file]
package/mac80211/patches/522-mac80211_configure_antenna_gain.patch [new file with mode: 0644]
package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch [new file with mode: 0644]
package/mac80211/patches/523-mac80211_configure_antenna_gain.patch [deleted file]
package/mac80211/patches/524-ath9k_use_configured_antenna_gain.patch [deleted file]
package/mac80211/patches/530-ath9k_extra_leds.patch
package/mac80211/patches/531-ath9k_extra_platform_leds.patch
package/mac80211/patches/540-ath9k_reduce_ani_interval.patch [new file with mode: 0644]
package/mac80211/patches/541-ath9k_optimize_interrupt_mitigation.patch [deleted file]
package/mac80211/patches/541-ath9k_rx_dma_stop_check.patch [new file with mode: 0644]
package/mac80211/patches/542-ath9k_debugfs_diag.patch [new file with mode: 0644]
package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch [new file with mode: 0644]
package/mac80211/patches/550-ath9k_entropy_from_adc.patch [new file with mode: 0644]
package/mac80211/patches/550-ath9k_reduce_ani_interval.patch [deleted file]
package/mac80211/patches/551-ath9k_p2p_ifcomb.patch [new file with mode: 0644]
package/mac80211/patches/552-ath9k_p2p_ps_support.patch [new file with mode: 0644]
package/mac80211/patches/552-ath9k_rx_dma_stop_check.patch [deleted file]
package/mac80211/patches/553-ath9k_debugfs_diag.patch [deleted file]
package/mac80211/patches/554-ath9k_ani_mrc_fix.patch [deleted file]
package/mac80211/patches/555-ath9k-allow-to-disable-bands-via-platform-data.patch [deleted file]
package/mac80211/patches/556-ath9k_fix_rx_race.patch [deleted file]
package/mac80211/patches/560-ath9k_tx_queueing_rework.patch [deleted file]
package/mac80211/patches/561-ath9k-ar933x-usb-hang-workaround.patch [deleted file]
package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch [new file with mode: 0644]
package/mac80211/patches/601-rt2x00-set_pci_mwi.patch
package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch
package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch
package/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch [new file with mode: 0644]
package/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch [new file with mode: 0644]
package/mac80211/patches/605-rt2x00-pci-eeprom.patch [deleted file]
package/mac80211/patches/606-rt2x00_no_realign.patch
package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch
package/mac80211/patches/608-add_platform_data_mac_addr.patch
package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch
package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch
package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch
package/mac80211/patches/614-rt2x00-of_load_eeprom_filename.patch [deleted file]
package/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch [new file with mode: 0644]
package/mac80211/patches/616-rt2x00-support-rt5350.patch
package/mac80211/patches/617-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch [deleted file]
package/mac80211/patches/618-rt2x00-msi-fix.patch [deleted file]
package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch [new file with mode: 0644]
package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch [new file with mode: 0644]
package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch
package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch
package/mac80211/patches/750-rtlwifi-Align-private-space-in-rtl_priv-struct.patch [deleted file]
package/mac80211/patches/800-b43-gpio-mask-module-option.patch
package/mac80211/patches/810-b43_no_pio.patch
package/mac80211/patches/820-b43-add-antenna-control.patch
package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch
package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch
package/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch [new file with mode: 0644]
package/mac80211/patches/851-brcmsmac-remove-extra-regulation-restriction.patch [deleted file]
package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch [new file with mode: 0644]
package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch [new file with mode: 0644]
package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch [new file with mode: 0644]
package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch [new file with mode: 0644]
package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch [new file with mode: 0644]
package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch [new file with mode: 0644]
package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch [new file with mode: 0644]
package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch [new file with mode: 0644]
package/mac80211/patches/a00-ath9k_platform_h_backup.patch [new file with mode: 0644]

index e4fa9252f1ea757fd2eaf8a55ab0fcfc2f560f58..d9149d9cc5905584d33e7109a9e20b890b1077f0 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2007-2012 OpenWrt.org
+# Copyright (C) 2007-2013 OpenWrt.org
 #
 # This is free software, licensed under the GNU General Public License v2.
 # See /LICENSE for more information.
@@ -10,11 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=mac80211
 
-PKG_VERSION:=2013-06-27
+PKG_VERSION:=2014-01-23.1
 PKG_RELEASE:=1
 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
-PKG_BACKPORT_VERSION:=.1
-PKG_MD5SUM:=73bd220c64c5c6fdc22b3bb7f180644f
+PKG_BACKPORT_VERSION:=
+PKG_MD5SUM:=8db16edbdaf4abc2e9c2f3b6c86736a6
 
 PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2
 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
@@ -24,12 +24,14 @@ PKG_MAINTAINER:=Felix Fietkau <nbd@openwrt.org>
 
 PKG_DRIVERS = \
        adm8211 ath5k libertas-usb libertas-sd p54-common p54-pci p54-usb p54-spi \
-       rt2x00-lib rt2x00-pci rt2x00-usb rt2x00-soc rt2800-lib rt2400-pci \
-       rt2500-pci rt2500-usb rt61-pci rt73-usb rt2800-pci rt2800-usb \
+       rt2x00-lib rt2x00-pci rt2x00-usb rt2800-lib rt2400-pci rt2500-pci \
+       rt2500-usb rt61-pci rt73-usb rt2800-mmio rt2800-pci rt2800-usb rt2800-soc \
        rtl8180 rtl8187 zd1211rw mac80211-hwsim carl9170 b43 b43legacy \
-       ath9k-common ath9k ath9k-htc ath net-libipw net-ipw2100 net-ipw2200 \
+       ath9k-common ath9k ath9k-htc ath10k ath net-libipw net-ipw2100 net-ipw2200 \
        mwl8k net-hermes net-hermes-pci net-hermes-plx net-hermes-pcmcia \
-       iwl-legacy iwl3945 iwl4965 iwlagn wl12xx lib80211
+       iwl-legacy iwl3945 iwl4965 iwlagn wlcore wl12xx wl18xx lib80211 \
+       rtlwifi rtlwifi-pci rtlwifi-usb rtl8192c-common rtl8192ce rtl8192se \
+       rtl8192de rtl8192cu
 
 PKG_CONFIG_DEPENDS:= \
        CONFIG_PACKAGE_kmod-mac80211 \
@@ -40,10 +42,9 @@ PKG_CONFIG_DEPENDS:= \
        CONFIG_PACKAGE_B43_DEBUG \
        CONFIG_PACKAGE_B43_PIO \
        CONFIG_PACKAGE_B43_N_PHY \
+       CONFIG_PACKAGE_RTLWIFI_DEBUG \
        CONFIG_ATH_USER_REGD \
 
-CARL9170_FW_VERSION:=1.9.6
-
 include $(INCLUDE_DIR)/package.mk
 
 WMENU:=Wireless Drivers
@@ -104,12 +105,12 @@ Generic IEEE 802.11 Networking Stack (mac80211)
 endef
 
 PKG_LINUX_FIRMWARE_NAME:=linux-firmware
-PKG_LINUX_FIRMWARE_VERSION:=6942dba419d2ebf8c15514972e89734fd7a8cebc
+PKG_LINUX_FIRMWARE_VERSION:=7d0c7a8cfd78388d90cc784a185b19dcbdbce824
 PKG_LINUX_FIRMWARE_SOURCE:=$(PKG_LINUX_FIRMWARE_NAME)-$(PKG_LINUX_FIRMWARE_VERSION).tar.bz2
 PKG_LINUX_FIRMWARE_PROTO:=git
 PKG_LINUX_FIRMWARE_SOURCE_URL:=git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
 PKG_LINUX_FIRMWARE_SUBDIR:=$(PKG_LINUX_FIRMWARE_NAME)-$(PKG_LINUX_FIRMWARE_VERSION)
-PKG_LINUX_FIRMWARE_MIRROR_MD5SUM:=a5f8c27af9e43f0ad24d7f821c5a781e
+PKG_LINUX_FIRMWARE_MIRROR_MD5SUM:=837a1a9456c1ec8b428cc0b2b08a331b
 
 define Download/linux-firmware
   FILE:=$(PKG_LINUX_FIRMWARE_SOURCE)
@@ -122,11 +123,28 @@ define Download/linux-firmware
 endef
 $(eval $(call Download,linux-firmware))
 
+PKG_ATH10K_LINUX_FIRMWARE_NAME:=ath10k-firmware
+PKG_ATH10K_LINUX_FIRMWARE_VERSION:=d86e78e5c6be34329936c8bd73a212700437be2e
+PKG_ATH10K_LINUX_FIRMWARE_SOURCE:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION).tar.bz2
+PKG_ATH10K_LINUX_FIRMWARE_PROTO:=git
+PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL:=https://github.com/kvalo/ath10k-firmware.git
+PKG_ATH10K_LINUX_FIRMWARE_SUBDIR:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION)
+#PKG_ATH10K_LINUX_FIRMWARE_MIRROR_MD5SUM:=?
+
+define Download/ath10k-firmware
+  FILE:=$(PKG_ATH10K_LINUX_FIRMWARE_SOURCE)
+  URL:=$(PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL)
+  PROTO:=$(PKG_ATH10K_LINUX_FIRMWARE_PROTO)
+  VERSION:=$(PKG_ATH10K_LINUX_FIRMWARE_VERSION)
+  SUBDIR:=$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)
+  #MIRROR_MD5SUM:=$(PKG_ATH10K_LINUX_FIRMWARE_MIRROR_MD5SUM)
+endef
+$(eval $(call Download,ath10k-firmware))
+
 # Prism54 drivers
 P54PCIFW:=2.13.12.0.arm
 P54USBFW:=2.13.24.0.lm87.arm
 P54SPIFW:=2.13.0.0.a.13.14.arm
-CARL9170_FW:=carl9170-1.fw
 
 define Download/p54usb
   FILE:=$(P54USBFW)
@@ -149,13 +167,6 @@ define Download/p54spi
 endef
 $(eval $(call Download,p54spi))
 
-define Download/carl9170
-  FILE:=$(CARL9170_FW)-$(CARL9170_FW_VERSION)
-  URL:=http://downloads.openwrt.org/sources/
-  MD5SUM:=2fa6ed98d53d0b5fbcc136d1cf5e9609
-endef
-$(eval $(call Download,carl9170))
-
 define KernelPackage/p54/Default
   $(call KernelPackage/mac80211/Default)
   TITLE:=Prism54 Drivers
@@ -233,6 +244,7 @@ endef
 define KernelPackage/rt2x00-mmio
 $(call KernelPackage/rt2x00/Default)
   DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-eeprom-93cx6
+  HIDDEN:=1
   TITLE+= (MMIO)
   FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00mmio.ko
   AUTOLOAD:=$(call AutoLoad,25,rt2x00mmio)
@@ -241,6 +253,7 @@ endef
 define KernelPackage/rt2x00-pci
 $(call KernelPackage/rt2x00/Default)
   DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-mmio +kmod-rt2x00-lib
+  HIDDEN:=1
   TITLE+= (PCI)
   FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00pci.ko
   AUTOLOAD:=$(call AutoLoad,26,rt2x00pci)
@@ -249,22 +262,16 @@ endef
 define KernelPackage/rt2x00-usb
 $(call KernelPackage/rt2x00/Default)
   DEPENDS+= @USB_SUPPORT +kmod-rt2x00-lib +kmod-usb-core
+  HIDDEN:=1
   TITLE+= (USB)
   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00usb.ko
   AUTOLOAD:=$(call AutoLoad,26,rt2x00usb)
 endef
 
-define KernelPackage/rt2x00-soc
-$(call KernelPackage/rt2x00/Default)
-  DEPENDS+= @TARGET_ramips @!TARGET_ramips_mt7620a @!TARGET_ramips_rt3883 +kmod-rt2x00-mmio +kmod-rt2x00-lib
-  TITLE+= (SoC)
-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00soc.ko
-  AUTOLOAD:=$(call AutoLoad,26,rt2x00soc)
-endef
-
 define KernelPackage/rt2800-lib
 $(call KernelPackage/rt2x00/Default)
-  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +TARGET_ramips:kmod-rt2x00-soc +@DRIVER_11N_SUPPORT
+  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT||TARGET_ramips) +kmod-rt2x00-lib +kmod-lib-crc-ccitt +@DRIVER_11N_SUPPORT
+  HIDDEN:=1
   TITLE+= (rt2800 LIB)
   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800lib.ko
   AUTOLOAD:=$(call AutoLoad,27,rt2800lib)
@@ -310,12 +317,31 @@ define KernelPackage/rt73-usb
   AUTOLOAD:=$(call AutoLoad,27,rt73usb)
 endef
 
+define KernelPackage/rt2800-mmio
+$(call KernelPackage/rt2x00/Default)
+  TITLE += (RT28xx/RT3xxx MMIO)
+  DEPENDS += +kmod-rt2800-lib +kmod-rt2x00-mmio
+  HIDDEN:=1
+  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800mmio.ko
+  AUTOLOAD:=$(call AutoLoad,28,rt2800mmio)
+endef
+
+define KernelPackage/rt2800-soc
+$(call KernelPackage/rt2x00/Default)
+  DEPENDS += @TARGET_ramips_rt305x +kmod-rt2800-mmio +kmod-rt2800-lib
+  TITLE += (RT28xx/RT3xxx SoC)
+  FILES := \
+       $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2x00soc.ko \
+       $(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800soc.ko
+  AUTOLOAD:=$(call AutoLoad,29,rt2x00soc rt2800soc)
+endef
+
 define KernelPackage/rt2800-pci
 $(call KernelPackage/rt2x00/Default)
-  DEPENDS+= @(PCI_SUPPORT||TARGET_ramips) +PCI_SUPPORT:kmod-rt2x00-pci +kmod-rt2800-lib +kmod-lib-crc-ccitt +TARGET_ramips:kmod-rt2x00-soc
+  DEPENDS+= @PCI_SUPPORT +kmod-rt2x00-pci +kmod-rt2800-lib +kmod-rt2800-mmio
   TITLE+= (RT2860 PCI)
   FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rt2x00/rt2800pci.ko
-  AUTOLOAD:=$(call AutoLoad,28,rt2800pci)
+  AUTOLOAD:=$(call AutoLoad,29,rt2800pci)
 endef
 
 define KernelPackage/rt2800-usb
@@ -349,6 +375,106 @@ $(call KernelPackage/rtl818x/Default)
   AUTOLOAD:=$(call AutoLoad,27,rtl8187)
 endef
 
+define KernelPackage/rtlwifi/config
+       menu "Configuration"
+               depends on PACKAGE_kmod-rtlwifi
+
+       config PACKAGE_RTLWIFI_DEBUG
+               bool "Realtek wireless debugging"
+               help
+                 Say Y, if you want to debug realtek wireless drivers.
+
+       endmenu
+endef
+
+define KernelPackage/rtlwifi
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Realtek common driver part
+  DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +@DRIVER_11N_SUPPORT
+  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtlwifi.ko
+  AUTOLOAD:=$(call AutoLoad,60,rtlwifi)
+  MENU:=1
+endef
+
+define KernelPackage/rtlwifi-pci
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Realtek common driver part (PCI support)
+  DEPENDS+= @PCI_SUPPORT +kmod-rtlwifi
+  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl_pci.ko
+  AUTOLOAD:=$(call AutoLoad,61,rtl_pci)
+  HIDDEN:=1
+endef
+
+define KernelPackage/rtlwifi-usb
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Realtek common driver part (USB support)
+  DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-rtlwifi
+  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl_usb.ko
+  AUTOLOAD:=$(call AutoLoad,61,rtl_usb)
+  HIDDEN:=1
+endef
+
+define KernelPackage/rtl8192c-common
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Realtek RTL8192CE/RTL8192CU common support module
+  DEPENDS+= +kmod-rtlwifi
+  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192c/rtl8192c-common.ko
+  AUTOLOAD:=$(call AutoLoad,62,rtl8192c-common)
+  HIDDEN:=1
+endef
+
+define KernelPackage/rtl8192ce
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Realtek RTL8192CE/RTL8188CE support
+  DEPENDS+= +kmod-rtlwifi-pci +kmod-rtl8192c-common
+  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192ce/rtl8192ce.ko
+  AUTOLOAD:=$(call AutoLoad,63,rtl8192ce)
+endef
+
+define KernelPackage/rtl8192ce/install
+       $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+       $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cfw.bin $(1)/lib/firmware/rtlwifi
+endef
+
+define KernelPackage/rtl8192se
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Realtek RTL8192SE/RTL8191SE support
+  DEPENDS+= +kmod-rtlwifi-pci
+  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192se/rtl8192se.ko
+  AUTOLOAD:=$(call AutoLoad,63,rtl8192se)
+endef
+
+define KernelPackage/rtl8192se/install
+       $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+       $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192sefw.bin $(1)/lib/firmware/rtlwifi
+endef
+
+define KernelPackage/rtl8192de
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Realtek RTL8192DE/RTL8188DE support
+  DEPENDS+= +kmod-rtlwifi-pci
+  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192de/rtl8192de.ko
+  AUTOLOAD:=$(call AutoLoad,63,rtl8192de)
+endef
+
+define KernelPackage/rtl8192de/install
+       $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+       $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192defw.bin $(1)/lib/firmware/rtlwifi
+endef
+
+define KernelPackage/rtl8192cu
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Realtek RTL8192CU/RTL8188CU support
+  DEPENDS+= +kmod-rtlwifi-usb +kmod-rtl8192c-common
+  FILES:= $(PKG_BUILD_DIR)/drivers/net/wireless/rtlwifi/rtl8192cu/rtl8192cu.ko
+  AUTOLOAD:=$(call AutoLoad,63,rtl8192cu)
+endef
+
+define KernelPackage/rtl8192cu/install
+       $(INSTALL_DIR) $(1)/lib/firmware/rtlwifi
+       $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/rtlwifi/rtl8192cufw.bin $(1)/lib/firmware/rtlwifi
+endef
+
 ZD1211FW_NAME:=zd1211-firmware
 ZD1211FW_VERSION:=1.4
 define Download/zd1211rw
@@ -463,6 +589,23 @@ This module adds support for wireless adapters based on
 Atheros USB AR9271 and AR7010 family of chipsets.
 endef
 
+define KernelPackage/ath10k
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Atheros 802.11ac wireless cards support
+  URL:=http://wireless.kernel.org/en/users/Drivers/ath10k
+  DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11N_SUPPORT
+  FILES:= \
+       $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \
+       $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko
+  AUTOLOAD:=$(call AutoLoad,55,ath10k_core ath10k_pci)
+endef
+
+define KernelPackage/ath10k/description
+This module adds support for wireless adapters based on
+Atheros IEEE 802.11ac family of chipsets. For now only
+PCI is supported.
+endef
+
 define KernelPackage/carl9170
   $(call KernelPackage/mac80211/Default)
   TITLE:=Driver for Atheros AR9170 USB sticks
@@ -471,14 +614,10 @@ define KernelPackage/carl9170
   AUTOLOAD:=$(call AutoLoad,60,carl9170)
 endef
 
-define KernelPackage/carl9170/install
-       $(INSTALL_DIR) $(1)/lib/firmware
-       $(INSTALL_DATA) $(DL_DIR)/$(CARL9170_FW)-$(CARL9170_FW_VERSION) $(1)/lib/firmware/$(CARL9170_FW)
-endef
-
 define KernelPackage/lib80211
   $(call KernelPackage/mac80211/Default)
   TITLE:=802.11 Networking stack
+  DEPENDS:=+kmod-cfg80211
   FILES:= \
        $(PKG_BUILD_DIR)/net/wireless/lib80211.ko \
        $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_wep.ko \
@@ -642,8 +781,10 @@ define KernelPackage/iwlagn
   $(call KernelPackage/mac80211/Default)
   DEPENDS:= +kmod-mac80211 @PCI_SUPPORT +@DRIVER_11N_SUPPORT
   TITLE:=Intel AGN Wireless support
-  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/iwlwifi.ko
-  AUTOLOAD:=$(call AutoLoad,60,iwlwifi)
+  FILES:= \
+       $(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/iwlwifi.ko \
+       $(PKG_BUILD_DIR)/drivers/net/wireless/iwlwifi/dvm/iwldvm.ko
+  AUTOLOAD:=$(call AutoLoad,60,iwlwifi iwldvm)
   MENU:=1
 endef
 
@@ -791,22 +932,47 @@ define KernelPackage/mwl8k/description
 endef
 
 
-define KernelPackage/wl12xx
+define KernelPackage/wlcore
   $(call KernelPackage/mac80211/Default)
-  TITLE:=Driver for TI WL12xx
-  URL:=http://wireless.kernel.org/en/users/Drivers/wl12xx
-  DEPENDS+= @TARGET_omap4 +kmod-mac80211
+  TITLE:=TI common driver part
+  DEPENDS+= @TARGET_omap +kmod-mac80211 +@DRIVER_11N_SUPPORT
   FILES:= \
-       $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl12xx/wl12xx.ko \
        $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore.ko \
        $(PKG_BUILD_DIR)/drivers/net/wireless/ti/wlcore/wlcore_sdio.ko
-  AUTOLOAD:=$(call AutoLoad,61,wlcore wlcore_sdio wl12xx)
+  AUTOLOAD:=$(call AutoLoad,61,wlcore wlcore_sdio)
+endef
+
+define KernelPackage/wlcore/description
+ This module contains some common parts needed by TI Wireless drivers.
+endef
+
+define KernelPackage/wl12xx
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Driver for TI WL12xx
+  URL:=http://wireless.kernel.org/en/users/Drivers/wl12xx
+  DEPENDS+= +kmod-wlcore
+  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl12xx/wl12xx.ko
+  AUTOLOAD:=$(call AutoLoad,62,wl12xx)
 endef
 
 define KernelPackage/wl12xx/description
  Kernel modules for TI WL12xx
 endef
 
+define KernelPackage/wl18xx
+  $(call KernelPackage/mac80211/Default)
+  TITLE:=Driver for TI WL18xx
+  URL:=http://wireless.kernel.org/en/users/Drivers/wl18xx
+  DEPENDS+= +kmod-wlcore
+  FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ti/wl18xx/wl18xx.ko
+  AUTOLOAD:=$(call AutoLoad,62,wl18xx)
+endef
+
+define KernelPackage/wl18xx/description
+ Kernel modules for TI WL18xx
+endef
+
+
 #Broadcom firmware
 ifneq ($(CONFIG_B43_FW_5_10),)
   PKG_B43_FWV4_NAME:=broadcom-wl
@@ -1194,6 +1360,7 @@ ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS
        MAC80211_DEBUGFS \
        ATH9K_DEBUGFS \
        ATH9K_HTC_DEBUGFS \
+       ATH10K_DEBUGFS \
        CARL9170_DEBUGFS \
        ATH5K_DEBUG
 endif
@@ -1201,7 +1368,7 @@ endif
 config-$(call config_package,lib80211) += LIB80211 LIB80211_CRYPT_WEP LIB80211_CRYPT_CCMP LIB80211_CRYPT_TKIP
 
 config-$(call config_package,ath) += ATH_CARDS ATH_COMMON
-config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG
+config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG ATH10K_DEBUG
 
 config-$(call config_package,ath9k) += ATH9K
 config-$(call config_package,ath9k-common) += ATH9K_COMMON
@@ -1210,6 +1377,7 @@ config-$(CONFIG_PCI) += ATH9K_PCI
 config-$(CONFIG_ATH_USER_REGD) += ATH_USER_REGD
 
 config-$(call config_package,ath9k-htc) += ATH9K_HTC
+config-$(call config_package,ath10k) += ATH10K ATH10K_PCI
 
 config-$(call config_package,ath5k) += ATH5K
 ifdef CONFIG_TARGET_atheros
@@ -1232,7 +1400,8 @@ config-y += B43LEGACY_DMA_MODE
 
 config-$(call config_package,brcmutil) += BRCMUTIL
 config-$(call config_package,brcmsmac) += BRCMSMAC
-config-$(call config_package,brcmfmac) += BRCMFMAC BRCMFMAC_USB
+config-$(call config_package,brcmfmac) += BRCMFMAC
+config-y += BRCMFMAC_USB
 config-$(CONFIG_PACKAGE_BRCM80211_DEBUG) += BRCMDBG
 
 config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM
@@ -1241,7 +1410,6 @@ config-$(call config_package,rt2x00-lib) += RT2X00 RT2X00_LIB
 config-$(call config_package,rt2x00-pci) += RT2X00_LIB_PCI
 config-$(call config_package,rt2x00-mmio) += RT2X00_LIB_MMIO
 config-$(call config_package,rt2x00-usb) += RT2X00_LIB_USB
-config-$(call config_package,rt2x00-soc) += RT2X00_LIB_SOC
 config-$(CONFIG_PACKAGE_RT2X00_LIB_DEBUGFS) += RT2X00_LIB_DEBUGFS
 config-$(CONFIG_PACKAGE_RT2X00_DEBUG) += RT2X00_DEBUG
 
@@ -1252,15 +1420,18 @@ config-$(call config_package,rt61-pci) += RT61PCI
 config-$(call config_package,rt73-usb) += RT73USB
 
 config-$(call config_package,rt2800-lib) += RT2800_LIB
-config-y += RT2800PCI_RT33XX RT2800PCI_RT35XX RT2800PCI_RT53XX RT2800PCI_RT3290
 
+config-$(call config_package,rt2800-soc) += RT2800SOC
 config-$(call config_package,rt2800-pci) += RT2800PCI
+config-y += RT2800PCI_RT33XX RT2800PCI_RT35XX RT2800PCI_RT53XX RT2800PCI_RT3290
+
 config-$(call config_package,rt2800-usb) += RT2800USB
+config-y += RT2800USB_RT33XX RT2800USB_RT35XX RT2800USB_RT3573 RT2800USB_RT53XX RT2800USB_RT55XX
 
 config-$(call config_package,iwl-legacy) += IWLEGACY
 config-$(call config_package,iwl3945) += IWL3945
 config-$(call config_package,iwl4965) += IWL4965
-config-$(call config_package,iwlagn) += IWLWIFI
+config-$(call config_package,iwlagn) += IWLWIFI IWLDVM
 
 config-$(call config_package,net-libipw) += LIBIPW
 config-$(call config_package,net-ipw2100) += IPW2100
@@ -1283,9 +1454,22 @@ config-$(call config_package,libertas-usb) += LIBERTAS LIBERTAS_USB
 config-$(call config_package,mwl8k) += MWL8K
 config-$(call config_package,rtl8180) += RTL8180
 config-$(call config_package,rtl8187) += RTL8187
-config-$(call config_package,wl12xx) += WL_TI WLCORE WLCORE_SDIO WL12XX
+config-$(call config_package,wlcore) += WLCORE WLCORE_SDIO
+config-$(call config_package,wl12xx) += WL12XX
+config-$(call config_package,wl18xx) += WL18XX
+config-y += WL_TI WILINK_PLATFORM_DATA
 config-$(call config_package,zd1211rw) += ZD1211RW
 
+config-$(call config_package,rtlwifi) += RTL_CARDS RTLWIFI
+config-$(call config_package,rtlwifi-pci) += RTLWIFI_PCI
+config-$(call config_package,rtlwifi-usb) += RTLWIFI_USB
+config-$(call config_package,rtl8192c-common) += RTL8192C_COMMON
+config-$(call config_package,rtl8192ce) += RTL8192CE
+config-$(call config_package,rtl8192se) += RTL8192SE
+config-$(call config_package,rtl8192de) += RTL8192DE
+config-$(call config_package,rtl8192cu) += RTL8192CU
+config-$(CONFIG_PACKAGE_RTLWIFI_DEBUG) += RTLWIFI_DEBUG
+
 config-$(CONFIG_LEDS_TRIGGERS) += MAC80211_LEDS B43_LEDS B43LEGACY_LEDS
 
 MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \
@@ -1298,6 +1482,10 @@ MAKE_OPTS:= -C "$(PKG_BUILD_DIR)" \
        KERNEL_SUBLEVEL=$(lastword $(subst ., ,$(KERNEL_PATCHVER))) \
        KBUILD_LDFLAGS_MODULE_PREREQ=
 
+ifneq ($(findstring c,$(OPENWRT_VERBOSE)),)
+  MAKE_OPTS += V=1
+endif
+
 define ConfigVars
 $(subst $(space),,$(foreach opt,$(config-$(1)),CPTCFG_$(opt)=$(1)
 ))
@@ -1317,6 +1505,7 @@ define Build/Prepare
        $(TAR) -C $(PKG_BUILD_DIR) -xzf $(DL_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION).tgz
        $(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)
+       $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SOURCE)
        rm -rf \
                $(PKG_BUILD_DIR)/include/linux/ssb \
                $(PKG_BUILD_DIR)/include/linux/bcma \
@@ -1439,15 +1628,32 @@ define KernelPackage/wl12xx/install
                $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-plt.bin \
                $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl127x-fw-5-sr.bin \
                $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl1271-nvs.bin \
+               $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-mr.bin \
+               $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-plt.bin \
+               $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-fw-5-sr.bin \
+               $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl128x-nvs.bin \
                $(1)/lib/firmware/ti-connectivity
 endef
 
+define KernelPackage/wl18xx/install
+       $(INSTALL_DIR) $(1)/lib/firmware/ti-connectivity
+       $(INSTALL_DATA) \
+               $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-conf.bin \
+               $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw.bin \
+               $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/ti-connectivity/wl18xx-fw-2.bin \
+               $(1)/lib/firmware/ti-connectivity
+endef
 
 define KernelPackage/zd1211rw/install
        $(INSTALL_DIR) $(1)/lib/firmware/zd1211
        $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(ZD1211FW_NAME)/zd1211* $(1)/lib/firmware/zd1211
 endef
 
+define KernelPackage/carl9170/install
+       $(INSTALL_DIR) $(1)/lib/firmware
+       $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(PKG_LINUX_FIRMWARE_SUBDIR)/carl9170-1.fw $(1)/lib/firmware
+endef
+
 define KernelPackage/ath9k-htc/install
        $(INSTALL_DIR) $(1)/lib/firmware
        $(INSTALL_DATA) \
@@ -1456,6 +1662,14 @@ define KernelPackage/ath9k-htc/install
                $(1)/lib/firmware/
 endef
 
+define KernelPackage/ath10k/install
+       $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0
+       $(INSTALL_DATA) \
+               $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \
+               $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/firmware-2.bin \
+               $(1)/lib/firmware/ath10k/QCA988X/hw2.0/
+endef
+
 define KernelPackage/mwl8k/install
        $(INSTALL_DIR) $(1)/lib/firmware/mwl8k
        $(INSTALL_DATA) \
@@ -1592,22 +1806,32 @@ $(eval $(call KernelPackage,rt2x00-lib))
 $(eval $(call KernelPackage,rt2x00-mmio))
 $(eval $(call KernelPackage,rt2x00-pci))
 $(eval $(call KernelPackage,rt2x00-usb))
-$(eval $(call KernelPackage,rt2x00-soc))
 $(eval $(call KernelPackage,rt2800-lib))
 $(eval $(call KernelPackage,rt2400-pci))
 $(eval $(call KernelPackage,rt2500-pci))
 $(eval $(call KernelPackage,rt2500-usb))
 $(eval $(call KernelPackage,rt61-pci))
 $(eval $(call KernelPackage,rt73-usb))
+$(eval $(call KernelPackage,rt2800-mmio))
+$(eval $(call KernelPackage,rt2800-soc))
 $(eval $(call KernelPackage,rt2800-pci))
 $(eval $(call KernelPackage,rt2800-usb))
 $(eval $(call KernelPackage,rtl8180))
 $(eval $(call KernelPackage,rtl8187))
+$(eval $(call KernelPackage,rtlwifi))
+$(eval $(call KernelPackage,rtlwifi-pci))
+$(eval $(call KernelPackage,rtlwifi-usb))
+$(eval $(call KernelPackage,rtl8192c-common))
+$(eval $(call KernelPackage,rtl8192ce))
+$(eval $(call KernelPackage,rtl8192se))
+$(eval $(call KernelPackage,rtl8192de))
+$(eval $(call KernelPackage,rtl8192cu))
 $(eval $(call KernelPackage,zd1211rw))
 $(eval $(call KernelPackage,mac80211-hwsim))
 $(eval $(call KernelPackage,ath9k-common))
 $(eval $(call KernelPackage,ath9k))
 $(eval $(call KernelPackage,ath9k-htc))
+$(eval $(call KernelPackage,ath10k))
 $(eval $(call KernelPackage,ath))
 $(eval $(call KernelPackage,carl9170))
 $(eval $(call KernelPackage,b43))
@@ -1627,4 +1851,6 @@ $(eval $(call KernelPackage,net-hermes))
 $(eval $(call KernelPackage,net-hermes-pci))
 $(eval $(call KernelPackage,net-hermes-plx))
 $(eval $(call KernelPackage,net-hermes-pcmcia))
+$(eval $(call KernelPackage,wlcore))
 $(eval $(call KernelPackage,wl12xx))
+$(eval $(call KernelPackage,wl18xx))
index 20f6bfa93cb55c74312d09edd51f82bd399a88c4..1994ca38d447153780f38edd21bbd191944f490e 100644 (file)
@@ -19,11 +19,8 @@ mac80211_hostapd_setup_base() {
 
        [ -n "$channel" -a -z "$hwmode" ] && wifi_fixup_hwmode "$device"
 
-       [ "$channel" = auto ] && {
-               channel=$(iw phy "$phy" info | \
-                       sed -ne '/MHz/ { /disabled\|passive\|radar/d; s/.*\[//; s/\].*//; p; q }')
-               config_set "$device" channel "$channel"
-       }
+       hostapd_channel=$channel
+       [ "$channel" = auto -o "$channel" = 0 ] && hostapd_channel=acs_survey
 
        [ -n "$hwmode" ] && {
                config_get hwmode_11n "$device" hwmode_11n
@@ -97,7 +94,7 @@ tx_queue_data0_cwmin=3
 tx_queue_data0_cwmax=7
 tx_queue_data0_burst=1.5
 ${hwmode:+hw_mode=$hwmode}
-${channel:+channel=$channel}
+${hostapd_channel:+channel=$hostapd_channel}
 ${beacon_int:+beacon_int=$beacon_int}
 ${country:+country_code=$country}
 ${noscan:+noscan=$noscan}
@@ -110,6 +107,7 @@ EOF
 mac80211_hostapd_setup_bss() {
        local phy="$1"
        local vif="$2"
+       local staidx="$3"
 
        hostapd_cfg=
        cfgfile="/var/run/hostapd-$phy.conf"
@@ -132,6 +130,8 @@ mac80211_hostapd_setup_bss() {
        config_get_bool wds "$vif" wds 0
        [ "$wds" -gt 0 ] && append hostapd_cfg "wds_sta=1" "$N"
 
+       [ "$staidx" -gt 0 ] && append hostapd_cfg "start_disabled=1" "$N"
+
        local macaddr hidden maxassoc wmm
        config_get macaddr "$vif" macaddr
        config_get maxassoc "$vif" maxassoc
@@ -251,7 +251,7 @@ disable_mac80211() (
        include /lib/network
        for wdev in $(list_phy_interfaces "$phy"); do
                [ -f "/var/run/$wdev.pid" ] && kill $(cat /var/run/$wdev.pid) >&/dev/null 2>&1
-               for pid in `pidof wpa_supplicant`; do
+               for pid in `pidof wpa_supplicant meshd-nl80211`; do
                        grep "$wdev" /proc/$pid/cmdline >/dev/null && \
                                kill $pid
                done
@@ -318,6 +318,7 @@ enable_mac80211() {
        local i=0
        local macidx=0
        local apidx=0
+       local staidx=0
        fixed=""
        local hostapd_ctrl=""
 
@@ -370,14 +371,20 @@ enable_mac80211() {
                                [ "$apidx" -gt 1 ] || iw phy "$phy" interface add "$ifname" type managed
                        ;;
                        mesh)
-                               config_get mesh_id "$vif" mesh_id
-                               iw phy "$phy" interface add "$ifname" type mp mesh_id "$mesh_id"
+                               config_get key "$vif" key ""
+                               if [ -n "$key" ]; then
+                                       iw phy "$phy" interface add "$ifname" type mp
+                               else
+                                       config_get mesh_id "$vif" mesh_id
+                                       iw phy "$phy" interface add "$ifname" type mp mesh_id "$mesh_id"
+                               fi
                        ;;
                        monitor)
                                iw phy "$phy" interface add "$ifname" type monitor
                        ;;
                        sta)
                                local wdsflag
+                               staidx="$(($staidx + 1))"
                                config_get_bool wds "$vif" wds 0
                                [ "$wds" -gt 0 ] && wdsflag="4addr on"
                                iw phy "$phy" interface add "$ifname" type managed $wdsflag
@@ -426,9 +433,16 @@ enable_mac80211() {
        rm -f /var/run/hostapd-$phy.conf
        for vif in $vifs; do
                config_get mode "$vif" mode
-               [ "$mode" = "ap" ] || continue
-               mac80211_hostapd_setup_bss "$phy" "$vif"
-               start_hostapd=1
+               case "$mode" in
+                       ap)
+                               mac80211_hostapd_setup_bss "$phy" "$vif" "$staidx"
+                               start_hostapd=1
+                       ;;
+                       mesh)
+                               config_get key "$vif" key ""
+                               [ -n "$key" ] && authsae_start_interface "$device" "$vif"
+                       ;;
+               esac
        done
 
        [ -n "$start_hostapd" ] && {
index b250e6926e6c8884315918aa8e0a7d6bf2a42abd..2badb21c451169ab87e92b7f8b9cf02c841afa66 100644 (file)
@@ -1,22 +1,29 @@
 # This is the world regulatory domain
 country 00:
        (2402 - 2472 @ 40), (3, 20)
-        # Channel 12 - 13. No HT40 channel fits here
-        (2457 - 2482 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS
-        # Channel 14. Only JP enables this and for 802.11b only
-        (2474 - 2494 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS, NO-OFDM
-        # Channel 36 - 48
-        (5170 - 5250 @ 40), (3, 20)
-        # NB: 5260 MHz - 5700 MHz requies DFS
-        # Channel 149 - 165
-        (5735 - 5835 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
-
+       # Channel 12 - 13.
+       (2457 - 2482 @ 40), (3, 20), PASSIVE-SCAN, NO-IBSS
+       # Channel 14. Only JP enables this and for 802.11b only
+       (2474 - 2494 @ 20), (3, 20), PASSIVE-SCAN, NO-IBSS, NO-OFDM
+       # Channel 36 - 48
+       (5170 - 5250 @ 80), (3, 20)
+       # NB: 5260 MHz - 5700 MHz requies DFS
+       # Channel 149 - 165
+       (5735 - 5835 @ 80), (3, 20), PASSIVE-SCAN, NO-IBSS
+       # IEEE 802.11ad (60GHz), channels 1..3
+       (57240 - 63720 @ 2160), (N/A, 0)
+
+
+country AD:
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country AE:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country AL:
        (2402 - 2482 @ 20), (N/A, 20)
@@ -34,22 +41,25 @@ country AN:
 
 country AR:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 20), DFS
-       (5490 - 5710 @ 40), (3, 20), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country AT: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country AU:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (3, 23)
-       (5250 - 5330 @ 40), (3, 23), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country AW:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -67,6 +77,8 @@ country BA: DFS-ETSI
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country BB:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -79,15 +91,19 @@ country BD:
 
 country BE: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country BG: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 40), (N/A, 23)
        (5250 - 5290 @ 40), (N/A, 23), DFS
        (5490 - 5710 @ 40), (N/A, 30), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country BH:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -112,10 +128,10 @@ country BO:
 
 country BR:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 20), DFS
-       (5490 - 5710 @ 40), (3, 20), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country BY:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -129,16 +145,18 @@ country BZ:
 
 country CA:
        (2402 - 2472 @ 40), (3, 27)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 20), DFS
-       (5490 - 5710 @ 40), (3, 20), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country CH: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country CL:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -148,31 +166,34 @@ country CL:
 
 country CN:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5735 - 5835 @ 40), (N/A, 30)
+       (5735 - 5835 @ 80), (N/A, 30)
+       # 60 gHz band channels 1,4: 28dBm, channels 2,3: 44dBm
+       # ref: http://www.miit.gov.cn/n11293472/n11505629/n11506593/n11960250/n11960606/n11960700/n12330791.files/n12330790.pdf
+       (57240 - 59400 @ 2160), (N/A, 28)
+       (59400 - 63720 @ 2160), (N/A, 44)
+       (63720 - 65880 @ 2160), (N/A, 28)
 
 country CO:
        (2402 - 2472 @ 40), (3, 27)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 23), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country CR:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 20), (3, 17)
-       (5250 - 5330 @ 20), (3, 23), DFS
-       (5735 - 5835 @ 20), (3, 30)
-
-country CS:
-       (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country CY: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 # Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf
 # and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
@@ -180,9 +201,11 @@ country CY: DFS-ETSI
 # implemented.
 country CZ: DFS-ETSI
        (2400 - 2483.5 @ 40), (N/A, 100 mW)
-       (5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
-       (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
-       (5470 - 5725 @ 40), (N/A, 500 mW), DFS
+       (5150 - 5250 @ 80), (N/A, 200 mW), NO-OUTDOOR
+       (5250 - 5350 @ 80), (N/A, 100 mW), NO-OUTDOOR, DFS
+       (5470 - 5725 @ 80), (N/A, 500 mW), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 # Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
 # http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
@@ -200,17 +223,21 @@ country DE: DFS-ETSI
        # entries 279004 and 280006
        (2400 - 2483.5 @ 40), (N/A, 100 mW)
        # entry 303005
-       (5150 - 5250 @ 40), (N/A, 100 mW), NO-OUTDOOR
+       (5150 - 5250 @ 80), (N/A, 100 mW), NO-OUTDOOR
        # entries 304002 and 305002
-       (5250 - 5350 @ 40), (N/A, 100 mW), NO-OUTDOOR, DFS
+       (5250 - 5350 @ 80), (N/A, 100 mW), NO-OUTDOOR, DFS
        # entries 308002, 309001 and 310003
-       (5470 - 5725 @ 40), (N/A, 500 mW), DFS
+       (5470 - 5725 @ 80), (N/A, 500 mW), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country DK: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country DO:
        (2402 - 2472 @ 40), (3, 27)
@@ -223,15 +250,18 @@ country DZ:
 
 country EC:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 20), (3, 17)
-       (5250 - 5330 @ 20), (3, 23), DFS
-       (5735 - 5835 @ 20), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country EE: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country EG:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -239,33 +269,43 @@ country EG:
        (5250 - 5330 @ 20), (N/A, 20), DFS
 
 country ES: DFS-ETSI
-       (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (2400 - 2483.5 @ 40), (N/A, 100 mW)
+       (5150 - 5250 @ 80), (N/A, 100 mW), NO-OUTDOOR
+       (5250 - 5350 @ 80), (N/A, 100 mW), NO-OUTDOOR, DFS
+       (5470 - 5725 @ 80), (N/A, 500 mW), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country FI: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country FR: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country GE:
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 40), (N/A, 18)
        (5250 - 5330 @ 40), (N/A, 18), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country GB: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country GD:
        (2402 - 2472 @ 40), (3, 27)
@@ -276,9 +316,11 @@ country GD:
 
 country GR: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country GL: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
@@ -294,9 +336,10 @@ country GT:
 
 country GU:
        (2402 - 2472 @ 40), (3, 27)
-       (5170 - 5250 @ 20), (3, 17)
-       (5250 - 5330 @ 20), (3, 23), DFS
-       (5735 - 5835 @ 20), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country HN:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -307,16 +350,18 @@ country HN:
 
 country HK:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 20), DFS
-       (5490 - 5710 @ 40), (3, 20), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country HR: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country HT:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -329,20 +374,26 @@ country HU: DFS-ETSI
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country ID:
+       # ref: http://www.postel.go.id/content/ID/regulasi/standardisasi/kepdir/bwa%205,8%20ghz.pdf
        (2402 - 2482 @ 40), (N/A, 20)
+       (5735 - 5815 @ 80), (N/A, 20)
 
 country IE: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country IL:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5150 - 5250 @ 40), (N/A, 200 mW), NO-OUTDOOR
-       (5250 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR, DFS
+       (5150 - 5250 @ 80), (N/A, 200 mW), NO-OUTDOOR
+       (5250 - 5350 @ 80), (N/A, 200 mW), NO-OUTDOOR, DFS
 
 country IN:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -355,6 +406,8 @@ country IS: DFS-ETSI
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country IR:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -362,9 +415,11 @@ country IR:
 
 country IT: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country JM:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -374,18 +429,13 @@ country JM:
        (5735 - 5835 @ 40), (3, 30)
 
 country JP:
-       (2402 - 2472 @ 40), (N/A, 20)
-       (2457 - 2482 @ 20), (N/A, 20)
+       (2402 - 2482 @ 40), (N/A, 20)
        (2474 - 2494 @ 20), (N/A, 20), NO-OFDM
-       (4910 - 4930 @ 10), (N/A, 23)
        (4910 - 4990 @ 40), (N/A, 23)
-       (4930 - 4950 @ 10), (N/A, 23)
-       (5030 - 5045 @ 10), (N/A, 23)
        (5030 - 5090 @ 40), (N/A, 23)
-       (5050 - 5060 @ 10), (N/A, 23)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 23), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 160), (N/A, 23), DFS
 
 country JO:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -410,15 +460,15 @@ country KP:
 
 country KR:
        (2402 - 2482 @ 20), (N/A, 20)
-       (5170 - 5250 @ 20), (3, 20)
-       (5250 - 5330 @ 20), (3, 20), DFS
-       (5490 - 5630 @ 20), (3, 30), DFS
-       (5735 - 5815 @ 20), (3, 30)
+       (5170 - 5250 @ 80), (3, 20)
+       (5250 - 5330 @ 80), (3, 20), DFS
+       (5490 - 5630 @ 80), (3, 30), DFS
+       (5735 - 5815 @ 80), (3, 30)
 
 country KW:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
 
 country KZ:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -445,18 +495,24 @@ country LT: DFS-ETSI
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country LU: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country LV: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country MC: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
@@ -465,6 +521,8 @@ country MC: DFS-ETSI
 
 country MA:
        (2402 - 2482 @ 40), (N/A, 20)
+       (5170 - 5250 @ 80), (N/A, 23)
+       (5735 - 5835 @ 80), (N/A, 23)
 
 country MO:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -477,35 +535,45 @@ country MK: DFS-ETSI
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country MT: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country MY:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 30), DFS
-       (5735 - 5835 @ 40), (N/A, 30)
+       (5170 - 5250 @ 80), (N/A, 17)
+       (5250 - 5330 @ 80), (N/A, 23), DFS
+       (5735 - 5835 @ 80), (N/A, 30)
 
 country MX:
        (2402 - 2472 @ 40), (3, 27)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 23), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country NL: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20), NO-OUTDOOR
-       (5250 - 5330 @ 40), (N/A, 20), NO-OUTDOOR, DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20), NO-OUTDOOR
+       (5250 - 5330 @ 80), (N/A, 20), NO-OUTDOOR, DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country NO: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country NP:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -513,9 +581,10 @@ country NP:
 
 country NZ:
        (2402 - 2482 @ 40), (N/A, 30)
-       (5170 - 5250 @ 20), (3, 23)
-       (5250 - 5330 @ 20), (3, 23), DFS
-       (5735 - 5835 @ 20), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country OM:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -532,7 +601,10 @@ country PA:
 
 country PE:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5735 - 5835 @ 40), (N/A, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country PG:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -542,7 +614,10 @@ country PG:
 
 country PH:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5735 - 5835 @ 40), (N/A, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country PK:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -550,21 +625,26 @@ country PK:
 
 country PL: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country PT: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country PR:
        (2402 - 2472 @ 40), (3, 27)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 23), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country QA:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -575,40 +655,66 @@ country RO: DFS-ETSI
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+
+
+# Source:
+# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
+country RS:
+       (2400 - 2483.5 @ 40), (N/A, 100 mW)
+       (5150 - 5350 @ 40), (N/A, 200 mW), NO-OUTDOOR
+       (5470 - 5725 @ 20), (3, 1000 mW), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country RU:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5735 - 5835 @ 20), (N/A, 30)
+       (5170 - 5330 @ 40), (N/A, 20)
+       (5650 - 5710 @ 40), (N/A, 30)
+       (5735 - 5835 @ 40), (N/A, 30)
+
+country RW:
+       (2402 - 2482 @ 40), (N/A, 20)
+       (5735 - 5835 @ 40), (N/A, 30)
 
 country SA:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 20), (3, 23)
-       (5250 - 5330 @ 20), (3, 23), DFS
-       (5735 - 5835 @ 20), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country SE: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country SG:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5735 - 5835 @ 40), (N/A, 20)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country SI: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
        (5170 - 5250 @ 40), (N/A, 20)
        (5250 - 5330 @ 40), (N/A, 20), DFS
        (5490 - 5710 @ 40), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country SK: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
-       (5490 - 5710 @ 40), (N/A, 27), DFS
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country SV:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -622,14 +728,15 @@ country SY:
 country TW:
        (2402 - 2472 @ 40), (3, 27)
        (5270 - 5330 @ 40), (3, 17), DFS
-       (5735 - 5815 @ 40), (3, 30)
+       (5490 - 5710 @ 80), (3, 30), DFS
+       (5735 - 5815 @ 80), (3, 30)
 
 country TH:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 20), DFS
-       (5490 - 5710 @ 40), (3, 20), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country TT:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -645,19 +752,36 @@ country TN:
 
 country TR: DFS-ETSI
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 20), (N/A, 20)
-       (5250 - 5330 @ 20), (N/A, 20), DFS
-
+       (5170 - 5250 @ 80), (N/A, 20)
+       (5250 - 5330 @ 80), (N/A, 20), DFS
+       (5490 - 5710 @ 80), (N/A, 27), DFS
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
+# Source:
+# #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874
+# #1174 / 23 Oct 2008: http://www.nkrz.gov.ua/uk/activities/ruling/1225269361
+# (appendix 8)
+# Listed 5GHz range is a lowest common denominator for all related
+# rules in the referenced laws. Such a range is used because of
+# disputable definitions there.
 country UA:
-       (2402 - 2482 @ 40), (N/A, 20)
+       (2400 - 2483.5 @ 40), (N/A, 20), NO-OUTDOOR
+       (5150 - 5350 @ 40), (N/A, 20), NO-OUTDOOR
+       # 60 gHz band channels 1-4, ref: Etsi En 302 567
+       (57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
 
 country US: DFS-FCC
        (2402 - 2472 @ 40), (3, 27)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 20), DFS
-       (5490 - 5600 @ 40), (3, 20), DFS
-       (5650 - 5710 @ 40), (3, 20), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5600 @ 80), (3, 24), DFS
+       (5650 - 5710 @ 40), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
+       # 60g band
+       # reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255
+       # channels 1,2,3, EIRP=40dBm(43dBm peak)
+       (57240 - 63720 @ 2160), (N/A, 40)
 
 country UY:
        (2402 - 2482 @ 40), (N/A, 20)
@@ -679,18 +803,20 @@ country VE:
 
 country VN:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (N/A, 20)
-       (5250 - 5330 @ 40), (N/A, 20), DFS
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country YE:
        (2402 - 2482 @ 40), (N/A, 20)
 
 country ZA:
        (2402 - 2482 @ 40), (N/A, 20)
-       (5170 - 5250 @ 40), (3, 17)
-       (5250 - 5330 @ 40), (3, 20), DFS
-       (5490 - 5710 @ 40), (3, 20), DFS
-       (5735 - 5835 @ 40), (3, 30)
+       (5170 - 5250 @ 80), (3, 17)
+       (5250 - 5330 @ 80), (3, 24), DFS
+       (5490 - 5710 @ 80), (3, 24), DFS
+       (5735 - 5835 @ 80), (3, 30)
 
 country ZW:
        (2402 - 2482 @ 40), (N/A, 20)
index c541985cf3f0d2cc2af886fc210f8f68d4c34ede..26b327ac8e5e8426cc8c022f50fac1eaba425eb1 100644 (file)
 +      @$(MAKE) Kconfig.versions
        @$(MAKE) -f Makefile.real "$@"
  
- else
+ .PHONY: defconfig-help
 --- a/Makefile.real
 +++ b/Makefile.real
 @@ -54,7 +54,7 @@ defconfig-%::
diff --git a/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch b/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch
new file mode 100644 (file)
index 0000000..584fb05
--- /dev/null
@@ -0,0 +1,40 @@
+From 88e75363ff9c00cc2e7768ca23ded79bf8d6bf08 Mon Sep 17 00:00:00 2001
+From: Hauke Mehrtens <hauke@hauke-m.de>
+Date: Fri, 7 Feb 2014 19:13:11 +0100
+Subject: [PATCH 1/8] backports: add led_trigger_blink{_oneshot}()
+
+When led support is deactivated in the kernel and
+CPTCFG_BACKPORT_BUILD_LEDS is set mac80211 references
+led_trigger_blink_oneshot() but it is not declared anywhere.
+
+This fixes the following build error:
+net/mac80211/led.c: In function 'ieee80211_led_rx':
+net/mac80211/led.c:25:2: error: implicit declaration of function 'led_trigger_blink_oneshot' [-Werror=implicit-function-declaration]
+
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ backport-include/backport/leds-disabled.h |   13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+--- a/backport-include/backport/leds-disabled.h
++++ b/backport-include/backport/leds-disabled.h
+@@ -163,6 +163,19 @@ static inline void led_trigger_event(str
+                                    enum led_brightness event)
+ {
+ }
++
++static inline void led_trigger_blink(struct led_trigger *trigger,
++                                   unsigned long *delay_on,
++                                   unsigned long *delay_off)
++{
++}
++
++static inline void led_trigger_blink_oneshot(struct led_trigger *trigger,
++                                           unsigned long *delay_on,
++                                           unsigned long *delay_off,
++                                           int invert)
++{
++}
+ #endif
+ #endif /* __BACKPORT_LED_DISABLED_SUPPORT */
index 89c6a60e13727233b6dbebfce3ac77aab3c9ce3e..e6d4ff6e9de4c2838ef9dc37ce39c5697794a375 100644 (file)
@@ -6,11 +6,11 @@
  
 +#ifdef CONFIG_COMPAT_BLUETOOTH
  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
+ #ifdef CONFIG_TTY
  /*
-  *            Termios Helper Methods
-@@ -112,4 +113,4 @@ int tty_set_termios(struct tty_struct *t
- }
+@@ -114,4 +115,4 @@ int tty_set_termios(struct tty_struct *t
  EXPORT_SYMBOL_GPL(tty_set_termios);
+ #endif /* CONFIG_TTY */
  #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) */
 -
 +#endif
index 789a77ab12693ee1f8d3381b8dae2e01d78be6ec..5ee52a240d893432c0d44ee8c06119f472dd93f9 100644 (file)
@@ -1,13 +1,20 @@
 --- a/drivers/net/wireless/rt2x00/Kconfig
 +++ b/drivers/net/wireless/rt2x00/Kconfig
-@@ -202,25 +202,28 @@ config RT2800USB_UNKNOWN
- endif
+@@ -225,36 +225,37 @@ config RT2800SOC
  
  config RT2800_LIB
 -      tristate
 +      tristate "RT2800 USB/PCI support"
        depends on m
  
+ config RT2800_LIB_MMIO
+-      tristate
++      tristate "RT2800 MMIO support"
+       depends on m
+       select RT2X00_LIB_MMIO
+       select RT2800_LIB
  config RT2X00_LIB_MMIO
 -      tristate
 +      tristate "RT2x00 MMIO support"
@@ -16,7 +23,6 @@
  config RT2X00_LIB_PCI
 -      tristate
 +      tristate "RT2x00 PCI support"
-+      depends on PCI
        depends on m
        select RT2X00_LIB
  
  config RT2X00_LIB_USB
 -      tristate
 +      tristate "RT2x00 USB support"
-+      depends on USB
        depends on m
        select RT2X00_LIB
  
+ config RT2X00_LIB
+-      tristate
++      tristate "RT2x00 support"
+       depends on m
+       select BACKPORT_AVERAGE
index 5e8d421aa565572b120045c07aefa30418db4422..f4b9470627e65a288b2b58064f08ed1515c56164 100644 (file)
@@ -1,6 +1,6 @@
 --- a/.local-symbols
 +++ b/.local-symbols
-@@ -363,42 +363,6 @@ USB_CDC_PHONET=
+@@ -379,42 +379,6 @@ USB_CDC_PHONET=
  USB_IPHETH=
  USB_SIERRA_NET=
  USB_VL600=
@@ -40,9 +40,9 @@
 -BCMA_DRIVER_GMAC_CMN=
 -BCMA_DRIVER_GPIO=
 -BCMA_DEBUG=
DRM=
DRM_USB=
DRM_KMS_HELPER=
NFC=
NFC_DIGITAL=
NFC_NCI=
 --- a/Kconfig
 +++ b/Kconfig
 @@ -33,9 +33,6 @@ source drivers/net/wireless/Kconfig
 -source drivers/ssb/Kconfig
 -source drivers/bcma/Kconfig
 -
- source drivers/gpu/drm/Kconfig
  source net/nfc/Kconfig
+ source drivers/regulator/Kconfig
 --- a/Makefile.kernel
 +++ b/Makefile.kernel
-@@ -26,8 +26,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/
+@@ -25,8 +25,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/
  obj-$(CPTCFG_WLAN) += drivers/net/wireless/
  obj-$(CPTCFG_BT) += net/bluetooth/
  obj-$(CPTCFG_BT) += drivers/bluetooth/
 -obj-$(CPTCFG_BCMA) += drivers/bcma/
  obj-$(CPTCFG_ETHERNET) += drivers/net/ethernet/
  obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/
- obj-$(CPTCFG_DRM) += drivers/gpu/drm/
+ obj-$(CPTCFG_NFC) += net/nfc/
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -2729,7 +2729,7 @@ static struct ssb_device *b43_ssb_gpio_d
+@@ -2734,7 +2734,7 @@ static struct ssb_device *b43_ssb_gpio_d
  {
        struct ssb_bus *bus = dev->dev->sdev->bus;
  
@@ -77,7 +77,7 @@
        return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
  #else
        return bus->chipco.dev;
-@@ -4735,7 +4735,7 @@ static int b43_wireless_core_init(struct
+@@ -4751,7 +4751,7 @@ static int b43_wireless_core_init(struct
        }
        if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
                hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
diff --git a/package/mac80211/patches/100-revert_aes_ccm_port.patch b/package/mac80211/patches/100-revert_aes_ccm_port.patch
new file mode 100644 (file)
index 0000000..4654bc8
--- /dev/null
@@ -0,0 +1,347 @@
+--- a/net/mac80211/Kconfig
++++ b/net/mac80211/Kconfig
+@@ -5,7 +5,6 @@ config MAC80211
+       depends on CRYPTO
+       depends on CRYPTO_ARC4
+       depends on CRYPTO_AES
+-      depends on CRYPTO_CCM
+       depends on CRC32
+       select BACKPORT_AVERAGE
+       ---help---
+--- a/net/mac80211/aes_ccm.c
++++ b/net/mac80211/aes_ccm.c
+@@ -2,8 +2,6 @@
+  * Copyright 2003-2004, Instant802 Networks, Inc.
+  * Copyright 2005-2006, Devicescape Software, Inc.
+  *
+- * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+- *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+@@ -19,75 +17,134 @@
+ #include "key.h"
+ #include "aes_ccm.h"
+-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+-                             u8 *data, size_t data_len, u8 *mic)
++static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a)
+ {
+-      struct scatterlist assoc, pt, ct[2];
+-      struct {
+-              struct aead_request     req;
+-              u8                      priv[crypto_aead_reqsize(tfm)];
+-      } aead_req;
+-
+-      memset(&aead_req, 0, sizeof(aead_req));
+-
+-      sg_init_one(&pt, data, data_len);
+-      sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
+-      sg_init_table(ct, 2);
+-      sg_set_buf(&ct[0], data, data_len);
+-      sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
+-
+-      aead_request_set_tfm(&aead_req.req, tfm);
+-      aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
+-      aead_request_set_crypt(&aead_req.req, &pt, ct, data_len, b_0);
++      int i;
++      u8 *b_0, *aad, *b, *s_0;
+-      crypto_aead_encrypt(&aead_req.req);
++      b_0 = scratch + 3 * AES_BLOCK_SIZE;
++      aad = scratch + 4 * AES_BLOCK_SIZE;
++      b = scratch;
++      s_0 = scratch + AES_BLOCK_SIZE;
++
++      crypto_cipher_encrypt_one(tfm, b, b_0);
++
++      /* Extra Authenticate-only data (always two AES blocks) */
++      for (i = 0; i < AES_BLOCK_SIZE; i++)
++              aad[i] ^= b[i];
++      crypto_cipher_encrypt_one(tfm, b, aad);
++
++      aad += AES_BLOCK_SIZE;
++
++      for (i = 0; i < AES_BLOCK_SIZE; i++)
++              aad[i] ^= b[i];
++      crypto_cipher_encrypt_one(tfm, a, aad);
++
++      /* Mask out bits from auth-only-b_0 */
++      b_0[0] &= 0x07;
++
++      /* S_0 is used to encrypt T (= MIC) */
++      b_0[14] = 0;
++      b_0[15] = 0;
++      crypto_cipher_encrypt_one(tfm, s_0, b_0);
+ }
+-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+-                            u8 *data, size_t data_len, u8 *mic)
++
++void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
++                             u8 *data, size_t data_len,
++                             u8 *cdata, u8 *mic)
+ {
+-      struct scatterlist assoc, pt, ct[2];
+-      struct {
+-              struct aead_request     req;
+-              u8                      priv[crypto_aead_reqsize(tfm)];
+-      } aead_req;
+-
+-      memset(&aead_req, 0, sizeof(aead_req));
+-
+-      sg_init_one(&pt, data, data_len);
+-      sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad));
+-      sg_init_table(ct, 2);
+-      sg_set_buf(&ct[0], data, data_len);
+-      sg_set_buf(&ct[1], mic, IEEE80211_CCMP_MIC_LEN);
+-
+-      aead_request_set_tfm(&aead_req.req, tfm);
+-      aead_request_set_assoc(&aead_req.req, &assoc, assoc.length);
+-      aead_request_set_crypt(&aead_req.req, ct, &pt,
+-                             data_len + IEEE80211_CCMP_MIC_LEN, b_0);
++      int i, j, last_len, num_blocks;
++      u8 *pos, *cpos, *b, *s_0, *e, *b_0;
++
++      b = scratch;
++      s_0 = scratch + AES_BLOCK_SIZE;
++      e = scratch + 2 * AES_BLOCK_SIZE;
++      b_0 = scratch + 3 * AES_BLOCK_SIZE;
++
++      num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
++      last_len = data_len % AES_BLOCK_SIZE;
++      aes_ccm_prepare(tfm, scratch, b);
++
++      /* Process payload blocks */
++      pos = data;
++      cpos = cdata;
++      for (j = 1; j <= num_blocks; j++) {
++              int blen = (j == num_blocks && last_len) ?
++                      last_len : AES_BLOCK_SIZE;
++
++              /* Authentication followed by encryption */
++              for (i = 0; i < blen; i++)
++                      b[i] ^= pos[i];
++              crypto_cipher_encrypt_one(tfm, b, b);
++
++              b_0[14] = (j >> 8) & 0xff;
++              b_0[15] = j & 0xff;
++              crypto_cipher_encrypt_one(tfm, e, b_0);
++              for (i = 0; i < blen; i++)
++                      *cpos++ = *pos++ ^ e[i];
++      }
+-      return crypto_aead_decrypt(&aead_req.req);
++      for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
++              mic[i] = b[i] ^ s_0[i];
+ }
+-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[])
++
++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
++                            u8 *cdata, size_t data_len, u8 *mic, u8 *data)
+ {
+-      struct crypto_aead *tfm;
+-      int err;
++      int i, j, last_len, num_blocks;
++      u8 *pos, *cpos, *b, *s_0, *a, *b_0;
+-      tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
+-      if (IS_ERR(tfm))
+-              return tfm;
+-
+-      err = crypto_aead_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
+-      if (!err)
+-              err = crypto_aead_setauthsize(tfm, IEEE80211_CCMP_MIC_LEN);
+-      if (!err)
+-              return tfm;
++      b = scratch;
++      s_0 = scratch + AES_BLOCK_SIZE;
++      a = scratch + 2 * AES_BLOCK_SIZE;
++      b_0 = scratch + 3 * AES_BLOCK_SIZE;
++
++      num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE);
++      last_len = data_len % AES_BLOCK_SIZE;
++      aes_ccm_prepare(tfm, scratch, a);
++
++      /* Process payload blocks */
++      cpos = cdata;
++      pos = data;
++      for (j = 1; j <= num_blocks; j++) {
++              int blen = (j == num_blocks && last_len) ?
++                      last_len : AES_BLOCK_SIZE;
++
++              /* Decryption followed by authentication */
++              b_0[14] = (j >> 8) & 0xff;
++              b_0[15] = j & 0xff;
++              crypto_cipher_encrypt_one(tfm, b, b_0);
++              for (i = 0; i < blen; i++) {
++                      *pos = *cpos++ ^ b[i];
++                      a[i] ^= *pos++;
++              }
++              crypto_cipher_encrypt_one(tfm, a, a);
++      }
++
++      for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) {
++              if ((mic[i] ^ s_0[i]) != a[i])
++                      return -1;
++      }
+-      crypto_free_aead(tfm);
+-      return ERR_PTR(err);
++      return 0;
+ }
+-void ieee80211_aes_key_free(struct crypto_aead *tfm)
++
++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
++{
++      struct crypto_cipher *tfm;
++
++      tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
++      if (!IS_ERR(tfm))
++              crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
++
++      return tfm;
++}
++
++
++void ieee80211_aes_key_free(struct crypto_cipher *tfm)
+ {
+-      crypto_free_aead(tfm);
++      crypto_free_cipher(tfm);
+ }
+--- a/net/mac80211/aes_ccm.h
++++ b/net/mac80211/aes_ccm.h
+@@ -12,11 +12,13 @@
+ #include <linux/crypto.h>
+-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[]);
+-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+-                             u8 *data, size_t data_len, u8 *mic);
+-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+-                            u8 *data, size_t data_len, u8 *mic);
+-void ieee80211_aes_key_free(struct crypto_aead *tfm);
++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]);
++void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
++                             u8 *data, size_t data_len,
++                             u8 *cdata, u8 *mic);
++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
++                            u8 *cdata, size_t data_len,
++                            u8 *mic, u8 *data);
++void ieee80211_aes_key_free(struct crypto_cipher *tfm);
+ #endif /* AES_CCM_H */
+--- a/net/mac80211/key.h
++++ b/net/mac80211/key.h
+@@ -84,7 +84,7 @@ struct ieee80211_key {
+                        * Management frames.
+                        */
+                       u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
+-                      struct crypto_aead *tfm;
++                      struct crypto_cipher *tfm;
+                       u32 replays; /* dot11RSNAStatsCCMPReplays */
+               } ccmp;
+               struct {
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -301,16 +301,22 @@ ieee80211_crypto_tkip_decrypt(struct iee
+ }
+-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
++static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
+                               int encrypted)
+ {
+       __le16 mask_fc;
+       int a4_included, mgmt;
+       u8 qos_tid;
+-      u16 len_a;
++      u8 *b_0, *aad;
++      u16 data_len, len_a;
+       unsigned int hdrlen;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++      memset(scratch, 0, 6 * AES_BLOCK_SIZE);
++
++      b_0 = scratch + 3 * AES_BLOCK_SIZE;
++      aad = scratch + 4 * AES_BLOCK_SIZE;
++
+       /*
+        * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
+        * Retry, PwrMgt, MoreData; set Protected
+@@ -332,21 +338,20 @@ static void ccmp_special_blocks(struct s
+       else
+               qos_tid = 0;
+-      /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
+-       * mode authentication are not allowed to collide, yet both are derived
+-       * from this vector b_0. We only set L := 1 here to indicate that the
+-       * data size can be represented in (L+1) bytes. The CCM layer will take
+-       * care of storing the data length in the top (L+1) bytes and setting
+-       * and clearing the other bits as is required to derive the two IVs.
+-       */
+-      b_0[0] = 0x1;
++      data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN;
++      if (encrypted)
++              data_len -= IEEE80211_CCMP_MIC_LEN;
++      /* First block, b_0 */
++      b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
+       /* Nonce: Nonce Flags | A2 | PN
+        * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
+        */
+       b_0[1] = qos_tid | (mgmt << 4);
+       memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
+       memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
++      /* l(m) */
++      put_unaligned_be16(data_len, &b_0[14]);
+       /* AAD (extra authenticate-only data) / masked 802.11 header
+        * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
+@@ -402,8 +407,7 @@ static int ccmp_encrypt_skb(struct ieee8
+       u8 *pos;
+       u8 pn[6];
+       u64 pn64;
+-      u8 aad[2 * AES_BLOCK_SIZE];
+-      u8 b_0[AES_BLOCK_SIZE];
++      u8 scratch[6 * AES_BLOCK_SIZE];
+       if (info->control.hw_key &&
+           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+@@ -456,9 +460,9 @@ static int ccmp_encrypt_skb(struct ieee8
+               return 0;
+       pos += IEEE80211_CCMP_HDR_LEN;
+-      ccmp_special_blocks(skb, pn, b_0, aad, 0);
+-      ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+-                                skb_put(skb, IEEE80211_CCMP_MIC_LEN));
++      ccmp_special_blocks(skb, pn, scratch, 0);
++      ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
++                                pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN));
+       return 0;
+ }
+@@ -521,16 +525,16 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+       }
+       if (!(status->flag & RX_FLAG_DECRYPTED)) {
+-              u8 aad[2 * AES_BLOCK_SIZE];
+-              u8 b_0[AES_BLOCK_SIZE];
++              u8 scratch[6 * AES_BLOCK_SIZE];
+               /* hardware didn't decrypt/verify MIC */
+-              ccmp_special_blocks(skb, pn, b_0, aad, 1);
++              ccmp_special_blocks(skb, pn, scratch, 1);
+               if (ieee80211_aes_ccm_decrypt(
+-                          key->u.ccmp.tfm, b_0, aad,
++                          key->u.ccmp.tfm, scratch,
+                           skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
+                           data_len,
+-                          skb->data + skb->len - IEEE80211_CCMP_MIC_LEN))
++                          skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
++                          skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
+                       return RX_DROP_UNUSABLE;
+       }
index 92c19099812f97d77bb25b827d1e96140d8d3ad8..7b50154e86611be35709dc411fd69d28930cd527 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/mac80211/main.c
 +++ b/net/mac80211/main.c
-@@ -300,7 +300,7 @@ void ieee80211_restart_hw(struct ieee802
+@@ -287,7 +287,7 @@ void ieee80211_restart_hw(struct ieee802
  }
  EXPORT_SYMBOL(ieee80211_restart_hw);
  
@@ -9,7 +9,7 @@
  static int ieee80211_ifa_changed(struct notifier_block *nb,
                                 unsigned long data, void *arg)
  {
-@@ -359,7 +359,7 @@ static int ieee80211_ifa_changed(struct 
+@@ -346,7 +346,7 @@ static int ieee80211_ifa_changed(struct 
  }
  #endif
  
@@ -18,7 +18,7 @@
  static int ieee80211_ifa6_changed(struct notifier_block *nb,
                                  unsigned long data, void *arg)
  {
-@@ -990,14 +990,14 @@ int ieee80211_register_hw(struct ieee802
+@@ -1031,14 +1031,14 @@ int ieee80211_register_hw(struct ieee802
                goto fail_pm_qos;
        }
  
@@ -35,7 +35,7 @@
        local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
        result = register_inet6addr_notifier(&local->ifa6_notifier);
        if (result)
-@@ -1006,13 +1006,13 @@ int ieee80211_register_hw(struct ieee802
+@@ -1047,13 +1047,13 @@ int ieee80211_register_hw(struct ieee802
  
        return 0;
  
@@ -52,7 +52,7 @@
   fail_ifa:
        pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
                               &local->network_latency_notifier);
-@@ -1045,10 +1045,10 @@ void ieee80211_unregister_hw(struct ieee
+@@ -1086,10 +1086,10 @@ void ieee80211_unregister_hw(struct ieee
  
        pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY,
                               &local->network_latency_notifier);
index d9672d473f87b307b1a05ee3065331591f7c050e..21516ffde905c949713bb8f9dbdaf44cfc59bff8 100644 (file)
@@ -17,7 +17,7 @@
        { AR5K_RXNOFRM,         8 },
 --- a/drivers/net/wireless/ath/ath5k/dma.c
 +++ b/drivers/net/wireless/ath/ath5k/dma.c
-@@ -860,10 +860,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
+@@ -869,10 +869,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 73f440bd3b99b9354bb932ce451069e4f03ce70f..1da7941d21d155039520685cd9e5aa01e0e15d7d 100644 (file)
---- a/net/mac80211/agg-rx.c
-+++ b/net/mac80211/agg-rx.c
-@@ -204,6 +204,8 @@ static void ieee80211_send_addba_resp(st
-               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-       else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-               memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
-+      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);
+commit 584d297fd29fb39c76af25ae74ff9d5fe74c8a14
+Author: Helmut Schaa <helmut.schaa@googlemail.com>
+Date:   Wed Mar 12 10:37:55 2014 +0100
+
+    ath9k: Fix sequence number assignment for non-data frames
+    
+    Since commit 558ff225de80ac95b132d3a115ddadcd64498b4f (ath9k: fix
+    ps-poll responses under a-mpdu sessions) non-data frames would have
+    gotten a sequence number from a TIDs sequence counter instead of
+    using the global sequence counter.
+    
+    This can lead to instable connections.
+    
+    To fix this only select the correct TID if we are processing a
+    data frame. Furthermore, prevent non-data frames to get a sequence
+    number from a TID sequence counter by adding a check to
+    ath_tx_setup_buffer.
+    
+    Cc: Felix Fietkau <nbd@openwrt.org>
+    Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
+
+commit 3a0f984b1cdcd6a9f8c441635ef3b05d58547f4e
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Tue Mar 11 14:03:32 2014 +0100
+
+    ath9k_hw: set ANI firstep as absolute values instead of relative
+    
+    On older chips, the INI value differ in similar ways as cycpwr_thr1, so
+    convert it to absolute values as well.
+    
+    Since the ANI algorithm is different here compared to the old
+    implementation (fewer steps, controlled at a different point in time),
+    it makes sense to use values similar to what would be applied for newer
+    chips, just without relying on INI defaults.
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 91d70d40400c569b49605b78fd7c43e9405694f4
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Tue Mar 11 14:00:37 2014 +0100
+
+    ath9k_hw: set ANI cycpwr_thr1 as absolute values instead of relative
+    
+    The table was copied from the ANI implementation of AR9300. It assumes
+    that the INI values contain a baseline value that is usable as reference
+    from which to increase/decrease based on the noise immunity value.
+    
+    On older chips, the differences are bigger and especially AR5008/AR9001
+    are configured to much more sensitive values than what is useful.
+    
+    Improve ANI behavior by reverting to the absolute values used in the
+    previous implementation (expressed as a simple formula instead of the
+    old table).
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit c977493766310a825f406836636ffd66e1447783
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Mon Mar 10 19:52:56 2014 +0100
+
+    ath9k_hw: remove ANI function restrictions for AP mode
+    
+    The primary purpose of this piece of code was to selectively disable
+    OFDM weak signal detection. The checks for this are elsewhere, and an
+    earlier commit relaxed the restrictions for older chips, which are more
+    sensitive to interference.
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 8d804f1af11e4e058b1e8453327777d73a585cb8
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun Mar 9 11:25:43 2014 +0100
+
+    ath9k: clean up and enhance ANI debugfs file
+    
+    Unify scnprintf calls and include the current OFDM/CCK immunity level.
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 22e298b5a3a8a49e33805d4e351965123dede35b
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun Mar 9 10:58:47 2014 +0100
+
+    ath9k: fix ready time of the multicast buffer queue
+    
+    qi->tqi_readyTime is written directly to registers that expect
+    microseconds as unit instead of TU.
+    When setting the CABQ ready time, cur_conf->beacon_interval is in TU, so
+    convert it to microseconds before passing it to ath9k_hw.
+    
+    This should hopefully fix some Tx DMA issues with buffered multicast
+    frames in AP mode.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit fcb064fdd5a27bec8d24099bc0172468f34c97cb
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun Mar 9 09:43:09 2014 +0100
+
+    ath9k_hw: fix unreachable code in baseband hang detection code
+    
+    The commit "ath9k: reduce baseband hang detection false positive rate"
+    added a delay in the loop checking the baseband state, however it was
+    unreachable due to previous 'continue' statements.
+    
+    Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 31959d8df39319e32c6d5ba9c135727be90cfad7
+Author: Michal Kazior <michal.kazior@tieto.com>
+Date:   Fri Mar 7 08:09:38 2014 +0100
+
+    mac80211: fix possible NULL dereference
+    
+    If chanctx is missing on a given vif then the band
+    is assumed to be 2GHz. However if hw doesn't
+    support 2GHz band then mac80211 ended up with a
+    NULL dereference.
+    
+    This fixes a splat:
+    
+    [ 4605.207223] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
+    [ 4605.210789] IP: [<ffffffffa07b5635>] ieee80211_parse_bitrates+0x65/0x110 [mac80211]
+    
+    The splat was preceeded by WARN_ON(!chanctx_conf)
+    in ieee80211_get_sdata_band().
+    
+    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+
+commit 6c5a3ffa0a2d22c091a2717f427259bacf77ac5e
+Author: Michael Braun <michael-dev@fami-braun.de>
+Date:   Thu Mar 6 15:08:43 2014 +0100
+
+    mac80211: fix WPA with VLAN on AP side with ps-sta again
+    
+    commit de74a1d9032f4d37ea453ad2a647e1aff4cd2591
+      "mac80211: fix WPA with VLAN on AP side with ps-sta"
+    fixed an issue where queued multicast packets would
+    be sent out encrypted with the key of an other bss.
+    
+    commit "7cbf9d017dbb5e3276de7d527925d42d4c11e732"
+      "mac80211: fix oops on mesh PS broadcast forwarding"
+    essentially reverted it, because vif.type cannot be AP_VLAN
+    due to the check to vif.type in ieee80211_get_buffered_bc before.
+    
+    As the later commit intended to fix the MESH case, fix it
+    by checking for IFTYPE_AP instead of IFTYPE_AP_VLAN.
+    
+    Fixes: 7cbf9d017dbb
+    Cc: <stable@vger.kernel.org> # 3.10.x
+    Cc: <stable@vger.kernel.org> # 3.11.x
+    Cc: <stable@vger.kernel.org> # 3.12.x
+    Cc: <stable@vger.kernel.org> # 3.13.x
+    Cc: <linux-wireless@vger.kernel.org>
+    Cc: <projekt-wlan@fem.tu-ilmenau.de>
+    Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
+
+commit 9d6ab9bdb9b368a6cf9519f0f92509b5b2c297ec
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Mon Mar 3 14:19:08 2014 +0100
+
+    cfg80211: remove racy beacon_interval assignment
+    
+    In case of AP mode, the beacon interval is already reset to
+    zero inside cfg80211_stop_ap(), and in the other modes it
+    isn't relevant. Remove the assignment to remove a potential
+    race since the assignment isn't properly locked.
+    
+    Reported-by: Michal Kazior <michal.kazior@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 1abdeca3c6fb9cf1f84f85e78ed8d1c33bd69db0
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Fri Feb 28 18:52:56 2014 +0100
+
+    ath9k_hw: tweak noise immunity thresholds for older chipsets
+    
+    Older chipsets are more sensitive to high PHY error counts, and the
+    current noise immunity thresholds were based on tests run at QCA with
+    newer chipsets.
+    
+    This patch brings back the values from the old ANI implementation for
+    old chipsets, and it also disables weak signal detection on an earlier
+    noise immunity level, to improve overall radio stability on affected
+    devices.
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 431e506da5953adc3b65af25f4b90873d528c115
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Fri Feb 28 18:44:13 2014 +0100
+
+    ath9k_hw: toggle weak signal detection in AP mode on older chipsets
+    
+    The commit 80b4205b "ath9k: Fix OFDM weak signal detection for AP mode"
+    prevented weak signal detection changes from taking effect in AP mode on
+    all chipsets, claiming it is "not allowed".
+    
+    The main reason for not disabling weak signal detection in AP mode is
+    that typically beacon RSSI is used to track whether it is needed to
+    boost range, and this is unavailable in AP mode for obvious reasons.
+    
+    The problem with not disabling weak signal detection is that older
+    chipsets are very sensitive to high PHY error counts. When faced with
+    heavy noise, this can lead to an excessive amount of "Failed to stop
+    TX DMA" errors in the field.
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 98d1a6c5b14688ed030e81b889f607be308e0df9
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Mon Feb 24 22:20:32 2014 +0100
+
+    ath9k: fix invalid descriptor discarding
+    
+    Only set sc->rx.discard_next to rx_stats->rs_more when actually
+    discarding the current descriptor.
+    
+    Also, fix a detection of broken descriptors:
+    First the code checks if the current descriptor is not done.
+    Then it checks if the next descriptor is done.
+    Add a check that afterwards checks the first descriptor again, because
+    it might have been completed in the mean time.
+    
+    This fixes a regression introduced in
+    commit 723e711356b5a8a95728a890e254e8b0d47b55cf
+    "ath9k: fix handling of broken descriptors"
+    
+    Cc: stable@vger.kernel.org
+    Reported-by: Marco André Dinis <marcoandredinis@gmail.com>
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 52a46300e782fe6994466523eb2b0b59091ea59f
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Mon Feb 24 11:43:50 2014 +0100
+
+    ath9k: reduce baseband hang detection false positive rate
+    
+    Check if the baseband state remains stable, and add a small delay
+    between register reads.
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 118945bb12082e9d4edddc868d88143164e0f440
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sat Feb 22 14:55:23 2014 +0100
+
+    ath5k: set SURVEY_INFO_IN_USE on get_survey
+    
+    Only one channel is returned - the one currently being used.
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit ee41f72476e1ea44283dfe1cbf75b9543a1e15c8
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sat Feb 22 14:44:52 2014 +0100
+
+    ath9k: make some hardware reset log messages debug-only
+    
+    On some chips, baseband watchdog hangs are more common than others, and
+    the driver has support for handling them.
+    Interrupts even after a watchdog hang are also quite common, so there's
+    not much point in spamming the user's logfiles.
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit b14fbb554fc65a2e0b5c41a319269b0350f187e7
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sat Feb 22 14:35:25 2014 +0100
+
+    ath9k: do not set half/quarter channel flags in AR_PHY_MODE
+    
+    5/10 MHz channel bandwidth is configured via the PLL clock, instead of
+    the AR_PHY_MODE register. Using that register is AR93xx specific, and
+    makes the mode incompatible with earlier chipsets.
+    
+    In some early versions, these flags were apparently applied at the wrong
+    point in time and thus did not cause connectivity issues, however now
+    they are causing problems, as pointed out in this OpenWrt ticket:
+    
+    https://dev.openwrt.org/ticket/14916
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit 0f1cb7be2551b30b02cd54c897e0e29e483cfda5
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sat Feb 22 13:43:29 2014 +0100
+
+    ath9k: fix ps-poll responses under a-mpdu sessions
+    
+    When passing tx frames to the U-APSD queue for powersave poll responses,
+    the ath_atx_tid pointer needs to be passed to ath_tx_setup_buffer for
+    proper sequence number accounting.
+    
+    This fixes high latency and connection stability issues with ath9k
+    running as AP and a few kinds of mobile phones as client, when PS-Poll
+    is heavily used
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit d5d87a37bbd6066b2c3c5d0bd0fe2a6e2ea45cc5
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Fri Feb 21 11:39:59 2014 +0100
+
+    ath9k: list more reset causes in debugfs
+    
+    Number of MAC hangs and stuck beacons were missing
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit d84856012e0f10fe598a5ad3b7b869397a089e07
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Thu Feb 20 11:19:58 2014 +0100
+
+    mac80211: fix station wakeup powersave race
+    
+    Consider the following (relatively unlikely) scenario:
+     1) station goes to sleep while frames are buffered in driver
+     2) driver blocks wakeup (until no more frames are buffered)
+     3) station wakes up again
+     4) driver unblocks wakeup
+    
+    In this case, the current mac80211 code will do the following:
+     1) WLAN_STA_PS_STA set
+     2) WLAN_STA_PS_DRIVER set
+     3) - nothing -
+     4) WLAN_STA_PS_DRIVER cleared
+    
+    As a result, no frames will be delivered to the client, even
+    though it is awake, until it sends another frame to us that
+    triggers ieee80211_sta_ps_deliver_wakeup() in sta_ps_end().
+    
+    Since we now take the PS spinlock, we can fix this while at
+    the same time removing the complexity with the pending skb
+    queue function. This was broken since my commit 50a9432daeec
+    ("mac80211: fix powersaving clients races") due to removing
+    the clearing of WLAN_STA_PS_STA in the RX path.
+    
+    While at it, fix a cleanup path issue when a station is
+    removed while the driver is still blocking its wakeup.
+    
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 798f2786602cbe93e6b928299614aa36ebf50692
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Mon Feb 17 20:49:03 2014 +0100
+
+    mac80211: insert stations before adding to driver
+    
+    There's a race condition in mac80211 because we add stations
+    to the internal lists after adding them to the driver, which
+    means that (for example) the following can happen:
+     1. a station connects and is added
+     2. first, it is added to the driver
+     3. then, it is added to the mac80211 lists
+    
+    If the station goes to sleep between steps 2 and 3, and the
+    firmware/hardware records it as being asleep, mac80211 will
+    never instruct the driver to wake it up again as it never
+    realized it went to sleep since the RX path discarded the
+    frame as a "spurious class 3 frame", no station entry was
+    present yet.
+    
+    Fix this by adding the station in software first, and only
+    then adding it to the driver. That way, any state that the
+    driver changes will be reflected properly in mac80211's
+    station state. The problematic part is the roll-back if the
+    driver fails to add the station, in that case a bit more is
+    needed. To not make that overly complex prevent starting BA
+    sessions in the meantime.
+    
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit b9ba6a520cb07ab3aa7aaaf9ce4a0bc7a6bc06fe
+Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Date:   Thu Feb 20 09:22:11 2014 +0200
+
+    mac80211: fix AP powersave TX vs. wakeup race
+    
+    There is a race between the TX path and the STA wakeup: while
+    a station is sleeping, mac80211 buffers frames until it wakes
+    up, then the frames are transmitted. However, the RX and TX
+    path are concurrent, so the packet indicating wakeup can be
+    processed while a packet is being transmitted.
+    
+    This can lead to a situation where the buffered frames list
+    is emptied on the one side, while a frame is being added on
+    the other side, as the station is still seen as sleeping in
+    the TX path.
+    
+    As a result, the newly added frame will not be send anytime
+    soon. It might be sent much later (and out of order) when the
+    station goes to sleep and wakes up the next time.
+    
+    Additionally, it can lead to the crash below.
+    
+    Fix all this by synchronising both paths with a new lock.
+    Both path are not fastpath since they handle PS situations.
+    
+    In a later patch we'll remove the extra skb queue locks to
+    reduce locking overhead.
+    
+    BUG: unable to handle kernel
+    NULL pointer dereference at 000000b0
+    IP: [<ff6f1791>] ieee80211_report_used_skb+0x11/0x3e0 [mac80211]
+    *pde = 00000000
+    Oops: 0000 [#1] SMP DEBUG_PAGEALLOC
+    EIP: 0060:[<ff6f1791>] EFLAGS: 00210282 CPU: 1
+    EIP is at ieee80211_report_used_skb+0x11/0x3e0 [mac80211]
+    EAX: e5900da0 EBX: 00000000 ECX: 00000001 EDX: 00000000
+    ESI: e41d00c0 EDI: e5900da0 EBP: ebe458e4 ESP: ebe458b0
+     DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
+    CR0: 8005003b CR2: 000000b0 CR3: 25a78000 CR4: 000407d0
+    DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
+    DR6: ffff0ff0 DR7: 00000400
+    Process iperf (pid: 3934, ti=ebe44000 task=e757c0b0 task.ti=ebe44000)
+    iwlwifi 0000:02:00.0: I iwl_pcie_enqueue_hcmd Sending command LQ_CMD (#4e), seq: 0x0903, 92 bytes at 3[3]:9
+    Stack:
+     e403b32c ebe458c4 00200002 00200286 e403b338 ebe458cc c10960bb e5900da0
+     ff76a6ec ebe458d8 00000000 e41d00c0 e5900da0 ebe458f0 ff6f1b75 e403b210
+     ebe4598c ff723dc1 00000000 ff76a6ec e597c978 e403b758 00000002 00000002
+    Call Trace:
+     [<ff6f1b75>] ieee80211_free_txskb+0x15/0x20 [mac80211]
+     [<ff723dc1>] invoke_tx_handlers+0x1661/0x1780 [mac80211]
+     [<ff7248a5>] ieee80211_tx+0x75/0x100 [mac80211]
+     [<ff7249bf>] ieee80211_xmit+0x8f/0xc0 [mac80211]
+     [<ff72550e>] ieee80211_subif_start_xmit+0x4fe/0xe20 [mac80211]
+     [<c149ef70>] dev_hard_start_xmit+0x450/0x950
+     [<c14b9aa9>] sch_direct_xmit+0xa9/0x250
+     [<c14b9c9b>] __qdisc_run+0x4b/0x150
+     [<c149f732>] dev_queue_xmit+0x2c2/0xca0
+    
+    Cc: stable@vger.kernel.org
+    Reported-by: Yaara Rozenblum <yaara.rozenblum@intel.com>
+    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+    Reviewed-by: Stanislaw Gruszka <sgruszka@redhat.com>
+    [reword commit log, use a separate lock]
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 80e419de0dff38436b30d363311c625766193f86
+Author: Inbal Hacohen <Inbal.Hacohen@intel.com>
+Date:   Wed Feb 12 09:32:27 2014 +0200
+
+    cfg80211: bugfix in regulatory user hint process
+    
+    After processing hint_user, we would want to schedule the
+    timeout work only if we are actually waiting to CRDA. This happens
+    when the status is not "IGNORE" nor "ALREADY_SET".
+    
+    Signed-off-by: Inbal Hacohen <Inbal.Hacohen@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 6514c93afede55284e2cb63359aadedb85884c80
+Author: Jouni Malinen <jouni@qca.qualcomm.com>
+Date:   Tue Feb 18 20:41:08 2014 +0200
+
+    ath9k: Enable U-APSD AP mode support
+    
+    mac80211 handles the actual operations, so ath9k can just indicate
+    support for this. Based on initial tests, this combination seems to
+    work fine.
+    
+    Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
+
+commit a63caf0a357ad5c1f08d6b7827dc76c451445017
+Author: Stanislaw Gruszka <sgruszka@redhat.com>
+Date:   Wed Feb 19 13:15:17 2014 +0100
+
+    ath9k: protect tid->sched check
+    
+    We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That
+    is race condition which can result of doing list_del(&tid->list) twice
+    (second time with poisoned list node) and cause crash like shown below:
+    
+    [424271.637220] BUG: unable to handle kernel paging request at 00100104
+    [424271.637328] IP: [<f90fc072>] ath_tx_aggr_sleep+0x62/0xe0 [ath9k]
+    ...
+    [424271.639953] Call Trace:
+    [424271.639998]  [<f90f6900>] ? ath9k_get_survey+0x110/0x110 [ath9k]
+    [424271.640083]  [<f90f6942>] ath9k_sta_notify+0x42/0x50 [ath9k]
+    [424271.640177]  [<f809cfef>] sta_ps_start+0x8f/0x1c0 [mac80211]
+    [424271.640258]  [<c10f730e>] ? free_compound_page+0x2e/0x40
+    [424271.640346]  [<f809e915>] ieee80211_rx_handlers+0x9d5/0x2340 [mac80211]
+    [424271.640437]  [<c112f048>] ? kmem_cache_free+0x1d8/0x1f0
+    [424271.640510]  [<c1345a84>] ? kfree_skbmem+0x34/0x90
+    [424271.640578]  [<c10fc23c>] ? put_page+0x2c/0x40
+    [424271.640640]  [<c1345a84>] ? kfree_skbmem+0x34/0x90
+    [424271.640706]  [<c1345a84>] ? kfree_skbmem+0x34/0x90
+    [424271.640787]  [<f809dde3>] ? ieee80211_rx_handlers_result+0x73/0x1d0 [mac80211]
+    [424271.640897]  [<f80a07a0>] ieee80211_prepare_and_rx_handle+0x520/0xad0 [mac80211]
+    [424271.641009]  [<f809e22d>] ? ieee80211_rx_handlers+0x2ed/0x2340 [mac80211]
+    [424271.641104]  [<c13846ce>] ? ip_output+0x7e/0xd0
+    [424271.641182]  [<f80a1057>] ieee80211_rx+0x307/0x7c0 [mac80211]
+    [424271.641266]  [<f90fa6ee>] ath_rx_tasklet+0x88e/0xf70 [ath9k]
+    [424271.641358]  [<f80a0f2c>] ? ieee80211_rx+0x1dc/0x7c0 [mac80211]
+    [424271.641445]  [<f90f82db>] ath9k_tasklet+0xcb/0x130 [ath9k]
+    
+    Bug report:
+    https://bugzilla.kernel.org/show_bug.cgi?id=70551
+    
+    Reported-and-tested-by: Max Sydorenko <maxim.stargazer@gmail.com>
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+
+commit 82ed9e3ccc02797df2ffe4b78127c4cd5f799a41
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Tue Feb 11 15:54:13 2014 +0100
+
+    mac80211: send control port protocol frames to the VO queue
+    
+    Improves reliability of wifi connections with WPA, since authentication
+    frames are prioritized over normal traffic and also typically exempt
+    from aggregation.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit d4426800f71e972feaa33e04c5801fc730627bdd
+Author: Stanislaw Gruszka <stf_xl@wp.pl>
+Date:   Mon Feb 10 22:38:28 2014 +0100
+
+    rtl8187: fix regression on MIPS without coherent DMA
+    
+    This patch fixes regression caused by commit a16dad77634 "MIPS: Fix
+    potencial corruption". That commit fixes one corruption scenario in
+    cost of adding another one, which actually start to cause crashes
+    on Yeeloong laptop when rtl8187 driver is used.
+    
+    For correct DMA read operation on machines without DMA coherence, kernel
+    have to invalidate cache, such it will refill later with new data that
+    device wrote to memory, when that data is needed to process. We can only
+    invalidate full cache line. Hence when cache line includes both dma
+    buffer and some other data (written in cache, but not yet in main
+    memory), the other data can not hit memory due to invalidation. That
+    happen on rtl8187 where struct rtl8187_priv fields are located just
+    before and after small buffers that are passed to USB layer and DMA
+    is performed on them.
+    
+    To fix the problem we align buffers and reserve space after them to make
+    them match cache line.
+    
+    This patch does not resolve all possible MIPS problems entirely, for
+    that we have to assure that we always map cache aligned buffers for DMA,
+    what can be complex or even not possible. But patch fixes visible and
+    reproducible regression and seems other possible corruptions do not
+    happen in practice, since Yeeloong laptop works stable without rtl8187
+    driver.
+    
+    Bug report:
+    https://bugzilla.kernel.org/show_bug.cgi?id=54391
+    
+    Reported-by: Petr Pisar <petr.pisar@atlas.cz>
+    Bisected-by: Tom Li <biergaizi2009@gmail.com>
+    Reported-and-tested-by: Tom Li <biergaizi2009@gmail.com>
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
+
+commit e2f141d67ad1e7fe10aaab61811e8a409dfb2442
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Fri Feb 7 10:29:55 2014 +0530
+
+    ath9k: Calculate IQ-CAL median
+    
+    This patch adds a routine to calculate the median IQ correction
+    values for AR955x, which is used for outlier detection.
+    The normal method which is used for all other chips is
+    bypassed for AR955x.
+    
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit c52a6fce0820c8d0687443ab86058ae03b478c8f
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Fri Feb 7 10:29:54 2014 +0530
+
+    ath9k: Expand the IQ coefficient array
+    
+    This will be used for storing data for mutiple
+    IQ calibration runs, for AR955x.
+    
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 034969ff5c2b6431d10e07c1938f0b916da85cc3
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Fri Feb 7 10:29:53 2014 +0530
+
+    ath9k: Modify IQ calibration for AR955x
+    
+    IQ calibration post-processing for AR955x is different
+    from other chips - instead of just doing it as part
+    of AGC calibration once, it is triggered 3 times and
+    a median is determined. This patch adds initial support
+    for changing the calibration behavior for AR955x.
+    
+    Also, to simplify things, a helper routine to issue/poll
+    AGC calibration is used.
+    
+    For non-AR955x chips, the iqcal_idx (which will be used
+    in subsequent patches) is set to zero.
+    
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 9b1ed6454e6f3511f24266be99b4e403f243f6a8
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Fri Feb 7 10:29:52 2014 +0530
+
+    ath9k: Fix magnitude/phase calculation
+    
+    Incorrect values are programmed in the registers
+    containing the IQ correction coefficients by the IQ-CAL
+    post-processing code. Fix this.
+    
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 36f93484f96f79171dcecb67c5ef0c3de22531a6
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Fri Feb 7 10:29:51 2014 +0530
+
+    ath9k: Rename ar9003_hw_tx_iqcal_load_avg_2_passes
+    
+    Use ar9003_hw_tx_iq_cal_outlier_detection instead.
+    
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 3af09a7f5d21dd5fd15b973ce6a91a575da30417
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Fri Feb 7 10:29:50 2014 +0530
+
+    ath9k: Check explicitly for IQ calibration
+    
+    In chips like AR955x, the initvals contain the information
+    whether IQ calibration is to be done in the HW when an
+    AGC calibration is triggered. Check if IQ-CAL is enabled
+    in the initvals before flagging 'txiqcal_done' as true.
+    
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit cb4969634b93c4643a32cc3fbd27d2b288b25771
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Fri Feb 7 10:29:49 2014 +0530
+
+    ath9k: Fix IQ cal post processing for SoC
+    
+    Calibration data is not reused for SoC chips, so
+    call ar9003_hw_tx_iq_cal_post_proc() with the correct
+    argument. The 'is_reusable' flag is currently used
+    only for PC-OEM chips, but it makes things clearer to
+    specify it explicity.
+    
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit e138e0ef9560c46ce93dbb22a728a57888e94d1c
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Mon Feb 3 13:31:37 2014 +0530
+
+    ath9k: Fix TX power calculation
+    
+    The commit, "ath9k_hw: Fix incorrect Tx control power in AR9003 template"
+    fixed the incorrect values in the eeprom templates, but if
+    boards have already been calibrated with incorrect values,
+    they would still be using the wrong TX power. Fix this by assigning
+    a default value in such cases.
+    
+    Cc: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit b9f268b5b01331c3c82179abca551429450e9417
+Author: Michal Kazior <michal.kazior@tieto.com>
+Date:   Wed Jan 29 14:22:27 2014 +0100
+
+    cfg80211: consider existing DFS interfaces
+    
+    It was possible to break interface combinations in
+    the following way:
+    
+     combo 1: iftype = AP, num_ifaces = 2, num_chans = 2,
+     combo 2: iftype = AP, num_ifaces = 1, num_chans = 1, radar = HT20
+    
+    With the above interface combinations it was
+    possible to:
+    
+     step 1. start AP on DFS channel by matching combo 2
+     step 2. start AP on non-DFS channel by matching combo 1
+    
+    This was possible beacuse (step 2) did not consider
+    if other interfaces require radar detection.
+    
+    The patch changes how cfg80211 tracks channels -
+    instead of channel itself now a complete chandef
+    is stored.
+    
+    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit bc9c62f5f511cc395c62dbf4cdd437f23db53b28
+Author: Antonio Quartulli <antonio@open-mesh.com>
+Date:   Wed Jan 29 17:53:43 2014 +0100
+
+    cfg80211: fix channel configuration in IBSS join
+    
+    When receiving an IBSS_JOINED event select the BSS object
+    based on the {bssid, channel} couple rather than the bssid
+    only.
+    With the current approach if another cell having the same
+    BSSID (but using a different channel) exists then cfg80211
+    picks up the wrong BSS object.
+    The result is a mismatching channel configuration between
+    cfg80211 and the driver, that can lead to any sort of
+    problem.
+    
+    The issue can be triggered by having an IBSS sitting on
+    given channel and then asking the driver to create a new
+    cell using the same BSSID but with a different frequency.
+    By passing the channel to cfg80211_get_bss() we can solve
+    this ambiguity and retrieve/create the correct BSS object.
+    All the users of cfg80211_ibss_joined() have been changed
+    accordingly.
+    
+    Moreover WARN when cfg80211_ibss_joined() gets a NULL
+    channel as argument and remove a bogus call of the same
+    function in ath6kl (it does not make sense to call
+    cfg80211_ibss_joined() with a zero BSSID on ibss-leave).
+    
+    Cc: Kalle Valo <kvalo@qca.qualcomm.com>
+    Cc: Arend van Spriel <arend@broadcom.com>
+    Cc: Bing Zhao <bzhao@marvell.com>
+    Cc: Jussi Kivilinna <jussi.kivilinna@iki.fi>
+    Cc: libertas-dev@lists.infradead.org
+    Acked-by: Kalle Valo <kvalo@qca.qualcomm.com>
+    Signed-off-by: Antonio Quartulli <antonio@open-mesh.com>
+    [minor code cleanup in ath6kl]
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 7e0c41cb41f215aba2c39b1c237bb4d42ec49a85
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Fri Jan 24 14:41:44 2014 +0100
+
+    mac80211: fix bufferable MMPDU RX handling
+    
+    Action, disassoc and deauth frames are bufferable, and as such don't
+    have the PM bit in the frame control field reserved which means we
+    need to react to the bit when receiving in such a frame.
+    
+    Fix this by introducing a new helper ieee80211_is_bufferable_mmpdu()
+    and using it for the RX path that currently ignores the PM bit in
+    any non-data frames for doze->wake transitions, but listens to it in
+    all frames for wake->doze transitions, both of which are wrong.
+    
+    Also use the new helper in the TX path to clean up the code.
+    
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit fc0df6d2343636e3f48a069330d5b972e3d8659d
+Author: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+Date:   Fri Jan 24 14:29:21 2014 +0100
+
+    cfg80211: set preset_chandef after channel switch
+    
+    Set preset_chandef in channel switch notification.
+    In other case we will have old preset_chandef.
+    
+    Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit cdec895e2344987ff171cece96e25d7407a3ebf6
+Author: Simon Wunderlich <simon@open-mesh.com>
+Date:   Fri Jan 24 23:48:29 2014 +0100
+
+    mac80211: send ibss probe responses with noack flag
+    
+    Responding to probe requests for scanning clients will often create
+    excessive retries, as it happens quite often that the scanning client
+    already left the channel. Therefore do it like hostapd and send probe
+    responses for wildcard SSID only once by using the noack flag.
+    
+    Signed-off-by: Simon Wunderlich <simon@open-mesh.com>
+    [fix typo & 'wildcard SSID' in commit log]
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 0b865d1e6b9c05052adae9315df7cb195dc60c3b
+Author: Luciano Coelho <luciano.coelho@intel.com>
+Date:   Tue Jan 28 17:09:08 2014 +0200
+
+    mac80211: ibss: remove unnecessary call to release channel
+    
+    The ieee80211_vif_use_channel() function calls
+    ieee80211_vif_release_channel(), so there's no need to call it
+    explicitly in __ieee80211_sta_join_ibss().
+    
+    Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit e1b6c17e971f0a51ff86c2dac2584c63cd999cd7
+Author: Michal Kazior <michal.kazior@tieto.com>
+Date:   Wed Jan 29 07:56:21 2014 +0100
+
+    mac80211: add missing CSA locking
+    
+    The patch adds a missing sdata lock and adds a few
+    lockdeps for easier maintenance.
+    
+    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit ad17ba7d14d225b109b73c177cd446afb8050598
+Author: Michal Kazior <michal.kazior@tieto.com>
+Date:   Wed Jan 29 07:56:20 2014 +0100
+
+    mac80211: fix sdata->radar_required locking
+    
+    radar_required setting wasn't protected by
+    local->mtx in some places. This should prevent
+    from scanning/radar detection/roc colliding.
+    
+    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 5fcd5f1808813a3d9e502fd756e01bee8a79c85d
+Author: Michal Kazior <michal.kazior@tieto.com>
+Date:   Wed Jan 29 07:56:19 2014 +0100
+
+    mac80211: move csa_active setting in STA CSA
+    
+    The sdata->vif.csa_active could be left set after,
+    e.g. channel context constraints check fail in STA
+    mode leaving the interface in a strange state for
+    a brief period of time until it is disconnected.
+    This was harmless but ugly.
+    
+    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+    Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit e486da4b7eed71821c6b4c1bb9ac62ffd3ab13e9
+Author: Michal Kazior <michal.kazior@tieto.com>
+Date:   Wed Jan 29 07:56:18 2014 +0100
+
+    mac80211: fix possible memory leak on AP CSA failure
+    
+    If CSA for AP interface failed and the interface
+    was not stopped afterwards another CSA request
+    would leak sdata->u.ap.next_beacon.
+    
+    Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
+    Reviewed-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 3a77ba08940682bf3d52cf14f980337324af9d4a
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Sat Feb 1 00:33:29 2014 +0100
+
+    mac80211: fix fragmentation code, particularly for encryption
+    
+    The "new" fragmentation code (since my rewrite almost 5 years ago)
+    erroneously sets skb->len rather than using skb_trim() to adjust
+    the length of the first fragment after copying out all the others.
+    This leaves the skb tail pointer pointing to after where the data
+    originally ended, and thus causes the encryption MIC to be written
+    at that point, rather than where it belongs: immediately after the
+    data.
+    
+    The impact of this is that if software encryption is done, then
+     a) encryption doesn't work for the first fragment, the connection
+        becomes unusable as the first fragment will never be properly
+        verified at the receiver, the MIC is practically guaranteed to
+        be wrong
+     b) we leak up to 8 bytes of plaintext (!) of the packet out into
+        the air
+    
+    This is only mitigated by the fact that many devices are capable
+    of doing encryption in hardware, in which case this can't happen
+    as the tail pointer is irrelevant in that case. Additionally,
+    fragmentation is not used very frequently and would normally have
+    to be configured manually.
+    
+    Fix this by using skb_trim() properly.
+    
+    Cc: stable@vger.kernel.org
+    Fixes: 2de8e0d999b8 ("mac80211: rewrite fragmentation")
+    Reported-by: Jouni Malinen <j@w1.fi>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit de5f242e0c10e841017e37eb8c38974a642dbca8
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date:   Tue Jan 28 06:21:59 2014 +0530
+
+    ath9k: Fix build error on ARM
+    
+    Use mdelay instead of udelay to fix this error:
+    
+    ERROR: "__bad_udelay" [drivers/net/wireless/ath/ath9k/ath9k_hw.ko] undefined!
+    make[1]: *** [__modpost] Error 1
+    make: *** [modules] Error 2
+    
+    Reported-by: Josh Boyer <jwboyer@fedoraproject.org>
+    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 8e3ea7a51dfc61810fcefd947f6edcf61125252a
+Author: Geert Uytterhoeven <geert@linux-m68k.org>
+Date:   Sun Jan 26 11:53:21 2014 +0100
+
+    ath9k: Fix uninitialized variable in ath9k_has_tx_pending()
+    
+    drivers/net/wireless/ath/ath9k/main.c: In function â€˜ath9k_has_tx_pending’:
+    drivers/net/wireless/ath/ath9k/main.c:1869: warning: â€˜npend’ may be used uninitialized in this function
+    
+    Introduced by commit 10e2318103f5941aa70c318afe34bc41f1b98529 ("ath9k:
+    optimize ath9k_flush").
+    
+    Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
+
+commit a4a634a6937ebdd827fa58e8fcdb8ca49a3769f6
+Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Date:   Mon Jan 27 11:07:42 2014 +0200
+
+    mac80211: release the channel in error path in start_ap
+    
+    When the driver cannot start the AP or when the assignement
+    of the beacon goes wrong, we need to unassign the vif.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit dfb6889a75c601aedb7450b7e606668e77da6679
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Wed Jan 22 11:14:19 2014 +0200
+
+    cfg80211: send scan results from work queue
+    
+    Due to the previous commit, when a scan finishes, it is in theory
+    possible to hit the following sequence:
+     1. interface starts being removed
+     2. scan is cancelled by driver and cfg80211 is notified
+     3. scan done work is scheduled
+     4. interface is removed completely, rdev->scan_req is freed,
+        event sent to userspace but scan done work remains pending
+     5. new scan is requested on another virtual interface
+     6. scan done work runs, freeing the still-running scan
+    
+    To fix this situation, hang on to the scan done message and block
+    new scans while that is the case, and only send the message from
+    the work function, regardless of whether the scan_req is already
+    freed from interface removal. This makes step 5 above impossible
+    and changes step 6 to be
+     5. scan done work runs, sending the scan done message
+    
+    As this can't work for wext, so we send the message immediately,
+    but this shouldn't be an issue since we still return -EBUSY.
+    
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 45b7ab41fc08627d9a8428cb413d5d84662a9707
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Wed Jan 22 11:14:18 2014 +0200
+
+    cfg80211: fix scan done race
+    
+    When an interface/wdev is removed, any ongoing scan should be
+    cancelled by the driver. This will make it call cfg80211, which
+    only queues a work struct. If interface/wdev removal is quick
+    enough, this can leave the scan request pending and processed
+    only after the interface is gone, causing a use-after-free.
+    
+    Fix this by making sure the scan request is not pending after
+    the interface is destroyed. We can't flush or cancel the work
+    item due to locking concerns, but when it'll run it shouldn't
+    find anything to do. This leaves a potential issue, if a new
+    scan gets requested before the work runs, it prematurely stops
+    the running scan, potentially causing another crash. I'll fix
+    that in the next patch.
+    
+    This was particularly observed with P2P_DEVICE wdevs, likely
+    because freeing them is quicker than freeing netdevs.
+    
+    Reported-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
+    Fixes: 4a58e7c38443 ("cfg80211: don't "leak" uncompleted scans")
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit ae04fa489ab31b5a10d3cc8399f52761175d4321
+Author: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+Date:   Thu Jan 23 14:28:16 2014 +0200
+
+    mac80211: avoid deadlock revealed by lockdep
+    
+    sdata->u.ap.request_smps_work can’t be flushed synchronously
+    under wdev_lock(wdev) since ieee80211_request_smps_ap_work
+    itself locks the same lock.
+    While at it, reset the driver_smps_mode when the ap is
+    stopped to its default: OFF.
+    
+    This solves:
+    
+    ======================================================
+    [ INFO: possible circular locking dependency detected ]
+    3.12.0-ipeer+ #2 Tainted: G           O
+    -------------------------------------------------------
+    rmmod/2867 is trying to acquire lock:
+      ((&sdata->u.ap.request_smps_work)){+.+...}, at: [<c105b8d0>] flush_work+0x0/0x90
+    
+    but task is already holding lock:
+      (&wdev->mtx){+.+.+.}, at: [<f9b32626>] cfg80211_stop_ap+0x26/0x230 [cfg80211]
+    
+    which lock already depends on the new lock.
+    
+    the existing dependency chain (in reverse order) is:
+    
+    -> #1 (&wdev->mtx){+.+.+.}:
+            [<c10aefa9>] lock_acquire+0x79/0xe0
+            [<c1607a1a>] mutex_lock_nested+0x4a/0x360
+            [<fb06288b>] ieee80211_request_smps_ap_work+0x2b/0x50 [mac80211]
+            [<c105cdd8>] process_one_work+0x198/0x450
+            [<c105d469>] worker_thread+0xf9/0x320
+            [<c10669ff>] kthread+0x9f/0xb0
+            [<c1613397>] ret_from_kernel_thread+0x1b/0x28
+    
+    -> #0 ((&sdata->u.ap.request_smps_work)){+.+...}:
+            [<c10ae9df>] __lock_acquire+0x183f/0x1910
+            [<c10aefa9>] lock_acquire+0x79/0xe0
+            [<c105b917>] flush_work+0x47/0x90
+            [<c105d867>] __cancel_work_timer+0x67/0xe0
+            [<c105d90f>] cancel_work_sync+0xf/0x20
+            [<fb0765cc>] ieee80211_stop_ap+0x8c/0x340 [mac80211]
+            [<f9b3268c>] cfg80211_stop_ap+0x8c/0x230 [cfg80211]
+            [<f9b0d8f9>] cfg80211_leave+0x79/0x100 [cfg80211]
+            [<f9b0da72>] cfg80211_netdev_notifier_call+0xf2/0x4f0 [cfg80211]
+            [<c160f2c9>] notifier_call_chain+0x59/0x130
+            [<c106c6de>] __raw_notifier_call_chain+0x1e/0x30
+            [<c106c70f>] raw_notifier_call_chain+0x1f/0x30
+            [<c14f8213>] call_netdevice_notifiers_info+0x33/0x70
+            [<c14f8263>] call_netdevice_notifiers+0x13/0x20
+            [<c14f82a4>] __dev_close_many+0x34/0xb0
+            [<c14f83fe>] dev_close_many+0x6e/0xc0
+            [<c14f9c77>] rollback_registered_many+0xa7/0x1f0
+            [<c14f9dd4>] unregister_netdevice_many+0x14/0x60
+            [<fb06f4d9>] ieee80211_remove_interfaces+0xe9/0x170 [mac80211]
+            [<fb055116>] ieee80211_unregister_hw+0x56/0x110 [mac80211]
+            [<fa3e9396>] iwl_op_mode_mvm_stop+0x26/0xe0 [iwlmvm]
+            [<f9b9d8ca>] _iwl_op_mode_stop+0x3a/0x70 [iwlwifi]
+            [<f9b9d96f>] iwl_opmode_deregister+0x6f/0x90 [iwlwifi]
+            [<fa405179>] __exit_compat+0xd/0x19 [iwlmvm]
+            [<c10b8bf9>] SyS_delete_module+0x179/0x2b0
+            [<c1613421>] sysenter_do_call+0x12/0x32
+    
+    Fixes: 687da132234f ("mac80211: implement SMPS for AP")
+    Cc: <stable@vger.kernel.org> [3.13]
+    Reported-by: Ilan Peer <ilan.peer@intel.com>
+    Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 178b205e96217164fd7c30113464250d0b6f5eca
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Thu Jan 23 16:32:29 2014 +0100
+
+    cfg80211: re-enable 5/10 MHz support
+    
+    Unfortunately I forgot this during the merge window, but the
+    patch seems small enough to go in as a fix. The userspace API
+    bug that was the reason for disabling it has long been fixed.
+    
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 110a1c79acda14edc83b7c8dc5af9c7ddd23eb61
+Author: Pontus Fuchs <pontus.fuchs@gmail.com>
+Date:   Thu Jan 16 15:00:40 2014 +0100
+
+    nl80211: Reset split_start when netlink skb is exhausted
+    
+    When the netlink skb is exhausted split_start is left set. In the
+    subsequent retry, with a larger buffer, the dump is continued from the
+    failing point instead of from the beginning.
+    
+    This was causing my rt28xx based USB dongle to now show up when
+    running "iw list" with an old iw version without split dump support.
+    
+    Cc: stable@vger.kernel.org
+    Fixes: 3713b4e364ef ("nl80211: allow splitting wiphy information in dumps")
+    Signed-off-by: Pontus Fuchs <pontus.fuchs@gmail.com>
+    [avoid the entire workaround when state->split is set]
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit b4c31b45ffc7ef110fa9ecc34d7878fe7c5b9da4
+Author: Eliad Peller <eliad@wizery.com>
+Date:   Sun Jan 12 11:06:37 2014 +0200
+
+    mac80211: move roc cookie assignment earlier
+    
+    ieee80211_start_roc_work() might add a new roc
+    to existing roc, and tell cfg80211 it has already
+    started.
+    
+    However, this might happen before the roc cookie
+    was set, resulting in REMAIN_ON_CHANNEL (started)
+    event with null cookie. Consequently, it can make
+    wpa_supplicant go out of sync.
+    
+    Fix it by setting the roc cookie earlier.
+    
+    Cc: stable@vger.kernel.org
+    Signed-off-by: Eliad Peller <eliad@wizery.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit cfdc9157bfd7bcf88ab4dae08873a9907eba984c
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Fri Jan 24 14:06:29 2014 +0100
+
+    nl80211: send event when AP operation is stopped
+    
+    There are a few cases, e.g. suspend, where an AP interface is
+    stopped by the kernel rather than by userspace request, most
+    commonly when suspending. To let userspace know about this,
+    send the NL80211_CMD_STOP_AP command as an event every time
+    an AP interface is stopped. This also happens when userspace
+    did in fact request the AP stop, but that's not a problem.
+    
+    For full-MAC drivers this may need to be extended to also
+    cover cases where the device stopped the AP operation for
+    some reason, this a bit more complicated because then all
+    cfg80211 state also needs to be reset; such API is not part
+    of this patch.
+    
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit d5d567eda7704f190379ca852a8f9a4112e3eee3
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Thu Jan 23 16:20:29 2014 +0100
+
+    mac80211: add length check in ieee80211_is_robust_mgmt_frame()
+    
+    A few places weren't checking that the frame passed to the
+    function actually has enough data even though the function
+    clearly documents it must have a payload byte. Make this
+    safer by changing the function to take an skb and checking
+    the length inside. The old version is preserved for now as
+    the rtl* drivers use it and don't have a correct skb.
+    
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit f8f6d212a047fc65c7d3442dfc038f65517236fc
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Fri Jan 24 10:53:53 2014 +0100
+
+    nl80211: fix scheduled scan RSSI matchset attribute confusion
+    
+    The scheduled scan matchsets were intended to be a list of filters,
+    with the found BSS having to pass at least one of them to be passed
+    to the host. When the RSSI attribute was added, however, this was
+    broken and currently wpa_supplicant adds that attribute in its own
+    matchset; however, it doesn't intend that to mean that anything
+    that passes the RSSI filter should be passed to the host, instead
+    it wants it to mean that everything needs to also have higher RSSI.
+    
+    This is semantically problematic because we have a list of filters
+    like [ SSID1, SSID2, SSID3, RSSI ] with no real indication which
+    one should be OR'ed and which one AND'ed.
+    
+    To fix this, move the RSSI filter attribute into each matchset. As
+    we need to stay backward compatible, treat a matchset with only the
+    RSSI attribute as a "default RSSI filter" for all other matchsets,
+    but only if there are other matchsets (an RSSI-only matchset by
+    itself is still desirable.)
+    
+    To make driver implementation easier, keep a global min_rssi_thold
+    for the entire request as well. The only affected driver is ath6kl.
+    
+    I found this when I looked into the code after Raja Mani submitted
+    a patch fixing the n_match_sets calculation to disregard the RSSI,
+    but that patch didn't address the semantic issue.
+    
+    Reported-by: Raja Mani <rmani@qti.qualcomm.com>
+    Acked-by: Luciano Coelho <luciano.coelho@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit de553e8545e65a6dc4e45f43df7e1443d4291922
+Author: Johannes Berg <johannes.berg@intel.com>
+Date:   Fri Jan 24 10:17:47 2014 +0100
+
+    nl80211: check nla_parse() return values
+    
+    If there's a policy, then nla_parse() return values must be
+    checked, otherwise the policy is useless and there's nothing
+    that ensures the attributes are actually what we expect them
+    to be.
+    
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+
+commit 652204a0733e9e1c54661d6f9d36e2e1e3b22bb1
+Author: Karl Beldan <karl.beldan@rivierawaves.com>
+Date:   Thu Jan 23 20:06:34 2014 +0100
+
+    mac80211: send {ADD,DEL}BA on AC_VO like other mgmt frames, as per spec
+    
+    ATM, {ADD,DEL}BA and BAR frames are sent on the AC matching the TID of
+    the BA parameters. In the discussion [1] about this patch, Johannes
+    recalled that it fixed some races with the DELBA and indeed this
+    behavior was introduced in [2].
+    While [2] is right for the BARs, the part queueing the {ADD,DEL}BAs on
+    their BA params TID AC violates the spec and is more a workaround for
+    some drivers. Helmut expressed some concerns wrt such drivers, in
+    particular DELBAs in rt2x00.
+    
+    ATM, DELBAs are sent after a driver has called (hence "purposely")
+    ieee80211_start_tx_ba_cb_irqsafe and Johannes and Emmanuel gave some
+    details wrt intentions behind the split of the IEEE80211_AMPDU_TX_STOP_*
+    given to the driver ampdu_action supposed to call this function, which
+    could prove handy to people trying to do the right thing in faulty
+    drivers (if their fw/hw don't get in their way).
+    
+    [1] http://mid.gmane.org/1390391564-18481-1-git-send-email-karl.beldan@gmail.com
+    [2] Commit: cf6bb79ad828 ("mac80211: Use appropriate TID for sending BAR, ADDBA and DELBA frames")
+    
+    Signed-off-by: Karl Beldan <karl.beldan@rivierawaves.com>
+    Cc: Helmut Schaa <helmut.schaa@googlemail.com>
+    Cc: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
+    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
++++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
+@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struc
+       if (nw_type & ADHOC_NETWORK) {
+               ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
+                          nw_type & ADHOC_CREATOR ? "creator" : "joiner");
+-              cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
++              cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
+               cfg80211_put_bss(ar->wiphy, bss);
+               return;
+       }
+@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(st
+       }
+       if (vif->nw_type & ADHOC_NETWORK) {
+-              if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
++              if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
+                       ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
+                                  "%s: ath6k not in ibss mode\n", __func__);
+-                      return;
+-              }
+-              memset(bssid, 0, ETH_ALEN);
+-              cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
+               return;
+       }
+@@ -3256,6 +3252,15 @@ static int ath6kl_cfg80211_sscan_start(s
+       struct ath6kl_vif *vif = netdev_priv(dev);
+       u16 interval;
+       int ret, rssi_thold;
++      int n_match_sets = request->n_match_sets;
++
++      /*
++       * If there's a matchset w/o an SSID, then assume it's just for
++       * the RSSI (nothing else is currently supported) and ignore it.
++       * The device only supports a global RSSI filter that we set below.
++       */
++      if (n_match_sets == 1 && !request->match_sets[0].ssid.ssid_len)
++              n_match_sets = 0;
+       if (ar->state != ATH6KL_STATE_ON)
+               return -EIO;
+@@ -3268,11 +3273,11 @@ static int ath6kl_cfg80211_sscan_start(s
+       ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
+                                     request->n_ssids,
+                                     request->match_sets,
+-                                    request->n_match_sets);
++                                    n_match_sets);
+       if (ret < 0)
+               return ret;
+-      if (!request->n_match_sets) {
++      if (!n_match_sets) {
+               ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
+                                              ALL_BSS_FILTER, 0);
+               if (ret < 0)
+@@ -3286,12 +3291,12 @@ static int ath6kl_cfg80211_sscan_start(s
+       if (test_bit(ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD,
+                    ar->fw_capabilities)) {
+-              if (request->rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
++              if (request->min_rssi_thold <= NL80211_SCAN_RSSI_THOLD_OFF)
+                       rssi_thold = 0;
+-              else if (request->rssi_thold < -127)
++              else if (request->min_rssi_thold < -127)
+                       rssi_thold = -127;
+               else
+-                      rssi_thold = request->rssi_thold;
++                      rssi_thold = request->min_rssi_thold;
+               ret = ath6kl_wmi_set_rssi_filter_cmd(ar->wmi, vif->fw_vif_idx,
+                                                    rssi_thold);
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1316,7 +1316,7 @@ static bool ath9k_hw_set_reset(struct at
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               udelay(50);
+       else if (AR_SREV_9100(ah))
+-              udelay(10000);
++              mdelay(10);
+       else
+               udelay(100);
+@@ -1534,7 +1534,7 @@ EXPORT_SYMBOL(ath9k_hw_check_nav);
+ bool ath9k_hw_check_alive(struct ath_hw *ah)
+ {
+       int count = 50;
+-      u32 reg;
++      u32 reg, last_val;
+       if (AR_SREV_9300(ah))
+               return !ath9k_hw_detect_mac_hang(ah);
+@@ -1542,9 +1542,14 @@ bool ath9k_hw_check_alive(struct ath_hw 
+       if (AR_SREV_9285_12_OR_LATER(ah))
+               return true;
++      last_val = REG_READ(ah, AR_OBS_BUS_1);
+       do {
+               reg = REG_READ(ah, AR_OBS_BUS_1);
++              if (reg != last_val)
++                      return true;
++              udelay(1);
++              last_val = reg;
+               if ((reg & 0x7E7FFFEF) == 0x00702400)
+                       continue;
+@@ -2051,9 +2056,8 @@ static bool ath9k_hw_set_power_awake(str
+       REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+                   AR_RTC_FORCE_WAKE_EN);
+-
+       if (AR_SREV_9100(ah))
+-              udelay(10000);
++              mdelay(10);
+       else
+               udelay(50);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -451,7 +451,7 @@ void ath9k_tasklet(unsigned long data)
+                * interrupts are enabled in the reset routine.
+                */
+               atomic_inc(&ah->intr_ref_cnt);
+-              ath_dbg(common, ANY, "FATAL: Skipping interrupts\n");
++              ath_dbg(common, RESET, "FATAL: Skipping interrupts\n");
+               goto out;
+       }
+@@ -471,7 +471,7 @@ void ath9k_tasklet(unsigned long data)
+                        * interrupts are enabled in the reset routine.
+                        */
+                       atomic_inc(&ah->intr_ref_cnt);
+-                      ath_dbg(common, ANY,
++                      ath_dbg(common, RESET,
+                               "BB_WATCHDOG: Skipping interrupts\n");
+                       goto out;
+               }
+@@ -484,7 +484,7 @@ void ath9k_tasklet(unsigned long data)
+                       type = RESET_TYPE_TX_GTT;
+                       ath9k_queue_reset(sc, type);
+                       atomic_inc(&ah->intr_ref_cnt);
+-                      ath_dbg(common, ANY,
++                      ath_dbg(common, RESET,
+                               "GTT: Skipping interrupts\n");
+                       goto out;
+               }
+@@ -1866,7 +1866,7 @@ static void ath9k_set_coverage_class(str
+ static bool ath9k_has_tx_pending(struct ath_softc *sc)
+ {
+-      int i, npend;
++      int i, npend = 0;
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+               if (!ATH_TXQ_SETUP(sc, i))
+--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
++++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
+@@ -595,6 +595,9 @@ static void iwl_scan_offload_build_ssid(
+        * config match list.
+        */
+       for (i = 0; i < req->n_match_sets && i < PROBE_OPTION_MAX; i++) {
++              /* skip empty SSID matchsets */
++              if (!req->match_sets[i].ssid.ssid_len)
++                      continue;
+               scan->direct_scan[i].id = WLAN_EID_SSID;
+               scan->direct_scan[i].len = req->match_sets[i].ssid.ssid_len;
+               memcpy(scan->direct_scan[i].ssid, req->match_sets[i].ssid.ssid,
+--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
++++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+@@ -452,7 +452,7 @@ bool rtl88ee_rx_query_desc(struct ieee80
+                       /* During testing, hdr was NULL */
+                       return false;
+               }
+-              if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
++              if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
+                   (ieee80211_has_protected(hdr->frame_control)))
+                       rx_status->flag &= ~RX_FLAG_DECRYPTED;
+               else
+--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+@@ -393,7 +393,7 @@ bool rtl92ce_rx_query_desc(struct ieee80
+                       /* In testing, hdr was NULL here */
+                       return false;
+               }
+-              if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
++              if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
+                   (ieee80211_has_protected(hdr->frame_control)))
+                       rx_status->flag &= ~RX_FLAG_DECRYPTED;
+               else
+--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+@@ -310,7 +310,7 @@ bool rtl92se_rx_query_desc(struct ieee80
+                       /* during testing, hdr was NULL here */
+                       return false;
+               }
+-              if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
++              if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
+                       (ieee80211_has_protected(hdr->frame_control)))
+                       rx_status->flag &= ~RX_FLAG_DECRYPTED;
+               else
+--- a/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
++++ b/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c
+@@ -334,7 +334,7 @@ bool rtl8723ae_rx_query_desc(struct ieee
+                       /* during testing, hdr could be NULL here */
+                       return false;
+               }
+-              if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
++              if ((_ieee80211_is_robust_mgmt_frame(hdr)) &&
+                       (ieee80211_has_protected(hdr->frame_control)))
+                       rx_status->flag &= ~RX_FLAG_DECRYPTED;
+               else
+--- a/include/linux/ieee80211.h
++++ b/include/linux/ieee80211.h
+@@ -597,6 +597,20 @@ static inline int ieee80211_is_qos_nullf
+ }
+ /**
++ * ieee80211_is_bufferable_mmpdu - check if frame is bufferable MMPDU
++ * @fc: frame control field in little-endian byteorder
++ */
++static inline bool ieee80211_is_bufferable_mmpdu(__le16 fc)
++{
++      /* IEEE 802.11-2012, definition of "bufferable management frame";
++       * note that this ignores the IBSS special case. */
++      return ieee80211_is_mgmt(fc) &&
++             (ieee80211_is_action(fc) ||
++              ieee80211_is_disassoc(fc) ||
++              ieee80211_is_deauth(fc));
++}
++
++/**
+  * ieee80211_is_first_frag - check if IEEE80211_SCTL_FRAG is not set
+  * @seq_ctrl: frame sequence control bytes in little-endian byteorder
+  */
+@@ -2192,10 +2206,10 @@ static inline u8 *ieee80211_get_DA(struc
+ }
+ /**
+- * ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
++ * _ieee80211_is_robust_mgmt_frame - check if frame is a robust management frame
+  * @hdr: the frame (buffer must include at least the first octet of payload)
+  */
+-static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
++static inline bool _ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
+ {
+       if (ieee80211_is_disassoc(hdr->frame_control) ||
+           ieee80211_is_deauth(hdr->frame_control))
+@@ -2224,6 +2238,17 @@ static inline bool ieee80211_is_robust_m
+ }
+ /**
++ * ieee80211_is_robust_mgmt_frame - check if skb contains a robust mgmt frame
++ * @skb: the skb containing the frame, length will be checked
++ */
++static inline bool ieee80211_is_robust_mgmt_frame(struct sk_buff *skb)
++{
++      if (skb->len < 25)
++              return false;
++      return _ieee80211_is_robust_mgmt_frame((void *)skb->data);
++}
++
++/**
+  * ieee80211_is_public_action - check if frame is a public action frame
+  * @hdr: the frame
+  * @len: length of the frame
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -1395,9 +1395,11 @@ struct cfg80211_scan_request {
+  * struct cfg80211_match_set - sets of attributes to match
+  *
+  * @ssid: SSID to be matched
++ * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
+  */
+ struct cfg80211_match_set {
+       struct cfg80211_ssid ssid;
++      s32 rssi_thold;
+ };
+ /**
+@@ -1420,7 +1422,8 @@ struct cfg80211_match_set {
+  * @dev: the interface
+  * @scan_start: start time of the scheduled scan
+  * @channels: channels to scan
+- * @rssi_thold: don't report scan results below this threshold (in s32 dBm)
++ * @min_rssi_thold: for drivers only supporting a single threshold, this
++ *    contains the minimum over all matchsets
+  */
+ struct cfg80211_sched_scan_request {
+       struct cfg80211_ssid *ssids;
+@@ -1433,7 +1436,7 @@ struct cfg80211_sched_scan_request {
+       u32 flags;
+       struct cfg80211_match_set *match_sets;
+       int n_match_sets;
+-      s32 rssi_thold;
++      s32 min_rssi_thold;
+       /* internal */
+       struct wiphy *wiphy;
+@@ -3130,8 +3133,8 @@ struct cfg80211_cached_keys;
+  * @identifier: (private) Identifier used in nl80211 to identify this
+  *    wireless device if it has no netdev
+  * @current_bss: (private) Used by the internal configuration code
+- * @channel: (private) Used by the internal configuration code to track
+- *    the user-set AP, monitor and WDS channel
++ * @chandef: (private) Used by the internal configuration code to track
++ *    the user-set channel definition.
+  * @preset_chandef: (private) Used by the internal configuration code to
+  *    track the channel to be used for AP later
+  * @bssid: (private) Used by the internal configuration code
+@@ -3195,9 +3198,7 @@ struct wireless_dev {
+       struct cfg80211_internal_bss *current_bss; /* associated / joined */
+       struct cfg80211_chan_def preset_chandef;
+-
+-      /* for AP and mesh channel tracking */
+-      struct ieee80211_channel *channel;
++      struct cfg80211_chan_def chandef;
+       bool ibss_fixed;
+       bool ibss_dfs_possible;
+@@ -3879,6 +3880,7 @@ void cfg80211_michael_mic_failure(struct
+  *
+  * @dev: network device
+  * @bssid: the BSSID of the IBSS joined
++ * @channel: the channel of the IBSS joined
+  * @gfp: allocation flags
+  *
+  * This function notifies cfg80211 that the device joined an IBSS or
+@@ -3888,7 +3890,8 @@ void cfg80211_michael_mic_failure(struct
+  * with the locally generated beacon -- this guarantees that there is
+  * always a scan result for this IBSS. cfg80211 will handle the rest.
+  */
+-void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
++void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
++                        struct ieee80211_channel *channel, gfp_t gfp);
+ /**
+  * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -2442,9 +2442,15 @@ enum nl80211_reg_rule_attr {
+  * enum nl80211_sched_scan_match_attr - scheduled scan match attributes
+  * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved
+  * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching,
+- * only report BSS with matching SSID.
++ *    only report BSS with matching SSID.
+  * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a
+- *    BSS in scan results. Filtering is turned off if not specified.
++ *    BSS in scan results. Filtering is turned off if not specified. Note that
++ *    if this attribute is in a match set of its own, then it is treated as
++ *    the default value for all matchsets with an SSID, rather than being a
++ *    matchset of its own without an RSSI filter. This is due to problems with
++ *    how this API was implemented in the past. Also, due to the same problem,
++ *    the only way to create a matchset with only an RSSI filter (with this
++ *    attribute) is if there's only a single matchset with the RSSI attribute.
+  * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter
+  *    attribute number currently defined
+  * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use
 --- a/net/mac80211/agg-tx.c
 +++ b/net/mac80211/agg-tx.c
-@@ -81,7 +81,8 @@ static void ieee80211_send_addba_request
-       memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
-       if (sdata->vif.type == NL80211_IFTYPE_AP ||
-           sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
--          sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
-+          sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
-+          sdata->vif.type == NL80211_IFTYPE_WDS)
-               memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
-       else if (sdata->vif.type == NL80211_IFTYPE_STATION)
-               memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
-@@ -527,6 +528,7 @@ int ieee80211_start_tx_ba_session(struct
-           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_WDS &&
-           sdata->vif.type != NL80211_IFTYPE_ADHOC)
-               return -EINVAL;
+@@ -107,7 +107,7 @@ static void ieee80211_send_addba_request
+       mgmt->u.action.u.addba_req.start_seq_num =
+                                       cpu_to_le16(start_seq_num << 4);
+-      ieee80211_tx_skb_tid(sdata, skb, tid);
++      ieee80211_tx_skb(sdata, skb);
+ }
+ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wip
+       /* TODO: make hostapd tell us what it wants */
+       sdata->smps_mode = IEEE80211_SMPS_OFF;
+       sdata->needed_rx_chains = sdata->local->rx_chains;
+-      sdata->radar_required = params->radar_required;
+       mutex_lock(&local->mtx);
++      sdata->radar_required = params->radar_required;
+       err = ieee80211_vif_use_channel(sdata, &params->chandef,
+                                       IEEE80211_CHANCTX_SHARED);
+       mutex_unlock(&local->mtx);
+@@ -1021,8 +1021,10 @@ static int ieee80211_start_ap(struct wip
+                                       IEEE80211_P2P_OPPPS_ENABLE_BIT;
+       err = ieee80211_assign_beacon(sdata, &params->beacon);
+-      if (err < 0)
++      if (err < 0) {
++              ieee80211_vif_release_channel(sdata);
+               return err;
++      }
+       changed |= err;
+       err = drv_start_ap(sdata->local, sdata);
+@@ -1032,6 +1034,7 @@ static int ieee80211_start_ap(struct wip
+               if (old)
+                       kfree_rcu(old, rcu_head);
+               RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
++              ieee80211_vif_release_channel(sdata);
+               return err;
+       }
+@@ -1053,6 +1056,7 @@ static int ieee80211_change_beacon(struc
+       int err;
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++      sdata_assert_lock(sdata);
+       /* don't allow changing the beacon while CSA is in place - offset
+        * of channel switch counter may change
+@@ -1080,6 +1084,8 @@ static int ieee80211_stop_ap(struct wiph
+       struct probe_resp *old_probe_resp;
+       struct cfg80211_chan_def chandef;
++      sdata_assert_lock(sdata);
++
+       old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
+       if (!old_beacon)
+               return -ENOENT;
+@@ -1090,8 +1096,6 @@ static int ieee80211_stop_ap(struct wiph
+       kfree(sdata->u.ap.next_beacon);
+       sdata->u.ap.next_beacon = NULL;
+-      cancel_work_sync(&sdata->u.ap.request_smps_work);
+-
+       /* turn off carrier for this interface and dependent VLANs */
+       list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+               netif_carrier_off(vlan->dev);
+@@ -1103,6 +1107,7 @@ static int ieee80211_stop_ap(struct wiph
+       kfree_rcu(old_beacon, rcu_head);
+       if (old_probe_resp)
+               kfree_rcu(old_probe_resp, rcu_head);
++      sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
+       __sta_info_flush(sdata, true);
+       ieee80211_free_keys(sdata, true);
+@@ -1988,6 +1993,9 @@ static int ieee80211_change_bss(struct w
+       band = ieee80211_get_sdata_band(sdata);
++      if (WARN_ON(!wiphy->bands[band]))
++              return -EINVAL;
++
+       if (params->use_cts_prot >= 0) {
+               sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
+               changed |= BSS_CHANGED_ERP_CTS_PROT;
+@@ -2638,6 +2646,24 @@ static int ieee80211_start_roc_work(stru
+       INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
+       INIT_LIST_HEAD(&roc->dependents);
++      /*
++       * cookie is either the roc cookie (for normal roc)
++       * or the SKB (for mgmt TX)
++       */
++      if (!txskb) {
++              /* local->mtx protects this */
++              local->roc_cookie_counter++;
++              roc->cookie = local->roc_cookie_counter;
++              /* wow, you wrapped 64 bits ... more likely a bug */
++              if (WARN_ON(roc->cookie == 0)) {
++                      roc->cookie = 1;
++                      local->roc_cookie_counter++;
++              }
++              *cookie = roc->cookie;
++      } else {
++              *cookie = (unsigned long)txskb;
++      }
++
+       /* if there's one pending or we're scanning, queue this one */
+       if (!list_empty(&local->roc_list) ||
+           local->scanning || local->radar_detect_enabled)
+@@ -2772,24 +2798,6 @@ static int ieee80211_start_roc_work(stru
+       if (!queued)
+               list_add_tail(&roc->list, &local->roc_list);
+-      /*
+-       * cookie is either the roc cookie (for normal roc)
+-       * or the SKB (for mgmt TX)
+-       */
+-      if (!txskb) {
+-              /* local->mtx protects this */
+-              local->roc_cookie_counter++;
+-              roc->cookie = local->roc_cookie_counter;
+-              /* wow, you wrapped 64 bits ... more likely a bug */
+-              if (WARN_ON(roc->cookie == 0)) {
+-                      roc->cookie = 1;
+-                      local->roc_cookie_counter++;
+-              }
+-              *cookie = roc->cookie;
+-      } else {
+-              *cookie = (unsigned long)txskb;
+-      }
+-
+       return 0;
+ }
+@@ -3004,8 +3012,10 @@ void ieee80211_csa_finalize_work(struct 
+       if (!ieee80211_sdata_running(sdata))
+               goto unlock;
+-      sdata->radar_required = sdata->csa_radar_required;
++      sdata_assert_lock(sdata);
++
+       mutex_lock(&local->mtx);
++      sdata->radar_required = sdata->csa_radar_required;
+       err = ieee80211_vif_change_channel(sdata, &changed);
+       mutex_unlock(&local->mtx);
+       if (WARN_ON(err < 0))
+@@ -3022,13 +3032,13 @@ void ieee80211_csa_finalize_work(struct 
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_AP:
+               err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon);
++              kfree(sdata->u.ap.next_beacon);
++              sdata->u.ap.next_beacon = NULL;
++
+               if (err < 0)
+                       goto unlock;
+               changed |= err;
+-              kfree(sdata->u.ap.next_beacon);
+-              sdata->u.ap.next_beacon = NULL;
+-
+               ieee80211_bss_info_change_notify(sdata, err);
+               break;
+       case NL80211_IFTYPE_ADHOC:
+@@ -3066,7 +3076,7 @@ int ieee80211_channel_switch(struct wiph
+       struct ieee80211_if_mesh __maybe_unused *ifmsh;
+       int err, num_chanctx;
+-      lockdep_assert_held(&sdata->wdev.mtx);
++      sdata_assert_lock(sdata);
+       if (!list_empty(&local->roc_list) || local->scanning)
+               return -EBUSY;
+--- a/net/mac80211/ht.c
++++ b/net/mac80211/ht.c
+@@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee802
+       mgmt->u.action.u.delba.params = cpu_to_le16(params);
+       mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code);
+-      ieee80211_tx_skb_tid(sdata, skb, tid);
++      ieee80211_tx_skb(sdata, skb);
+ }
+ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
+@@ -466,7 +466,9 @@ void ieee80211_request_smps_ap_work(stru
+                            u.ap.request_smps_work);
+       sdata_lock(sdata);
+-      __ieee80211_request_smps_ap(sdata, sdata->u.ap.driver_smps_mode);
++      if (sdata_dereference(sdata->u.ap.beacon, sdata))
++              __ieee80211_request_smps_ap(sdata,
++                                          sdata->u.ap.driver_smps_mode);
+       sdata_unlock(sdata);
+ }
  
---- a/net/mac80211/debugfs_sta.c
-+++ b/net/mac80211/debugfs_sta.c
-@@ -66,11 +66,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",
-                           TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
-                           TEST(PS_DRIVER), TEST(AUTHORIZED),
-                           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(UAPSD), TEST(SP), TEST(TDLS_PEER),
-                           TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
 --- a/net/mac80211/iface.c
 +++ b/net/mac80211/iface.c
-@@ -463,7 +463,6 @@ int ieee80211_do_open(struct wireless_de
-       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
-       struct net_device *dev = wdev->netdev;
-       struct ieee80211_local *local = sdata->local;
--      struct sta_info *sta;
-       u32 changed = 0;
-       int res;
-       u32 hw_reconf_flags = 0;
-@@ -629,30 +628,8 @@ int ieee80211_do_open(struct wireless_de
-       set_bit(SDATA_STATE_RUNNING, &sdata->state);
--      if (sdata->vif.type == NL80211_IFTYPE_WDS) {
--              /* Create STA entry for the WDS peer */
--              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
--                                   GFP_KERNEL);
--              if (!sta) {
--                      res = -ENOMEM;
--                      goto err_del_interface;
--              }
+@@ -770,12 +770,19 @@ static void ieee80211_do_stop(struct iee
+       ieee80211_roc_purge(local, sdata);
+-      if (sdata->vif.type == NL80211_IFTYPE_STATION)
++      switch (sdata->vif.type) {
++      case NL80211_IFTYPE_STATION:
+               ieee80211_mgd_stop(sdata);
 -
--              sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
--              sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
--              sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
+-      if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
++              break;
++      case NL80211_IFTYPE_ADHOC:
+               ieee80211_ibss_stop(sdata);
 -
--              res = sta_info_insert(sta);
--              if (res) {
--                      /* STA has been freed */
--                      goto err_del_interface;
--              }
++              break;
++      case NL80211_IFTYPE_AP:
++              cancel_work_sync(&sdata->u.ap.request_smps_work);
++              break;
++      default:
++              break;
++      }
+       /*
+        * Remove all stations associated with this interface.
+@@ -827,7 +834,9 @@ static void ieee80211_do_stop(struct iee
+       cancel_work_sync(&local->dynamic_ps_enable_work);
+       cancel_work_sync(&sdata->recalc_smps);
++      sdata_lock(sdata);
+       sdata->vif.csa_active = false;
++      sdata_unlock(sdata);
+       cancel_work_sync(&sdata->csa_finalize_work);
+       cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -599,10 +599,10 @@ static int ieee80211_is_unicast_robust_m
+ {
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-      if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1))
++      if (is_multicast_ether_addr(hdr->addr1))
+               return 0;
+-      return ieee80211_is_robust_mgmt_frame(hdr);
++      return ieee80211_is_robust_mgmt_frame(skb);
+ }
+@@ -610,10 +610,10 @@ static int ieee80211_is_multicast_robust
+ {
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+-      if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1))
++      if (!is_multicast_ether_addr(hdr->addr1))
+               return 0;
+-      return ieee80211_is_robust_mgmt_frame(hdr);
++      return ieee80211_is_robust_mgmt_frame(skb);
+ }
+@@ -626,7 +626,7 @@ static int ieee80211_get_mmie_keyidx(str
+       if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da))
+               return -1;
+-      if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr))
++      if (!ieee80211_is_robust_mgmt_frame(skb))
+               return -1; /* not a robust management frame */
+       mmie = (struct ieee80211_mmie *)
+@@ -1128,6 +1128,13 @@ static void sta_ps_end(struct sta_info *
+              sta->sta.addr, sta->sta.aid);
+       if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
++              /*
++               * Clear the flag only if the other one is still set
++               * so that the TX path won't start TX'ing new frames
++               * directly ... In the case that the driver flag isn't
++               * set ieee80211_sta_ps_deliver_wakeup() will clear it.
++               */
++              clear_sta_flag(sta, WLAN_STA_PS_STA);
+               ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n",
+                      sta->sta.addr, sta->sta.aid);
+               return;
+@@ -1311,18 +1318,15 @@ ieee80211_rx_h_sta_process(struct ieee80
+           !ieee80211_has_morefrags(hdr->frame_control) &&
+           !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
+           (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
+-           rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
++           rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
++          /* PM bit is only checked in frames where it isn't reserved,
++           * in AP mode it's reserved in non-bufferable management frames
++           * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
++           */
++          (!ieee80211_is_mgmt(hdr->frame_control) ||
++           ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
+               if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
+-                      /*
+-                       * Ignore doze->wake transitions that are
+-                       * indicated by non-data frames, the standard
+-                       * is unclear here, but for example going to
+-                       * PS mode and then scanning would cause a
+-                       * doze->wake transition for the probe request,
+-                       * and that is clearly undesirable.
+-                       */
+-                      if (ieee80211_is_data(hdr->frame_control) &&
+-                          !ieee80211_has_pm(hdr->frame_control))
++                      if (!ieee80211_has_pm(hdr->frame_control))
+                               sta_ps_end(sta);
+               } else {
+                       if (ieee80211_has_pm(hdr->frame_control))
+@@ -1845,8 +1849,7 @@ static int ieee80211_drop_unencrypted_mg
+                * having configured keys.
+                */
+               if (unlikely(ieee80211_is_action(fc) && !rx->key &&
+-                           ieee80211_is_robust_mgmt_frame(
+-                                   (struct ieee80211_hdr *) rx->skb->data)))
++                           ieee80211_is_robust_mgmt_frame(rx->skb)))
+                       return -EACCES;
+       }
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, 
+       if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP))
+               return 0;
+-      if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *)
+-                                          skb->data))
++      if (!ieee80211_is_robust_mgmt_frame(skb))
+               return 0;
+       return 1;
+@@ -478,6 +477,20 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
+                      sta->sta.addr, sta->sta.aid, ac);
+               if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
+                       purge_old_ps_buffers(tx->local);
++
++              /* sync with ieee80211_sta_ps_deliver_wakeup */
++              spin_lock(&sta->ps_lock);
++              /*
++               * STA woke up the meantime and all the frames on ps_tx_buf have
++               * been queued to pending queue. No reordering can happen, go
++               * ahead and Tx the packet.
++               */
++              if (!test_sta_flag(sta, WLAN_STA_PS_STA) &&
++                  !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
++                      spin_unlock(&sta->ps_lock);
++                      return TX_CONTINUE;
++              }
++
+               if (skb_queue_len(&sta->ps_tx_buf[ac]) >= STA_MAX_TX_BUFFER) {
+                       struct sk_buff *old = skb_dequeue(&sta->ps_tx_buf[ac]);
+                       ps_dbg(tx->sdata,
+@@ -492,6 +505,7 @@ ieee80211_tx_h_unicast_ps_buf(struct iee
+               info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
+               info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
+               skb_queue_tail(&sta->ps_tx_buf[ac], tx->skb);
++              spin_unlock(&sta->ps_lock);
+               if (!timer_pending(&local->sta_cleanup))
+                       mod_timer(&local->sta_cleanup,
+@@ -525,9 +539,7 @@ ieee80211_tx_h_ps_buf(struct ieee80211_t
+       /* only deauth, disassoc and action are bufferable MMPDUs */
+       if (ieee80211_is_mgmt(hdr->frame_control) &&
+-          !ieee80211_is_deauth(hdr->frame_control) &&
+-          !ieee80211_is_disassoc(hdr->frame_control) &&
+-          !ieee80211_is_action(hdr->frame_control)) {
++          !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) {
+               if (tx->flags & IEEE80211_TX_UNICAST)
+                       info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER;
+               return TX_CONTINUE;
+@@ -567,7 +579,7 @@ ieee80211_tx_h_select_key(struct ieee802
+               tx->key = key;
+       else if (ieee80211_is_mgmt(hdr->frame_control) &&
+                is_multicast_ether_addr(hdr->addr1) &&
+-               ieee80211_is_robust_mgmt_frame(hdr) &&
++               ieee80211_is_robust_mgmt_frame(tx->skb) &&
+                (key = rcu_dereference(tx->sdata->default_mgmt_key)))
+               tx->key = key;
+       else if (is_multicast_ether_addr(hdr->addr1) &&
+@@ -582,12 +594,12 @@ ieee80211_tx_h_select_key(struct ieee802
+               tx->key = NULL;
+       else if (tx->skb->protocol == tx->sdata->control_port_protocol)
+               tx->key = NULL;
+-      else if (ieee80211_is_robust_mgmt_frame(hdr) &&
++      else if (ieee80211_is_robust_mgmt_frame(tx->skb) &&
+                !(ieee80211_is_action(hdr->frame_control) &&
+                  tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))
+               tx->key = NULL;
+       else if (ieee80211_is_mgmt(hdr->frame_control) &&
+-               !ieee80211_is_robust_mgmt_frame(hdr))
++               !ieee80211_is_robust_mgmt_frame(tx->skb))
+               tx->key = NULL;
+       else {
+               I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
+@@ -878,7 +890,7 @@ static int ieee80211_fragment(struct iee
+       }
+       /* adjust first fragment's length */
+-      skb->len = hdrlen + per_fragm;
++      skb_trim(skb, hdrlen + per_fragm);
+       return 0;
+ }
+@@ -2900,7 +2912,7 @@ ieee80211_get_buffered_bc(struct ieee802
+                               cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+               }
+-              if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
++              if (sdata->vif.type == NL80211_IFTYPE_AP)
+                       sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
+               if (!ieee80211_tx_prepare(sdata, &tx, skb))
+                       break;
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -499,7 +499,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+       hdrlen = ieee80211_hdrlen(hdr->frame_control);
+       if (!ieee80211_is_data(hdr->frame_control) &&
+-          !ieee80211_is_robust_mgmt_frame(hdr))
++          !ieee80211_is_robust_mgmt_frame(skb))
+               return RX_CONTINUE;
+       data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
+--- a/net/wireless/ap.c
++++ b/net/wireless/ap.c
+@@ -27,9 +27,10 @@ static int __cfg80211_stop_ap(struct cfg
+       err = rdev_stop_ap(rdev, dev);
+       if (!err) {
+               wdev->beacon_interval = 0;
+-              wdev->channel = NULL;
++              memset(&wdev->chandef, 0, sizeof(wdev->chandef));
+               wdev->ssid_len = 0;
+               rdev_set_qos_map(rdev, dev, NULL);
++              nl80211_send_ap_stopped(wdev);
+       }
+       return err;
+--- a/net/wireless/core.c
++++ b/net/wireless/core.c
+@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg
+       rdev->opencount--;
+-      WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
+-              !rdev->scan_req->notified);
++      if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
++              if (WARN_ON(!rdev->scan_req->notified))
++                      rdev->scan_req->aborted = true;
++              ___cfg80211_scan_done(rdev, false);
++      }
+ }
+ static int cfg80211_rfkill_set_block(void *data, bool blocked)
+@@ -447,9 +450,6 @@ int wiphy_register(struct wiphy *wiphy)
+       int i;
+       u16 ifmodes = wiphy->interface_modes;
+-      /* support for 5/10 MHz is broken due to nl80211 API mess - disable */
+-      wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ;
+-
+       /*
+        * There are major locking problems in nl80211/mac80211 for CSA,
+        * disable for all drivers until this has been reworked.
+@@ -795,8 +795,6 @@ void cfg80211_leave(struct cfg80211_regi
+       default:
+               break;
+       }
+-
+-      wdev->beacon_interval = 0;
+ }
+ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
+@@ -875,8 +873,11 @@ static int cfg80211_netdev_notifier_call
+               break;
+       case NETDEV_DOWN:
+               cfg80211_update_iface_num(rdev, wdev->iftype, -1);
+-              WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev &&
+-                      !rdev->scan_req->notified);
++              if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
++                      if (WARN_ON(!rdev->scan_req->notified))
++                              rdev->scan_req->aborted = true;
++                      ___cfg80211_scan_done(rdev, false);
++              }
+               if (WARN_ON(rdev->sched_scan_req &&
+                           rdev->sched_scan_req->dev == wdev->netdev)) {
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -62,6 +62,7 @@ struct cfg80211_registered_device {
+       struct rb_root bss_tree;
+       u32 bss_generation;
+       struct cfg80211_scan_request *scan_req; /* protected by RTNL */
++      struct sk_buff *scan_msg;
+       struct cfg80211_sched_scan_request *sched_scan_req;
+       unsigned long suspend_at;
+       struct work_struct scan_done_wk;
+@@ -210,6 +211,7 @@ struct cfg80211_event {
+               } dc;
+               struct {
+                       u8 bssid[ETH_ALEN];
++                      struct ieee80211_channel *channel;
+               } ij;
+       };
+ };
+@@ -257,7 +259,8 @@ int __cfg80211_leave_ibss(struct cfg8021
+                         struct net_device *dev, bool nowext);
+ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
+                       struct net_device *dev, bool nowext);
+-void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
++void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
++                          struct ieee80211_channel *channel);
+ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
+                           struct wireless_dev *wdev);
+@@ -361,7 +364,8 @@ int cfg80211_validate_key_settings(struc
+                                  struct key_params *params, int key_idx,
+                                  bool pairwise, const u8 *mac_addr);
+ void __cfg80211_scan_done(struct work_struct *wk);
+-void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
++void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
++                         bool send_message);
+ void __cfg80211_sched_scan_results(struct work_struct *wk);
+ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
+                              bool driver_initiated);
+@@ -441,7 +445,8 @@ static inline unsigned int elapsed_jiffi
+ void
+ cfg80211_get_chan_state(struct wireless_dev *wdev,
+                       struct ieee80211_channel **chan,
+-                      enum cfg80211_chan_mode *chanmode);
++                      enum cfg80211_chan_mode *chanmode,
++                      u8 *radar_detect);
+ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
+                                struct cfg80211_chan_def *chandef);
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -1723,9 +1723,10 @@ static int nl80211_dump_wiphy(struct sk_
+                                * We can then retry with the larger buffer.
+                                */
+                               if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
+-                                  !skb->len &&
++                                  !skb->len && !state->split &&
+                                   cb->min_dump_alloc < 4096) {
+                                       cb->min_dump_alloc = 4096;
++                                      state->split_start = 0;
+                                       rtnl_unlock();
+                                       return 1;
+                               }
+@@ -2047,10 +2048,12 @@ static int nl80211_set_wiphy(struct sk_b
+               nla_for_each_nested(nl_txq_params,
+                                   info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
+                                   rem_txq_params) {
+-                      nla_parse(tb, NL80211_TXQ_ATTR_MAX,
+-                                nla_data(nl_txq_params),
+-                                nla_len(nl_txq_params),
+-                                txq_params_policy);
++                      result = nla_parse(tb, NL80211_TXQ_ATTR_MAX,
++                                         nla_data(nl_txq_params),
++                                         nla_len(nl_txq_params),
++                                         txq_params_policy);
++                      if (result)
++                              goto bad_res;
+                       result = parse_txq_params(tb, &txq_params);
+                       if (result)
+                               goto bad_res;
+@@ -3289,7 +3292,7 @@ static int nl80211_start_ap(struct sk_bu
+       if (!err) {
+               wdev->preset_chandef = params.chandef;
+               wdev->beacon_interval = params.beacon_interval;
+-              wdev->channel = params.chandef.chan;
++              wdev->chandef = params.chandef;
+               wdev->ssid_len = params.ssid_len;
+               memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
+       }
+@@ -5210,9 +5213,11 @@ static int nl80211_set_reg(struct sk_buf
+       nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
+                           rem_reg_rules) {
+-              nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
+-                        nla_data(nl_reg_rule), nla_len(nl_reg_rule),
+-                        reg_rule_policy);
++              r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
++                            nla_data(nl_reg_rule), nla_len(nl_reg_rule),
++                            reg_rule_policy);
++              if (r)
++                      goto bad_reg;
+               r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]);
+               if (r)
+                       goto bad_reg;
+@@ -5277,7 +5282,7 @@ static int nl80211_trigger_scan(struct s
+       if (!rdev->ops->scan)
+               return -EOPNOTSUPP;
+-      if (rdev->scan_req) {
++      if (rdev->scan_req || rdev->scan_msg) {
+               err = -EBUSY;
+               goto unlock;
+       }
+@@ -5475,6 +5480,7 @@ static int nl80211_start_sched_scan(stru
+       enum ieee80211_band band;
+       size_t ie_len;
+       struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
++      s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
+       if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
+           !rdev->ops->sched_scan_start)
+@@ -5509,11 +5515,40 @@ static int nl80211_start_sched_scan(stru
+       if (n_ssids > wiphy->max_sched_scan_ssids)
+               return -EINVAL;
+-      if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH])
++      /*
++       * First, count the number of 'real' matchsets. Due to an issue with
++       * the old implementation, matchsets containing only the RSSI attribute
++       * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default'
++       * RSSI for all matchsets, rather than their own matchset for reporting
++       * all APs with a strong RSSI. This is needed to be compatible with
++       * older userspace that treated a matchset with only the RSSI as the
++       * global RSSI for all other matchsets - if there are other matchsets.
++       */
++      if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
+               nla_for_each_nested(attr,
+                                   info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
+-                                  tmp)
+-                      n_match_sets++;
++                                  tmp) {
++                      struct nlattr *rssi;
++
++                      err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
++                                      nla_data(attr), nla_len(attr),
++                                      nl80211_match_policy);
++                      if (err)
++                              return err;
++                      /* add other standalone attributes here */
++                      if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
++                              n_match_sets++;
++                              continue;
++                      }
++                      rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
++                      if (rssi)
++                              default_match_rssi = nla_get_s32(rssi);
++              }
++      }
++
++      /* However, if there's no other matchset, add the RSSI one */
++      if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF)
++              n_match_sets = 1;
+       if (n_match_sets > wiphy->max_match_sets)
+               return -EINVAL;
+@@ -5634,11 +5669,22 @@ static int nl80211_start_sched_scan(stru
+                                   tmp) {
+                       struct nlattr *ssid, *rssi;
+-                      nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
+-                                nla_data(attr), nla_len(attr),
+-                                nl80211_match_policy);
++                      err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX,
++                                      nla_data(attr), nla_len(attr),
++                                      nl80211_match_policy);
++                      if (err)
++                              goto out_free;
+                       ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID];
+                       if (ssid) {
++                              if (WARN_ON(i >= n_match_sets)) {
++                                      /* this indicates a programming error,
++                                       * the loop above should have verified
++                                       * things properly
++                                       */
++                                      err = -EINVAL;
++                                      goto out_free;
++                              }
++
+                               if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) {
+                                       err = -EINVAL;
+                                       goto out_free;
+@@ -5647,15 +5693,28 @@ static int nl80211_start_sched_scan(stru
+                                      nla_data(ssid), nla_len(ssid));
+                               request->match_sets[i].ssid.ssid_len =
+                                       nla_len(ssid);
++                              /* special attribute - old implemenation w/a */
++                              request->match_sets[i].rssi_thold =
++                                      default_match_rssi;
++                              rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
++                              if (rssi)
++                                      request->match_sets[i].rssi_thold =
++                                              nla_get_s32(rssi);
+                       }
+-                      rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
+-                      if (rssi)
+-                              request->rssi_thold = nla_get_u32(rssi);
+-                      else
+-                              request->rssi_thold =
+-                                                 NL80211_SCAN_RSSI_THOLD_OFF;
+                       i++;
+               }
++
++              /* there was no other matchset, so the RSSI one is alone */
++              if (i == 0)
++                      request->match_sets[0].rssi_thold = default_match_rssi;
++
++              request->min_rssi_thold = INT_MAX;
++              for (i = 0; i < n_match_sets; i++)
++                      request->min_rssi_thold =
++                              min(request->match_sets[i].rssi_thold,
++                                  request->min_rssi_thold);
++      } else {
++              request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF;
+       }
+       if (info->attrs[NL80211_ATTR_IE]) {
+@@ -5751,7 +5810,7 @@ static int nl80211_start_radar_detection
+       err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
+       if (!err) {
+-              wdev->channel = chandef.chan;
++              wdev->chandef = chandef;
+               wdev->cac_started = true;
+               wdev->cac_start_time = jiffies;
+       }
+@@ -7502,16 +7561,19 @@ static int nl80211_set_tx_bitrate_mask(s
+        * directly to the enum ieee80211_band values used in cfg80211.
+        */
+       BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
+-      nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
+-      {
++      nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
+               enum ieee80211_band band = nla_type(tx_rates);
++              int err;
++
+               if (band < 0 || band >= IEEE80211_NUM_BANDS)
+                       return -EINVAL;
+               sband = rdev->wiphy.bands[band];
+               if (sband == NULL)
+                       return -EINVAL;
+-              nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
+-                        nla_len(tx_rates), nl80211_txattr_policy);
++              err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
++                              nla_len(tx_rates), nl80211_txattr_policy);
++              if (err)
++                      return err;
+               if (tb[NL80211_TXRATE_LEGACY]) {
+                       mask.control[band].legacy = rateset_to_mask(
+                               sband,
+@@ -10054,40 +10116,31 @@ void nl80211_send_scan_start(struct cfg8
+                               NL80211_MCGRP_SCAN, GFP_KERNEL);
+ }
+-void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
+-                          struct wireless_dev *wdev)
++struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
++                                     struct wireless_dev *wdev, bool aborted)
+ {
+       struct sk_buff *msg;
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!msg)
+-              return;
++              return NULL;
+       if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
+-                                NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
++                                aborted ? NL80211_CMD_SCAN_ABORTED :
++                                          NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
+               nlmsg_free(msg);
+-              return;
++              return NULL;
+       }
+-      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+-                              NL80211_MCGRP_SCAN, GFP_KERNEL);
++      return msg;
+ }
+-void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
+-                             struct wireless_dev *wdev)
++void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
++                            struct sk_buff *msg)
+ {
+-      struct sk_buff *msg;
 -
--              rate_control_rate_init(sta);
--              netif_carrier_on(dev);
--      } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
-+      if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
-               rcu_assign_pointer(local->p2p_sdata, sdata);
+-      msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       if (!msg)
+               return;
+-      if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0,
+-                                NL80211_CMD_SCAN_ABORTED) < 0) {
+-              nlmsg_free(msg);
+-              return;
 -      }
+-
+       genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+                               NL80211_MCGRP_SCAN, GFP_KERNEL);
+ }
+@@ -11158,7 +11211,8 @@ void cfg80211_ch_switch_notify(struct ne
+                   wdev->iftype != NL80211_IFTYPE_MESH_POINT))
+               return;
  
-       /*
-        * set_multicast_list will be invoked by the networking core
-@@ -1116,6 +1093,74 @@ static void ieee80211_if_setup(struct ne
-       dev->destructor = free_netdev;
+-      wdev->channel = chandef->chan;
++      wdev->chandef = *chandef;
++      wdev->preset_chandef = *chandef;
+       nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
+ }
+ EXPORT_SYMBOL(cfg80211_ch_switch_notify);
+@@ -11673,6 +11727,35 @@ void cfg80211_crit_proto_stopped(struct 
  }
+ EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
  
-+static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
-+                                       struct sk_buff *skb)
++void nl80211_send_ap_stopped(struct wireless_dev *wdev)
 +{
-+      struct ieee80211_local *local = sdata->local;
-+      struct ieee80211_rx_status *rx_status;
-+      struct ieee802_11_elems elems;
-+      struct ieee80211_mgmt *mgmt;
-+      struct sta_info *sta;
-+      size_t baselen;
-+      u32 rates = 0;
-+      u16 stype;
-+      bool new = false;
-+      enum ieee80211_band band;
-+      struct ieee80211_supported_band *sband;
-+
-+      rx_status = IEEE80211_SKB_RXCB(skb);
-+      band = rx_status->band;
-+      sband = local->hw.wiphy->bands[band];
-+      mgmt = (struct ieee80211_mgmt *) skb->data;
-+      stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
-+
-+      if (stype != IEEE80211_STYPE_BEACON)
-+              return;
++      struct wiphy *wiphy = wdev->wiphy;
++      struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
++      struct sk_buff *msg;
++      void *hdr;
 +
-+      baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
-+      if (baselen > skb->len)
++      msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
++      if (!msg)
 +              return;
 +
-+      ieee802_11_parse_elems(mgmt->u.probe_resp.variable,
-+                             skb->len - baselen, false, &elems);
++      hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP);
++      if (!hdr)
++              goto out;
 +
-+      rates = ieee80211_sta_get_rates(local, &elems, band, NULL);
++      if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
++          nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
++          nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
++              goto out;
 +
-+      rcu_read_lock();
++      genlmsg_end(msg, hdr);
 +
-+      sta = sta_info_get(sdata, sdata->u.wds.remote_addr);
++      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0,
++                              NL80211_MCGRP_MLME, GFP_KERNEL);
++      return;
++ out:
++      nlmsg_free(msg);
++}
 +
-+      if (!sta) {
-+              rcu_read_unlock();
-+              sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr,
-+                                   GFP_KERNEL);
-+              if (!sta)
-+                      return;
+ /* initialisation/exit functions */
+ int nl80211_init(void)
+--- a/net/wireless/nl80211.h
++++ b/net/wireless/nl80211.h
+@@ -8,10 +8,10 @@ void nl80211_exit(void);
+ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev);
+ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev,
+                            struct wireless_dev *wdev);
+-void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
+-                          struct wireless_dev *wdev);
+-void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
+-                             struct wireless_dev *wdev);
++struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev,
++                                     struct wireless_dev *wdev, bool aborted);
++void nl80211_send_scan_result(struct cfg80211_registered_device *rdev,
++                            struct sk_buff *msg);
+ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
+                            struct net_device *netdev, u32 cmd);
+ void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
+@@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_reg
+                    enum nl80211_radar_event event,
+                    struct net_device *netdev, gfp_t gfp);
++void nl80211_send_ap_stopped(struct wireless_dev *wdev);
 +
-+              new = true;
+ void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev);
+ #endif /* __NET_WIRELESS_NL80211_H */
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct
+               dev->bss_generation++;
+ }
+-void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
++void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,
++                         bool send_message)
+ {
+       struct cfg80211_scan_request *request;
+       struct wireless_dev *wdev;
++      struct sk_buff *msg;
+ #ifdef CPTCFG_CFG80211_WEXT
+       union iwreq_data wrqu;
+ #endif
+       ASSERT_RTNL();
+-      request = rdev->scan_req;
++      if (rdev->scan_msg) {
++              nl80211_send_scan_result(rdev, rdev->scan_msg);
++              rdev->scan_msg = NULL;
++              return;
 +      }
++      request = rdev->scan_req;
+       if (!request)
+               return;
+@@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg802
+       if (wdev->netdev)
+               cfg80211_sme_scan_done(wdev->netdev);
+-      if (request->aborted) {
+-              nl80211_send_scan_aborted(rdev, wdev);
+-      } else {
+-              if (request->flags & NL80211_SCAN_FLAG_FLUSH) {
+-                      /* flush entries from previous scans */
+-                      spin_lock_bh(&rdev->bss_lock);
+-                      __cfg80211_bss_expire(rdev, request->scan_start);
+-                      spin_unlock_bh(&rdev->bss_lock);
+-              }
+-              nl80211_send_scan_done(rdev, wdev);
++      if (!request->aborted &&
++          request->flags & NL80211_SCAN_FLAG_FLUSH) {
++              /* flush entries from previous scans */
++              spin_lock_bh(&rdev->bss_lock);
++              __cfg80211_bss_expire(rdev, request->scan_start);
++              spin_unlock_bh(&rdev->bss_lock);
+       }
++      msg = nl80211_build_scan_msg(rdev, wdev, request->aborted);
 +
-+      sta->last_rx = jiffies;
-+      sta->sta.supp_rates[band] = rates;
+ #ifdef CPTCFG_CFG80211_WEXT
+       if (wdev->netdev && !request->aborted) {
+               memset(&wrqu, 0, sizeof(wrqu));
+@@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg802
+       rdev->scan_req = NULL;
+       kfree(request);
 +
-+      if (elems.ht_cap_elem)
-+              ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
-+                              elems.ht_cap_elem, sta);
++      if (!send_message)
++              rdev->scan_msg = msg;
++      else
++              nl80211_send_scan_result(rdev, msg);
+ }
+ void __cfg80211_scan_done(struct work_struct *wk)
+@@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_st
+                           scan_done_wk);
+       rtnl_lock();
+-      ___cfg80211_scan_done(rdev);
++      ___cfg80211_scan_done(rdev, true);
+       rtnl_unlock();
+ }
+@@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_dev
+       if (IS_ERR(rdev))
+               return PTR_ERR(rdev);
+-      if (rdev->scan_req) {
++      if (rdev->scan_req || rdev->scan_msg) {
+               err = -EBUSY;
+               goto out;
+       }
+@@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_dev
+       if (IS_ERR(rdev))
+               return PTR_ERR(rdev);
+-      if (rdev->scan_req)
++      if (rdev->scan_req || rdev->scan_msg)
+               return -EAGAIN;
+       res = ieee80211_scan_results(rdev, info, extra, data->length);
+--- a/net/wireless/sme.c
++++ b/net/wireless/sme.c
+@@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wir
+       ASSERT_RDEV_LOCK(rdev);
+       ASSERT_WDEV_LOCK(wdev);
+-      if (rdev->scan_req)
++      if (rdev->scan_req || rdev->scan_msg)
+               return -EBUSY;
+       if (wdev->conn->params.channel)
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -1001,7 +1001,6 @@ ieee80211_sta_process_chanswitch(struct 
+       }
+       ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
+-      sdata->vif.csa_active = true;
+       mutex_lock(&local->chanctx_mtx);
+       if (local->use_chanctx) {
+@@ -1039,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct 
+       mutex_unlock(&local->chanctx_mtx);
+       sdata->csa_chandef = csa_ie.chandef;
++      sdata->vif.csa_active = true;
+       if (csa_ie.mode)
+               ieee80211_stop_queues_by_reason(&local->hw,
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -196,6 +196,8 @@ static bool ieee80211_is_radar_required(
+ {
+       struct ieee80211_sub_if_data *sdata;
++      lockdep_assert_held(&local->mtx);
++
+       rcu_read_lock();
+       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+               if (sdata->radar_required) {
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -294,7 +294,6 @@ static void __ieee80211_sta_join_ibss(st
+       }
+       mutex_lock(&local->mtx);
+-      ieee80211_vif_release_channel(sdata);
+       if (ieee80211_vif_use_channel(sdata, &chandef,
+                                     ifibss->fixed_channel ?
+                                       IEEE80211_CHANCTX_SHARED :
+@@ -303,6 +302,7 @@ static void __ieee80211_sta_join_ibss(st
+               mutex_unlock(&local->mtx);
+               return;
+       }
++      sdata->radar_required = radar_required;
+       mutex_unlock(&local->mtx);
+       memcpy(ifibss->bssid, bssid, ETH_ALEN);
+@@ -318,7 +318,6 @@ static void __ieee80211_sta_join_ibss(st
+       rcu_assign_pointer(ifibss->presp, presp);
+       mgmt = (void *)presp->head;
+-      sdata->radar_required = radar_required;
+       sdata->vif.bss_conf.enable_beacon = true;
+       sdata->vif.bss_conf.beacon_int = beacon_int;
+       sdata->vif.bss_conf.basic_rates = basic_rates;
+@@ -386,7 +385,7 @@ static void __ieee80211_sta_join_ibss(st
+                                             presp->head_len, 0, GFP_KERNEL);
+       cfg80211_put_bss(local->hw.wiphy, bss);
+       netif_carrier_on(sdata->dev);
+-      cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
++      cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL);
+ }
+ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
+@@ -802,6 +801,8 @@ ieee80211_ibss_process_chanswitch(struct
+       int err;
+       u32 sta_flags;
++      sdata_assert_lock(sdata);
 +
-+      if (elems.wmm_param)
-+              set_sta_flag(sta, WLAN_STA_WME);
+       sta_flags = IEEE80211_STA_DISABLE_VHT;
+       switch (ifibss->chandef.width) {
+       case NL80211_CHAN_WIDTH_5:
+@@ -1471,6 +1472,11 @@ static void ieee80211_rx_mgmt_probe_req(
+       memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN);
+       ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa);
+       IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
 +
-+      if (new) {
-+              sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
-+              sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
-+              sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
-+              rate_control_rate_init(sta);
-+              sta_info_insert_rcu(sta);
-+      }
++      /* avoid excessive retries for probe request to wildcard SSIDs */
++      if (pos[1] == 0)
++              IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK;
 +
-+      rcu_read_unlock();
-+}
+       ieee80211_tx_skb(sdata, skb);
+ }
+--- a/net/mac80211/mesh.c
++++ b/net/mac80211/mesh.c
+@@ -872,6 +872,8 @@ ieee80211_mesh_process_chnswitch(struct 
+       if (!ifmsh->mesh_id)
+               return false;
++      sdata_assert_lock(sdata);
 +
- static void ieee80211_iface_work(struct work_struct *work)
+       sta_flags = IEEE80211_STA_DISABLE_VHT;
+       switch (sdata->vif.bss_conf.chandef.width) {
+       case NL80211_CHAN_WIDTH_20_NOHT:
+--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
++++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+@@ -4658,6 +4658,7 @@ brcmf_notify_connect_status(struct brcmf
+       struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+       struct net_device *ndev = ifp->ndev;
+       struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
++      struct ieee80211_channel *chan;
+       s32 err = 0;
+       if (ifp->vif->mode == WL_MODE_AP) {
+@@ -4665,9 +4666,10 @@ brcmf_notify_connect_status(struct brcmf
+       } else if (brcmf_is_linkup(e)) {
+               brcmf_dbg(CONN, "Linkup\n");
+               if (brcmf_is_ibssmode(ifp->vif)) {
++                      chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
+                       memcpy(profile->bssid, e->addr, ETH_ALEN);
+                       wl_inform_ibss(cfg, ndev, e->addr);
+-                      cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
++                      cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
+                       clear_bit(BRCMF_VIF_STATUS_CONNECTING,
+                                 &ifp->vif->sme_state);
+                       set_bit(BRCMF_VIF_STATUS_CONNECTED,
+--- a/drivers/net/wireless/libertas/cfg.c
++++ b/drivers/net/wireless/libertas/cfg.c
+@@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_pri
+       memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
+       priv->wdev->ssid_len = params->ssid_len;
+-      cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
++      cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan,
++                           GFP_KERNEL);
+       /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
+       priv->connect_status = LBS_CONNECTED;
+--- a/drivers/net/wireless/mwifiex/cfg80211.c
++++ b/drivers/net/wireless/mwifiex/cfg80211.c
+@@ -1881,7 +1881,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy 
+                                    params->privacy);
+ done:
+       if (!ret) {
+-              cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
++              cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
++                                   params->chandef.chan, GFP_KERNEL);
+               dev_dbg(priv->adapter->dev,
+                       "info: joined/created adhoc network with bssid"
+                       " %pM successfully\n", priv->cfg_bssid);
+--- a/drivers/net/wireless/rndis_wlan.c
++++ b/drivers/net/wireless/rndis_wlan.c
+@@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(s
+                                       bssid, req_ie, req_ie_len,
+                                       resp_ie, resp_ie_len, GFP_KERNEL);
+       } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
+-              cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
++              cfg80211_ibss_joined(usbdev->net, bssid,
++                                   get_current_channel(usbdev, NULL),
++                                   GFP_KERNEL);
+       kfree(info);
+--- a/net/wireless/ibss.c
++++ b/net/wireless/ibss.c
+@@ -14,7 +14,8 @@
+ #include "rdev-ops.h"
+-void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
++void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
++                          struct ieee80211_channel *channel)
+ {
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       struct cfg80211_bss *bss;
+@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_d
+       if (!wdev->ssid_len)
+               return;
+-      bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
+-                             wdev->ssid, wdev->ssid_len,
++      bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
+                              WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
+       if (WARN_ON(!bss))
+@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_d
+ #endif
+ }
+-void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
++void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
++                        struct ieee80211_channel *channel, gfp_t gfp)
  {
-       struct ieee80211_sub_if_data *sdata =
-@@ -1220,6 +1265,9 @@ static void ieee80211_iface_work(struct 
-                               break;
-                       ieee80211_mesh_rx_queued_mgmt(sdata, skb);
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+       struct cfg80211_event *ev;
+       unsigned long flags;
+-      trace_cfg80211_ibss_joined(dev, bssid);
++      trace_cfg80211_ibss_joined(dev, bssid, channel);
++
++      if (WARN_ON(!channel))
++              return;
+       ev = kzalloc(sizeof(*ev), gfp);
+       if (!ev)
+               return;
+       ev->type = EVENT_IBSS_JOINED;
+-      memcpy(ev->cr.bssid, bssid, ETH_ALEN);
++      memcpy(ev->ij.bssid, bssid, ETH_ALEN);
++      ev->ij.channel = channel;
+       spin_lock_irqsave(&wdev->event_lock, flags);
+       list_add_tail(&ev->list, &wdev->event_list);
+@@ -117,6 +122,7 @@ int __cfg80211_join_ibss(struct cfg80211
+       wdev->ibss_fixed = params->channel_fixed;
+       wdev->ibss_dfs_possible = params->userspace_handles_dfs;
++      wdev->chandef = params->chandef;
+ #ifdef CPTCFG_CFG80211_WEXT
+       wdev->wext.ibss.chandef = params->chandef;
+ #endif
+@@ -200,6 +206,7 @@ static void __cfg80211_clear_ibss(struct
+       wdev->current_bss = NULL;
+       wdev->ssid_len = 0;
++      memset(&wdev->chandef, 0, sizeof(wdev->chandef));
+ #ifdef CPTCFG_CFG80211_WEXT
+       if (!nowext)
+               wdev->wext.ibss.ssid_len = 0;
+--- a/net/wireless/trace.h
++++ b/net/wireless/trace.h
+@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
+       TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
+ );
+-DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
+-      TP_PROTO(struct net_device *netdev, const u8 *addr),
+-      TP_ARGS(netdev, addr)
+-);
+-
+ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
+       TP_PROTO(struct net_device *netdev, const u8 *addr),
+       TP_ARGS(netdev, addr)
+@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_r
+       TP_ARGS(netdev, addr)
+ );
++TRACE_EVENT(cfg80211_ibss_joined,
++      TP_PROTO(struct net_device *netdev, const u8 *bssid,
++               struct ieee80211_channel *channel),
++      TP_ARGS(netdev, bssid, channel),
++      TP_STRUCT__entry(
++              NETDEV_ENTRY
++              MAC_ENTRY(bssid)
++              CHAN_ENTRY
++      ),
++      TP_fast_assign(
++              NETDEV_ASSIGN;
++              MAC_ASSIGN(bssid, bssid);
++              CHAN_ASSIGN(channel);
++      ),
++      TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
++                NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
++);
++
+ TRACE_EVENT(cfg80211_probe_status,
+       TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
+                bool acked),
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct
+                                               ev->dc.reason, true);
                        break;
-+              case NL80211_IFTYPE_WDS:
-+                      ieee80211_wds_rx_queued_mgmt(sdata, skb);
-+                      break;
-               default:
-                       WARN(1, "frame for unexpected interface type");
+               case EVENT_IBSS_JOINED:
+-                      __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
++                      __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
++                                             ev->ij.channel);
                        break;
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -804,10 +804,18 @@ minstrel_ht_get_rate(void *priv, struct 
-       sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
-       info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-+      rate->count = 1;
-+
-+      if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
-+              int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
-+              rate->idx = mp->cck_rates[idx];
-+              rate->flags = 0;
-+              return;
-+      }
+               }
+               wdev_unlock(wdev);
+@@ -1356,7 +1357,7 @@ int cfg80211_can_use_iftype_chan(struct 
+                */
+               mutex_lock_nested(&wdev_iter->mtx, 1);
+               __acquire(wdev_iter->mtx);
+-              cfg80211_get_chan_state(wdev_iter, &ch, &chmode);
++              cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect);
+               wdev_unlock(wdev_iter);
+               switch (chmode) {
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -642,7 +642,8 @@ int cfg80211_set_monitor_channel(struct 
+ void
+ cfg80211_get_chan_state(struct wireless_dev *wdev,
+                       struct ieee80211_channel **chan,
+-                      enum cfg80211_chan_mode *chanmode)
++                      enum cfg80211_chan_mode *chanmode,
++                      u8 *radar_detect)
+ {
+       *chan = NULL;
+       *chanmode = CHAN_MODE_UNDEFINED;
+@@ -660,6 +661,11 @@ cfg80211_get_chan_state(struct wireless_
+                                    !wdev->ibss_dfs_possible)
+                                 ? CHAN_MODE_SHARED
+                                 : CHAN_MODE_EXCLUSIVE;
 +
-       rate->idx = sample_idx % MCS_GROUP_RATES +
-                   (sample_group->streams - 1) * MCS_GROUP_RATES;
-       rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
--      rate->count = 1;
- }
++                      /* consider worst-case - IBSS can try to return to the
++                       * original user-specified channel as creator */
++                      if (wdev->ibss_dfs_possible)
++                              *radar_detect |= BIT(wdev->chandef.width);
+                       return;
+               }
+               break;
+@@ -674,17 +680,26 @@ cfg80211_get_chan_state(struct wireless_
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_P2P_GO:
+               if (wdev->cac_started) {
+-                      *chan = wdev->channel;
++                      *chan = wdev->chandef.chan;
+                       *chanmode = CHAN_MODE_SHARED;
++                      *radar_detect |= BIT(wdev->chandef.width);
+               } else if (wdev->beacon_interval) {
+-                      *chan = wdev->channel;
++                      *chan = wdev->chandef.chan;
+                       *chanmode = CHAN_MODE_SHARED;
++
++                      if (cfg80211_chandef_dfs_required(wdev->wiphy,
++                                                        &wdev->chandef))
++                              *radar_detect |= BIT(wdev->chandef.width);
+               }
+               return;
+       case NL80211_IFTYPE_MESH_POINT:
+               if (wdev->mesh_id_len) {
+-                      *chan = wdev->channel;
++                      *chan = wdev->chandef.chan;
+                       *chanmode = CHAN_MODE_SHARED;
++
++                      if (cfg80211_chandef_dfs_required(wdev->wiphy,
++                                                        &wdev->chandef))
++                              *radar_detect |= BIT(wdev->chandef.width);
+               }
+               return;
+       case NL80211_IFTYPE_MONITOR:
+--- a/net/wireless/mesh.c
++++ b/net/wireless/mesh.c
+@@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211
+       if (!err) {
+               memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
+               wdev->mesh_id_len = setup->mesh_id_len;
+-              wdev->channel = setup->chandef.chan;
++              wdev->chandef = setup->chandef;
+       }
  
- static void
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -936,8 +936,14 @@ ieee80211_rx_h_check(struct ieee80211_rx
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+       return err;
+@@ -244,7 +244,7 @@ int cfg80211_set_mesh_channel(struct cfg
+               err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev,
+                                                    chandef->chan);
+               if (!err)
+-                      wdev->channel = chandef->chan;
++                      wdev->chandef = *chandef;
  
--      /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
--      if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
-+      /*
-+       * Drop duplicate 802.11 retransmissions
-+       * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
-+       */
-+      if (rx->skb->len >= 24 && rx->sta &&
-+          !ieee80211_is_ctl(hdr->frame_control) &&
-+          !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
-+          !is_multicast_ether_addr(hdr->addr1)) {
-               if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
-                            rx->sta->last_seq_ctrl[rx->seqno_idx] ==
-                            hdr->seq_ctrl)) {
-@@ -2369,6 +2375,7 @@ ieee80211_rx_h_action(struct ieee80211_r
-                   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_WDS &&
-                   sdata->vif.type != NL80211_IFTYPE_ADHOC)
+               return err;
+       }
+@@ -276,7 +276,7 @@ static int __cfg80211_leave_mesh(struct 
+       err = rdev_leave_mesh(rdev, dev);
+       if (!err) {
+               wdev->mesh_id_len = 0;
+-              wdev->channel = NULL;
++              memset(&wdev->chandef, 0, sizeof(wdev->chandef));
+               rdev_set_qos_map(rdev, dev, NULL);
+       }
+--- a/net/wireless/mlme.c
++++ b/net/wireless/mlme.c
+@@ -772,7 +772,7 @@ void cfg80211_cac_event(struct net_devic
+       if (WARN_ON(!wdev->cac_started))
+               return;
+-      if (WARN_ON(!wdev->channel))
++      if (WARN_ON(!wdev->chandef.chan))
+               return;
+       switch (event) {
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -5065,6 +5065,10 @@ static u16 ar9003_hw_get_max_edge_power(
                        break;
+               }
+       }
++
++      if (is2GHz && !twiceMaxEdgePower)
++              twiceMaxEdgePower = 60;
++
+       return twiceMaxEdgePower;
+ }
  
-@@ -2720,14 +2727,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
-       if (!ieee80211_vif_is_mesh(&sdata->vif) &&
-           sdata->vif.type != NL80211_IFTYPE_ADHOC &&
--          sdata->vif.type != NL80211_IFTYPE_STATION)
-+          sdata->vif.type != NL80211_IFTYPE_STATION &&
-+          sdata->vif.type != NL80211_IFTYPE_WDS)
-               return RX_DROP_MONITOR;
-       switch (stype) {
-       case cpu_to_le16(IEEE80211_STYPE_AUTH):
-       case cpu_to_le16(IEEE80211_STYPE_BEACON):
-       case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
--              /* process for all: mesh, mlme, ibss */
-+              /* process for all: mesh, mlme, ibss, wds */
-               break;
-       case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
-       case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
-@@ -3008,6 +3016,9 @@ static int prepare_for_handlers(struct i
-       case NL80211_IFTYPE_ADHOC:
-               if (!bssid)
-                       return 0;
-+              if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
-+                  ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
-+                      return 0;
-               if (ieee80211_is_beacon(hdr->frame_control)) {
-                       return 1;
-               } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
-@@ -3059,10 +3070,16 @@ static int prepare_for_handlers(struct i
+--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+@@ -23,10 +23,11 @@
+ #define MAX_MEASUREMENT       MAX_IQCAL_MEASUREMENT
+ #define MAX_MAG_DELTA 11
+ #define MAX_PHS_DELTA 10
++#define MAXIQCAL        3
+ struct coeff {
+-      int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
+-      int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
++      int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
++      int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
+       int iqc_coeff[2];
+ };
+@@ -800,7 +801,7 @@ static bool ar9003_hw_calc_iq_corr(struc
+       if (q_q_coff > 63)
+               q_q_coff = 63;
+-      iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
++      iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
+       ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
+               chain_idx, iqc_coeff[0]);
+@@ -831,7 +832,7 @@ static bool ar9003_hw_calc_iq_corr(struc
+       if (q_q_coff > 63)
+               q_q_coff = 63;
+-      iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
++      iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
+       ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
+               chain_idx, iqc_coeff[1]);
+@@ -839,7 +840,8 @@ static bool ar9003_hw_calc_iq_corr(struc
+       return true;
+ }
+-static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
++static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL],
++                                   int nmeasurement,
+                                    int max_delta)
+ {
+       int mp_max = -64, max_idx = 0;
+@@ -848,20 +850,20 @@ static void ar9003_hw_detect_outlier(int
+       /* find min/max mismatch across all calibrated gains */
+       for (i = 0; i < nmeasurement; i++) {
+-              if (mp_coeff[i] > mp_max) {
+-                      mp_max = mp_coeff[i];
++              if (mp_coeff[i][0] > mp_max) {
++                      mp_max = mp_coeff[i][0];
+                       max_idx = i;
+-              } else if (mp_coeff[i] < mp_min) {
+-                      mp_min = mp_coeff[i];
++              } else if (mp_coeff[i][0] < mp_min) {
++                      mp_min = mp_coeff[i][0];
+                       min_idx = i;
                }
-               break;
-       case NL80211_IFTYPE_WDS:
--              if (bssid || !ieee80211_is_data(hdr->frame_control))
--                      return 0;
-               if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2))
-                       return 0;
-+
-+              if (ieee80211_is_data(hdr->frame_control) ||
-+                  ieee80211_is_action(hdr->frame_control)) {
-+                      if (compare_ether_addr(sdata->vif.addr, hdr->addr1))
-+                              return 0;
-+              } else if (!ieee80211_is_beacon(hdr->frame_control))
-+                      return 0;
+       }
+       /* find average (exclude max abs value) */
+       for (i = 0; i < nmeasurement; i++) {
+-              if ((abs(mp_coeff[i]) < abs(mp_max)) ||
+-                  (abs(mp_coeff[i]) < abs(mp_min))) {
+-                      mp_avg += mp_coeff[i];
++              if ((abs(mp_coeff[i][0]) < abs(mp_max)) ||
++                  (abs(mp_coeff[i][0]) < abs(mp_min))) {
++                      mp_avg += mp_coeff[i][0];
+                       mp_count++;
+               }
+       }
+@@ -873,7 +875,7 @@ static void ar9003_hw_detect_outlier(int
+       if (mp_count)
+               mp_avg /= mp_count;
+       else
+-              mp_avg = mp_coeff[nmeasurement - 1];
++              mp_avg = mp_coeff[nmeasurement - 1][0];
+       /* detect outlier */
+       if (abs(mp_max - mp_min) > max_delta) {
+@@ -882,15 +884,16 @@ static void ar9003_hw_detect_outlier(int
+               else
+                       outlier_idx = min_idx;
+-              mp_coeff[outlier_idx] = mp_avg;
++              mp_coeff[outlier_idx][0] = mp_avg;
+       }
+ }
+-static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
+-                                               struct coeff *coeff,
+-                                               bool is_reusable)
++static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah,
++                                                struct coeff *coeff,
++                                                bool is_reusable)
+ {
+       int i, im, nmeasurement;
++      int magnitude, phase;
+       u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+@@ -920,21 +923,30 @@ static void ar9003_hw_tx_iqcal_load_avg_
+               if (nmeasurement > MAX_MEASUREMENT)
+                       nmeasurement = MAX_MEASUREMENT;
+-              /* detect outlier only if nmeasurement > 1 */
+-              if (nmeasurement > 1) {
+-                      /* Detect magnitude outlier */
+-                      ar9003_hw_detect_outlier(coeff->mag_coeff[i],
+-                                      nmeasurement, MAX_MAG_DELTA);
+-
+-                      /* Detect phase outlier */
+-                      ar9003_hw_detect_outlier(coeff->phs_coeff[i],
+-                                      nmeasurement, MAX_PHS_DELTA);
++              /*
++               * Skip normal outlier detection for AR9550.
++               */
++              if (!AR_SREV_9550(ah)) {
++                      /* detect outlier only if nmeasurement > 1 */
++                      if (nmeasurement > 1) {
++                              /* Detect magnitude outlier */
++                              ar9003_hw_detect_outlier(coeff->mag_coeff[i],
++                                                       nmeasurement,
++                                                       MAX_MAG_DELTA);
 +
-               break;
-       case NL80211_IFTYPE_P2P_DEVICE:
-               if (!ieee80211_is_public_action(hdr, skb->len) &&
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -32,7 +32,6 @@
-  * @WLAN_STA_SHORT_PREAMBLE: Station is capable of receiving short-preamble
-  *    frames.
-  * @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.
-@@ -66,7 +65,6 @@ enum ieee80211_sta_info_flags {
-       WLAN_STA_AUTHORIZED,
-       WLAN_STA_SHORT_PREAMBLE,
-       WLAN_STA_WME,
--      WLAN_STA_WDS,
-       WLAN_STA_CLEAR_PS_FILT,
-       WLAN_STA_MFP,
-       WLAN_STA_BLOCK_BA,
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -146,6 +146,28 @@ static void ath_set_rates(struct ieee802
-                              ARRAY_SIZE(bf->rates));
++                              /* Detect phase outlier */
++                              ar9003_hw_detect_outlier(coeff->phs_coeff[i],
++                                                       nmeasurement,
++                                                       MAX_PHS_DELTA);
++                      }
+               }
+               for (im = 0; im < nmeasurement; im++) {
++                      magnitude = coeff->mag_coeff[i][im][0];
++                      phase = coeff->phs_coeff[i][im][0];
+-                      coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
+-                              ((coeff->phs_coeff[i][im] & 0x7f) << 7);
++                      coeff->iqc_coeff[0] =
++                              (phase & 0x7f) | ((magnitude & 0x7f) << 7);
+                       if ((im % 2) == 0)
+                               REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+@@ -991,7 +1003,63 @@ static bool ar9003_hw_tx_iq_cal_run(stru
+       return true;
+ }
+-static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
++static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
++                                  struct coeff *coeff,
++                                  int i, int nmeasurement)
++{
++      struct ath_common *common = ath9k_hw_common(ah);
++      int im, ix, iy, temp;
++
++      for (im = 0; im < nmeasurement; im++) {
++              for (ix = 0; ix < MAXIQCAL - 1; ix++) {
++                      for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) {
++                              if (coeff->mag_coeff[i][im][iy] <
++                                  coeff->mag_coeff[i][im][ix]) {
++                                      temp = coeff->mag_coeff[i][im][ix];
++                                      coeff->mag_coeff[i][im][ix] =
++                                              coeff->mag_coeff[i][im][iy];
++                                      coeff->mag_coeff[i][im][iy] = temp;
++                              }
++                              if (coeff->phs_coeff[i][im][iy] <
++                                  coeff->phs_coeff[i][im][ix]) {
++                                      temp = coeff->phs_coeff[i][im][ix];
++                                      coeff->phs_coeff[i][im][ix] =
++                                              coeff->phs_coeff[i][im][iy];
++                                      coeff->phs_coeff[i][im][iy] = temp;
++                              }
++                      }
++              }
++              coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2];
++              coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2];
++
++              ath_dbg(common, CALIBRATE,
++                      "IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n",
++                      i, im,
++                      coeff->mag_coeff[i][im][0],
++                      coeff->phs_coeff[i][im][0]);
++      }
++}
++
++static bool ar955x_tx_iq_cal_median(struct ath_hw *ah,
++                                  struct coeff *coeff,
++                                  int iqcal_idx,
++                                  int nmeasurement)
++{
++      int i;
++
++      if ((iqcal_idx + 1) != MAXIQCAL)
++              return false;
++
++      for (i = 0; i < AR9300_MAX_CHAINS; i++) {
++              __ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement);
++      }
++
++      return true;
++}
++
++static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
++                                        int iqcal_idx,
++                                        bool is_reusable)
+ {
+       struct ath_common *common = ath9k_hw_common(ah);
+       const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
+@@ -1004,10 +1072,11 @@ static void ar9003_hw_tx_iq_cal_post_pro
+               AR_PHY_CHAN_INFO_TAB_1,
+               AR_PHY_CHAN_INFO_TAB_2,
+       };
+-      struct coeff coeff;
++      static struct coeff coeff;
+       s32 iq_res[6];
+       int i, im, j;
+-      int nmeasurement;
++      int nmeasurement = 0;
++      bool outlier_detect = true;
+       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+               if (!(ah->txchainmask & (1 << i)))
+@@ -1065,17 +1134,23 @@ static void ar9003_hw_tx_iq_cal_post_pro
+                               goto tx_iqcal_fail;
+                       }
+-                      coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
+-                      coeff.phs_coeff[i][im] =
++                      coeff.phs_coeff[i][im][iqcal_idx] =
++                              coeff.iqc_coeff[0] & 0x7f;
++                      coeff.mag_coeff[i][im][iqcal_idx] =
+                               (coeff.iqc_coeff[0] >> 7) & 0x7f;
+-                      if (coeff.mag_coeff[i][im] > 63)
+-                              coeff.mag_coeff[i][im] -= 128;
+-                      if (coeff.phs_coeff[i][im] > 63)
+-                              coeff.phs_coeff[i][im] -= 128;
++                      if (coeff.mag_coeff[i][im][iqcal_idx] > 63)
++                              coeff.mag_coeff[i][im][iqcal_idx] -= 128;
++                      if (coeff.phs_coeff[i][im][iqcal_idx] > 63)
++                              coeff.phs_coeff[i][im][iqcal_idx] -= 128;
+               }
+       }
+-      ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable);
++
++      if (AR_SREV_9550(ah))
++              outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff,
++                                                       iqcal_idx, nmeasurement);
++      if (outlier_detect)
++              ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
+       return;
+@@ -1409,7 +1484,7 @@ skip_tx_iqcal:
+       }
+       if (txiqcal_done)
+-              ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
++              ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
+       else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
+               ar9003_hw_tx_iq_cal_reload(ah);
+@@ -1455,14 +1530,38 @@ skip_tx_iqcal:
+       return true;
  }
  
-+static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
-+                           struct sk_buff *skb)
++static bool do_ar9003_agc_cal(struct ath_hw *ah)
 +{
-+      int q;
-+
-+      q = skb_get_queue_mapping(skb);
-+      if (txq == sc->tx.uapsdq)
-+              txq = sc->tx.txq_map[q];
-+
-+      if (txq != sc->tx.txq_map[q])
-+              return;
++      struct ath_common *common = ath9k_hw_common(ah);
++      bool status;
 +
-+      if (WARN_ON(--txq->pending_frames < 0))
-+              txq->pending_frames = 0;
++      REG_WRITE(ah, AR_PHY_AGC_CONTROL,
++                REG_READ(ah, AR_PHY_AGC_CONTROL) |
++                AR_PHY_AGC_CONTROL_CAL);
 +
-+      if (txq->stopped &&
-+          txq->pending_frames < sc->tx.txq_max_pending[q]) {
-+              ieee80211_wake_queue(sc->hw, q);
-+              txq->stopped = false;
++      status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
++                             AR_PHY_AGC_CONTROL_CAL,
++                             0, AH_WAIT_TIMEOUT);
++      if (!status) {
++              ath_dbg(common, CALIBRATE,
++                      "offset calibration failed to complete in %d ms,"
++                      "noisy environment?\n",
++                      AH_WAIT_TIMEOUT / 1000);
++              return false;
 +      }
++
++      return true;
 +}
 +
- static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
+ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
+                                  struct ath9k_channel *chan)
  {
-       struct ath_txq *txq = tid->ac->txq;
-@@ -167,6 +189,7 @@ static void ath_tx_flush_tid(struct ath_
-               if (!bf) {
-                       bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-                       if (!bf) {
-+                              ath_txq_skb_done(sc, txq, skb);
-                               ieee80211_free_txskb(sc->hw, skb);
-                               continue;
-                       }
-@@ -811,6 +834,7 @@ ath_tx_get_tid_subframe(struct ath_softc
-               if (!bf) {
-                       __skb_unlink(skb, &tid->buf_q);
-+                      ath_txq_skb_done(sc, txq, skb);
-                       ieee80211_free_txskb(sc->hw, skb);
-                       continue;
-               }
-@@ -1824,6 +1848,7 @@ static void ath_tx_send_ampdu(struct ath
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_hw_cal_data *caldata = ah->caldata;
+       bool txiqcal_done = false;
+-      bool is_reusable = true, status = true;
++      bool status = true;
+       bool run_agc_cal = false, sep_iq_cal = false;
++      int i = 0;
  
-       bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-       if (!bf) {
-+              ath_txq_skb_done(sc, txq, skb);
-               ieee80211_free_txskb(sc->hw, skb);
-               return;
-       }
-@@ -2090,6 +2115,7 @@ int ath_tx_start(struct ieee80211_hw *hw
+       /* Use chip chainmask only for calibration */
+       ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
+@@ -1485,7 +1584,12 @@ static bool ar9003_hw_init_cal_soc(struc
+        * AGC calibration. Specifically, AR9550 in SoC chips.
+        */
+       if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
+-              txiqcal_done = true;
++              if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
++                                 AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) {
++                              txiqcal_done = true;
++              } else {
++                      txiqcal_done = false;
++              }
+               run_agc_cal = true;
+       } else {
+               sep_iq_cal = true;
+@@ -1512,27 +1616,37 @@ skip_tx_iqcal:
+               if (AR_SREV_9330_11(ah))
+                       ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
  
-       bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-       if (!bf) {
-+              ath_txq_skb_done(sc, txq, skb);
-               if (txctl->paprd)
-                       dev_kfree_skb_any(skb);
-               else
-@@ -2189,7 +2215,7 @@ static void ath_tx_complete(struct ath_s
-       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;
--      int q, padpos, padsize;
-+      int padpos, padsize;
-       unsigned long flags;
+-              /* Calibrate the AGC */
+-              REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+-                        REG_READ(ah, AR_PHY_AGC_CONTROL) |
+-                        AR_PHY_AGC_CONTROL_CAL);
+-
+-              /* Poll for offset calibration complete */
+-              status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+-                                     AR_PHY_AGC_CONTROL_CAL,
+-                                     0, AH_WAIT_TIMEOUT);
+-      }
++              /*
++               * For non-AR9550 chips, we just trigger AGC calibration
++               * in the HW, poll for completion and then process
++               * the results.
++               *
++               * For AR955x, we run it multiple times and use
++               * median IQ correction.
++               */
++              if (!AR_SREV_9550(ah)) {
++                      status = do_ar9003_agc_cal(ah);
++                      if (!status)
++                              return false;
  
-       ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
-@@ -2225,21 +2251,7 @@ static void ath_tx_complete(struct ath_s
-       spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+-      if (!status) {
+-              ath_dbg(common, CALIBRATE,
+-                      "offset calibration failed to complete in %d ms; noisy environment?\n",
+-                      AH_WAIT_TIMEOUT / 1000);
+-              return false;
++                      if (txiqcal_done)
++                              ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
++              } else {
++                      if (!txiqcal_done) {
++                              status = do_ar9003_agc_cal(ah);
++                              if (!status)
++                                      return false;
++                      } else {
++                              for (i = 0; i < MAXIQCAL; i++) {
++                                      status = do_ar9003_agc_cal(ah);
++                                      if (!status)
++                                              return false;
++                                      ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
++                              }
++                      }
++              }
+       }
  
-       __skb_queue_tail(&txq->complete_q, skb);
--
--      q = skb_get_queue_mapping(skb);
--      if (txq == sc->tx.uapsdq)
--              txq = sc->tx.txq_map[q];
+-      if (txiqcal_done)
+-              ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
 -
--      if (txq == sc->tx.txq_map[q]) {
--              if (WARN_ON(--txq->pending_frames < 0))
--                      txq->pending_frames = 0;
--
--              if (txq->stopped &&
--                  txq->pending_frames < sc->tx.txq_max_pending[q]) {
--                      ieee80211_wake_queue(sc->hw, q);
--                      txq->stopped = false;
--              }
--      }
-+      ath_txq_skb_done(sc, txq, skb);
- }
+       /* Revert chainmask to runtime parameters */
+       ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
  
- static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -209,6 +209,7 @@ static bool ath_complete_reset(struct at
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       unsigned long flags;
-+      int i;
+--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
++++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
+@@ -15,6 +15,8 @@
+ #ifndef RTL8187_H
+ #define RTL8187_H
  
-       if (ath_startrecv(sc) != 0) {
-               ath_err(common, "Unable to restart recv logic\n");
-@@ -236,6 +237,15 @@ static bool ath_complete_reset(struct at
-               }
-       work:
-               ath_restart_work(sc);
++#include <linux/cache.h>
 +
-+              for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-+                      if (!ATH_TXQ_SETUP(sc, i))
-+                              continue;
-+
-+                      spin_lock_bh(&sc->tx.txq[i].axq_lock);
-+                      ath_txq_schedule(sc, &sc->tx.txq[i]);
-+                      spin_unlock_bh(&sc->tx.txq[i].axq_lock);
-+              }
-       }
+ #include "rtl818x.h"
+ #include "leds.h"
  
-       if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3)
-@@ -543,21 +553,10 @@ chip_reset:
+@@ -139,7 +141,10 @@ struct rtl8187_priv {
+       u8 aifsn[4];
+       u8 rfkill_mask;
+       struct {
+-              __le64 buf;
++              union {
++                      __le64 buf;
++                      u8 dummy1[L1_CACHE_BYTES];
++              } ____cacheline_aligned;
+               struct sk_buff_head queue;
+       } b_tx_status; /* This queue is used by both -b and non-b devices */
+       struct mutex io_mutex;
+@@ -147,7 +152,8 @@ struct rtl8187_priv {
+               u8 bits8;
+               __le16 bits16;
+               __le32 bits32;
+-      } *io_dmabuf;
++              u8 dummy2[L1_CACHE_BYTES];
++      } *io_dmabuf ____cacheline_aligned;
+       bool rfkill_off;
+       u16 seqno;
+ };
+--- a/net/mac80211/wme.c
++++ b/net/mac80211/wme.c
+@@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80
+               return IEEE80211_AC_BE;
+       }
  
- static int ath_reset(struct ath_softc *sc)
- {
--      int i, r;
-+      int r;
++      if (skb->protocol == sdata->control_port_protocol) {
++              skb->priority = 7;
++              return ieee80211_downgrade_queue(sdata, skb);
++      }
++
+       /* use the data classifier to determine what 802.1d tag the
+        * data frame has */
+       rcu_read_lock();
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_
+       for (tidno = 0, tid = &an->tid[tidno];
+            tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
  
-       ath9k_ps_wakeup(sc);
--
-       r = ath_reset_internal(sc, NULL);
--
--      for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
--              if (!ATH_TXQ_SETUP(sc, i))
+-              if (!tid->sched)
 -                      continue;
 -
--              spin_lock_bh(&sc->tx.txq[i].axq_lock);
--              ath_txq_schedule(sc, &sc->tx.txq[i]);
--              spin_unlock_bh(&sc->tx.txq[i].axq_lock);
--      }
--
-       ath9k_ps_restore(sc);
+               ac = tid->ac;
+               txq = ac->txq;
  
-       return r;
-@@ -2094,7 +2093,7 @@ static void ath9k_wow_add_pattern(struct
- {
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath9k_wow_pattern *wow_pattern = NULL;
--      struct cfg80211_wowlan_trig_pkt_pattern *patterns = wowlan->patterns;
-+      struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
-       int mask_len;
-       s8 i = 0;
+               ath_txq_lock(sc, txq);
  
---- a/drivers/net/wireless/mwifiex/cfg80211.c
-+++ b/drivers/net/wireless/mwifiex/cfg80211.c
-@@ -2298,8 +2298,7 @@ EXPORT_SYMBOL_GPL(mwifiex_del_virtual_in
++              if (!tid->sched) {
++                      ath_txq_unlock(sc, txq);
++                      continue;
++              }
++
+               buffered = ath_tid_has_buffered(tid);
  
- #ifdef CONFIG_PM
- static bool
--mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat,
--                           s8 *byte_seq)
-+mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq)
- {
-       int j, k, valid_byte_cnt = 0;
-       bool dont_care_byte = false;
---- a/drivers/net/wireless/ti/wlcore/main.c
-+++ b/drivers/net/wireless/ti/wlcore/main.c
-@@ -1315,7 +1315,7 @@ static struct sk_buff *wl12xx_alloc_dumm
- #ifdef CONFIG_PM
- static int
--wl1271_validate_wowlan_pattern(struct cfg80211_wowlan_trig_pkt_pattern *p)
-+wl1271_validate_wowlan_pattern(struct cfg80211_pkt_pattern *p)
- {
-       int num_fields = 0, in_field = 0, fields_size = 0;
-       int i, pattern_len = 0;
-@@ -1458,9 +1458,9 @@ void wl1271_rx_filter_flatten_fields(str
-  * Allocates an RX filter returned through f
-  * which needs to be freed using rx_filter_free()
-  */
--static int wl1271_convert_wowlan_pattern_to_rx_filter(
--      struct cfg80211_wowlan_trig_pkt_pattern *p,
--      struct wl12xx_rx_filter **f)
-+static int
-+wl1271_convert_wowlan_pattern_to_rx_filter(struct cfg80211_pkt_pattern *p,
-+                                         struct wl12xx_rx_filter **f)
- {
-       int i, j, ret = 0;
-       struct wl12xx_rx_filter *filter;
-@@ -1562,7 +1562,7 @@ static int wl1271_configure_wowlan(struc
+               tid->sched = false;
+@@ -1696,7 +1698,7 @@ int ath_cabq_update(struct ath_softc *sc
  
-       /* Translate WoWLAN patterns into filters */
-       for (i = 0; i < wow->n_patterns; i++) {
--              struct cfg80211_wowlan_trig_pkt_pattern *p;
-+              struct cfg80211_pkt_pattern *p;
-               struct wl12xx_rx_filter *filter = NULL;
+       ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
  
-               p = &wow->patterns[i];
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -1698,7 +1698,7 @@ struct cfg80211_pmksa {
- };
+-      qi.tqi_readyTime = (cur_conf->beacon_interval *
++      qi.tqi_readyTime = (TU_TO_USEC(cur_conf->beacon_interval) *
+                           ATH_CABQ_READY_TIME) / 100;
+       ath_txq_update(sc, qnum, &qi);
  
- /**
-- * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern
-+ * struct cfg80211_pkt_pattern - packet pattern
-  * @mask: bitmask where to match pattern and where to ignore bytes,
-  *    one bit per byte, in same format as nl80211
-  * @pattern: bytes to match where bitmask is 1
-@@ -1708,7 +1708,7 @@ struct cfg80211_pmksa {
-  * Internal note: @mask and @pattern are allocated in one chunk of
-  * memory, free @mask only!
-  */
--struct cfg80211_wowlan_trig_pkt_pattern {
-+struct cfg80211_pkt_pattern {
-       u8 *mask, *pattern;
-       int pattern_len;
-       int pkt_offset;
-@@ -1770,7 +1770,7 @@ struct cfg80211_wowlan {
-       bool any, disconnect, magic_pkt, gtk_rekey_failure,
-            eap_identity_req, four_way_handshake,
-            rfkill_release;
--      struct cfg80211_wowlan_trig_pkt_pattern *patterns;
-+      struct cfg80211_pkt_pattern *patterns;
-       struct cfg80211_wowlan_tcp *tcp;
-       int n_patterns;
- };
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -3060,11 +3060,11 @@ enum nl80211_tx_power_setting {
- };
+@@ -2061,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buff
  
- /**
-- * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute
-- * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute
-- * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has
-+ * enum nl80211_packet_pattern_attr - packet pattern attribute
-+ * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute
-+ * @NL80211_PKTPAT_PATTERN: the pattern, values where the mask has
-  *    a zero bit are ignored
-- * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have
-+ * @NL80211_PKTPAT_MASK: pattern mask, must be long enough to have
-  *    a bit for each byte in the pattern. The lowest-order bit corresponds
-  *    to the first byte of the pattern, but the bytes of the pattern are
-  *    in a little-endian-like format, i.e. the 9th byte of the pattern
-@@ -3075,23 +3075,23 @@ enum nl80211_tx_power_setting {
-  *    Note that the pattern matching is done as though frames were not
-  *    802.11 frames but 802.3 frames, i.e. the frame is fully unpacked
-  *    first (including SNAP header unpacking) and then matched.
-- * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after
-+ * @NL80211_PKTPAT_OFFSET: packet offset, pattern is matched after
-  *    these fixed number of bytes of received packet
-- * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes
-- * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number
-+ * @NUM_NL80211_PKTPAT: number of attributes
-+ * @MAX_NL80211_PKTPAT: max attribute number
-  */
--enum nl80211_wowlan_packet_pattern_attr {
--      __NL80211_WOWLAN_PKTPAT_INVALID,
--      NL80211_WOWLAN_PKTPAT_MASK,
--      NL80211_WOWLAN_PKTPAT_PATTERN,
--      NL80211_WOWLAN_PKTPAT_OFFSET,
-+enum nl80211_packet_pattern_attr {
-+      __NL80211_PKTPAT_INVALID,
-+      NL80211_PKTPAT_MASK,
-+      NL80211_PKTPAT_PATTERN,
-+      NL80211_PKTPAT_OFFSET,
--      NUM_NL80211_WOWLAN_PKTPAT,
--      MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1,
-+      NUM_NL80211_PKTPAT,
-+      MAX_NL80211_PKTPAT = NUM_NL80211_PKTPAT - 1,
- };
+       ATH_TXBUF_RESET(bf);
  
- /**
-- * struct nl80211_wowlan_pattern_support - pattern support information
-+ * struct nl80211_pattern_support - packet pattern support information
-  * @max_patterns: maximum number of patterns supported
-  * @min_pattern_len: minimum length of each pattern
-  * @max_pattern_len: maximum length of each pattern
-@@ -3101,13 +3101,22 @@ enum nl80211_wowlan_packet_pattern_attr 
-  * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the
-  * capability information given by the kernel to userspace.
-  */
--struct nl80211_wowlan_pattern_support {
-+struct nl80211_pattern_support {
-       __u32 max_patterns;
-       __u32 min_pattern_len;
-       __u32 max_pattern_len;
-       __u32 max_pkt_offset;
- } __attribute__((packed));
-+/* only for backward compatibility */
-+#define __NL80211_WOWLAN_PKTPAT_INVALID __NL80211_PKTPAT_INVALID
-+#define NL80211_WOWLAN_PKTPAT_MASK NL80211_PKTPAT_MASK
-+#define NL80211_WOWLAN_PKTPAT_PATTERN NL80211_PKTPAT_PATTERN
-+#define NL80211_WOWLAN_PKTPAT_OFFSET NL80211_PKTPAT_OFFSET
-+#define NUM_NL80211_WOWLAN_PKTPAT NUM_NL80211_PKTPAT
-+#define MAX_NL80211_WOWLAN_PKTPAT MAX_NL80211_PKTPAT
-+#define nl80211_wowlan_pattern_support nl80211_pattern_support
-+
- /**
-  * enum nl80211_wowlan_triggers - WoWLAN trigger definitions
-  * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes
-@@ -3127,7 +3136,7 @@ struct nl80211_wowlan_pattern_support {
-  *    pattern matching is done after the packet is converted to the MSDU.
-  *
-  *    In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute
-- *    carrying a &struct nl80211_wowlan_pattern_support.
-+ *    carrying a &struct nl80211_pattern_support.
-  *
-  *    When reporting wakeup. it is a u32 attribute containing the 0-based
-  *    index of the pattern that caused the wakeup, in the patterns passed
-@@ -3284,7 +3293,7 @@ struct nl80211_wowlan_tcp_data_token_fea
-  * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a
-  *    u32 attribute holding the maximum length
-  * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for
-- *    feature advertising. The mask works like @NL80211_WOWLAN_PKTPAT_MASK
-+ *    feature advertising. The mask works like @NL80211_PKTPAT_MASK
-  *    but on the TCP payload only.
-  * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes
-  * @MAX_NL80211_WOWLAN_TCP: highest attribute number
---- a/net/mac80211/mesh_ps.c
-+++ b/net/mac80211/mesh_ps.c
-@@ -229,6 +229,10 @@ void ieee80211_mps_sta_status_update(str
-       enum nl80211_mesh_power_mode pm;
-       bool do_buffer;
-+      /* For non-assoc STA, prevent buffering or frame transmission */
-+      if (sta->sta_state < IEEE80211_STA_ASSOC)
-+              return;
+-      if (tid) {
++      if (tid && ieee80211_is_data_present(hdr->frame_control)) {
+               fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
+               seqno = tid->seq_next;
+               hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
+@@ -2184,14 +2186,15 @@ int ath_tx_start(struct ieee80211_hw *hw
+               txq->stopped = true;
+       }
++      if (txctl->an && ieee80211_is_data_present(hdr->frame_control))
++              tid = ath_get_skb_tid(sc, txctl->an, skb);
 +
-       /*
-        * use peer-specific power mode if peering is established and the
-        * peer's power mode is known
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -441,10 +441,12 @@ static int nl80211_prepare_wdev_dump(str
-                       goto out_unlock;
-               }
-               *rdev = wiphy_to_dev((*wdev)->wiphy);
--              cb->args[0] = (*rdev)->wiphy_idx;
-+              /* 0 is the first index - add 1 to parse only once */
-+              cb->args[0] = (*rdev)->wiphy_idx + 1;
-               cb->args[1] = (*wdev)->identifier;
-       } else {
--              struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]);
-+              /* subtract the 1 again here */
-+              struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
-               struct wireless_dev *tmp;
-               if (!wiphy) {
-@@ -974,7 +976,7 @@ static int nl80211_send_wowlan(struct sk
-               return -ENOBUFS;
-       if (dev->wiphy.wowlan->n_patterns) {
--              struct nl80211_wowlan_pattern_support pat = {
-+              struct nl80211_pattern_support pat = {
-                       .max_patterns = dev->wiphy.wowlan->n_patterns,
-                       .min_pattern_len = dev->wiphy.wowlan->pattern_min_len,
-                       .max_pattern_len = dev->wiphy.wowlan->pattern_max_len,
-@@ -1568,8 +1570,10 @@ static int nl80211_dump_wiphy(struct sk_
-       rtnl_lock();
-       if (!state) {
-               state = kzalloc(sizeof(*state), GFP_KERNEL);
--              if (!state)
-+              if (!state) {
-+                      rtnl_unlock();
-                       return -ENOMEM;
-+              }
-               state->filter_wiphy = -1;
-               ret = nl80211_dump_wiphy_parse(skb, cb, state);
-               if (ret) {
-@@ -6615,12 +6619,14 @@ EXPORT_SYMBOL(cfg80211_testmode_alloc_ev
+       if (info->flags & IEEE80211_TX_CTL_PS_RESPONSE) {
+               ath_txq_unlock(sc, txq);
+               txq = sc->tx.uapsdq;
+               ath_txq_lock(sc, txq);
+       } else if (txctl->an &&
+                  ieee80211_is_data_present(hdr->frame_control)) {
+-              tid = ath_get_skb_tid(sc, txctl->an, skb);
+-
+               WARN_ON(tid->ac->txq != txctl->txq);
  
- void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
- {
-+      struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
-       void *hdr = ((void **)skb->cb)[1];
-       struct nlattr *data = ((void **)skb->cb)[2];
-       nla_nest_end(skb, data);
-       genlmsg_end(skb, hdr);
--      genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp);
-+      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0,
-+                              nl80211_testmode_mcgrp.id, gfp);
+               if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT)
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -943,6 +943,7 @@ static void ath9k_set_hw_capab(struct at
+       hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+       hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
+       hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
++      hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+       hw->queues = 4;
+       hw->max_rates = 4;
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1700,14 +1700,8 @@ void ieee80211_stop_queue_by_reason(stru
+ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue);
+ void ieee80211_add_pending_skb(struct ieee80211_local *local,
+                              struct sk_buff *skb);
+-void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
+-                                 struct sk_buff_head *skbs,
+-                                 void (*fn)(void *data), void *data);
+-static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local,
+-                                            struct sk_buff_head *skbs)
+-{
+-      ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL);
+-}
++void ieee80211_add_pending_skbs(struct ieee80211_local *local,
++                              struct sk_buff_head *skbs);
+ void ieee80211_flush_queues(struct ieee80211_local *local,
+                           struct ieee80211_sub_if_data *sdata);
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -91,7 +91,7 @@ static int sta_info_hash_del(struct ieee
+       return -ENOENT;
  }
- EXPORT_SYMBOL(cfg80211_testmode_event);
- #endif
-@@ -7593,12 +7599,11 @@ static int nl80211_send_wowlan_patterns(
-               if (!nl_pat)
-                       return -ENOBUFS;
-               pat_len = wowlan->patterns[i].pattern_len;
--              if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,
--                          DIV_ROUND_UP(pat_len, 8),
-+              if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8),
-                           wowlan->patterns[i].mask) ||
--                  nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,
--                          pat_len, wowlan->patterns[i].pattern) ||
--                  nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,
-+                  nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len,
-+                          wowlan->patterns[i].pattern) ||
-+                  nla_put_u32(msg, NL80211_PKTPAT_OFFSET,
-                               wowlan->patterns[i].pkt_offset))
-                       return -ENOBUFS;
-               nla_nest_end(msg, nl_pat);
-@@ -7939,7 +7944,7 @@ static int nl80211_set_wowlan(struct sk_
-               struct nlattr *pat;
-               int n_patterns = 0;
-               int rem, pat_len, mask_len, pkt_offset;
--              struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT];
-+              struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
-               nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
-                                   rem)
-@@ -7958,26 +7963,25 @@ static int nl80211_set_wowlan(struct sk_
-               nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN],
-                                   rem) {
--                      nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT,
--                                nla_data(pat), nla_len(pat), NULL);
-+                      nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat),
-+                                nla_len(pat), NULL);
-                       err = -EINVAL;
--                      if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] ||
--                          !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN])
-+                      if (!pat_tb[NL80211_PKTPAT_MASK] ||
-+                          !pat_tb[NL80211_PKTPAT_PATTERN])
-                               goto error;
--                      pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]);
-+                      pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]);
-                       mask_len = DIV_ROUND_UP(pat_len, 8);
--                      if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) !=
--                          mask_len)
-+                      if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len)
-                               goto error;
-                       if (pat_len > wowlan->pattern_max_len ||
-                           pat_len < wowlan->pattern_min_len)
-                               goto error;
--                      if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET])
-+                      if (!pat_tb[NL80211_PKTPAT_OFFSET])
-                               pkt_offset = 0;
-                       else
-                               pkt_offset = nla_get_u32(
--                                      pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]);
-+                                      pat_tb[NL80211_PKTPAT_OFFSET]);
-                       if (pkt_offset > wowlan->max_pkt_offset)
-                               goto error;
-                       new_triggers.patterns[i].pkt_offset = pkt_offset;
-@@ -7991,11 +7995,11 @@ static int nl80211_set_wowlan(struct sk_
-                       new_triggers.patterns[i].pattern =
-                               new_triggers.patterns[i].mask + mask_len;
-                       memcpy(new_triggers.patterns[i].mask,
--                             nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]),
-+                             nla_data(pat_tb[NL80211_PKTPAT_MASK]),
-                              mask_len);
-                       new_triggers.patterns[i].pattern_len = pat_len;
-                       memcpy(new_triggers.patterns[i].pattern,
--                             nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]),
-+                             nla_data(pat_tb[NL80211_PKTPAT_PATTERN]),
-                              pat_len);
-                       i++;
-               }
-@@ -10066,7 +10070,8 @@ void cfg80211_mgmt_tx_status(struct wire
  
-       genlmsg_end(msg, hdr);
+-static void cleanup_single_sta(struct sta_info *sta)
++static void __cleanup_single_sta(struct sta_info *sta)
+ {
+       int ac, i;
+       struct tid_ampdu_tx *tid_tx;
+@@ -99,7 +99,8 @@ static void cleanup_single_sta(struct st
+       struct ieee80211_local *local = sdata->local;
+       struct ps_data *ps;
  
--      genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
-+      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
-+                              nl80211_mlme_mcgrp.id, gfp);
-       return;
+-      if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
++      if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
++          test_sta_flag(sta, WLAN_STA_PS_DRIVER)) {
+               if (sta->sdata->vif.type == NL80211_IFTYPE_AP ||
+                   sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                       ps = &sdata->bss->ps;
+@@ -109,6 +110,7 @@ static void cleanup_single_sta(struct st
+                       return;
  
-  nla_put_failure:
---- a/net/wireless/reg.c
-+++ b/net/wireless/reg.c
-@@ -2247,10 +2247,13 @@ int reg_device_uevent(struct device *dev
+               clear_sta_flag(sta, WLAN_STA_PS_STA);
++              clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
  
- void wiphy_regulatory_register(struct wiphy *wiphy)
- {
-+      struct regulatory_request *lr;
-+
-       if (!reg_dev_ignore_cell_hint(wiphy))
-               reg_num_devs_support_basehint++;
+               atomic_dec(&ps->num_sta_ps);
+               sta_info_recalc_tim(sta);
+@@ -139,7 +141,14 @@ static void cleanup_single_sta(struct st
+               ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
+               kfree(tid_tx);
+       }
++}
  
--      wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
-+      lr = get_last_request();
-+      wiphy_update_regulatory(wiphy, lr->initiator);
++static void cleanup_single_sta(struct sta_info *sta)
++{
++      struct ieee80211_sub_if_data *sdata = sta->sdata;
++      struct ieee80211_local *local = sdata->local;
++
++      __cleanup_single_sta(sta);
+       sta_info_free(local, sta);
  }
  
- void wiphy_regulatory_deregister(struct wiphy *wiphy)
-@@ -2279,7 +2282,9 @@ void wiphy_regulatory_deregister(struct 
- static void reg_timeout_work(struct work_struct *work)
- {
-       REG_DBG_PRINT("Timeout while waiting for CRDA to reply, restoring regulatory settings\n");
-+      rtnl_lock();
-       restore_regulatory_settings(true);
-+      rtnl_unlock();
- }
+@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct i
+       rcu_read_unlock();
  
- int __init regulatory_init(void)
---- a/net/wireless/sme.c
-+++ b/net/wireless/sme.c
-@@ -34,8 +34,10 @@ struct cfg80211_conn {
-               CFG80211_CONN_SCAN_AGAIN,
-               CFG80211_CONN_AUTHENTICATE_NEXT,
-               CFG80211_CONN_AUTHENTICATING,
-+              CFG80211_CONN_AUTH_FAILED,
-               CFG80211_CONN_ASSOCIATE_NEXT,
-               CFG80211_CONN_ASSOCIATING,
-+              CFG80211_CONN_ASSOC_FAILED,
-               CFG80211_CONN_DEAUTH,
-               CFG80211_CONN_CONNECTED,
-       } state;
-@@ -164,6 +166,8 @@ static int cfg80211_conn_do_work(struct 
-                                         NULL, 0,
-                                         params->key, params->key_len,
-                                         params->key_idx, NULL, 0);
-+      case CFG80211_CONN_AUTH_FAILED:
-+              return -ENOTCONN;
-       case CFG80211_CONN_ASSOCIATE_NEXT:
-               BUG_ON(!rdev->ops->assoc);
-               wdev->conn->state = CFG80211_CONN_ASSOCIATING;
-@@ -188,10 +192,17 @@ static int cfg80211_conn_do_work(struct 
-                                            WLAN_REASON_DEAUTH_LEAVING,
-                                            false);
-               return err;
-+      case CFG80211_CONN_ASSOC_FAILED:
-+              cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
-+                                   NULL, 0,
-+                                   WLAN_REASON_DEAUTH_LEAVING, false);
-+              return -ENOTCONN;
-       case CFG80211_CONN_DEAUTH:
-               cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
-                                    NULL, 0,
-                                    WLAN_REASON_DEAUTH_LEAVING, false);
-+              /* free directly, disconnected event already sent */
-+              cfg80211_sme_free(wdev);
-               return 0;
-       default:
-               return 0;
-@@ -371,7 +382,7 @@ bool cfg80211_sme_rx_assoc_resp(struct w
-               return true;
+       spin_lock_init(&sta->lock);
++      spin_lock_init(&sta->ps_lock);
+       INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
+       INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
+       mutex_init(&sta->ampdu_mlme.mtx);
+@@ -487,21 +497,26 @@ static int sta_info_insert_finish(struct
+               goto out_err;
        }
  
--      wdev->conn->state = CFG80211_CONN_DEAUTH;
-+      wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
-       schedule_work(&rdev->conn_work);
-       return false;
- }
-@@ -383,7 +394,13 @@ void cfg80211_sme_deauth(struct wireless
+-      /* notify driver */
+-      err = sta_info_insert_drv_state(local, sdata, sta);
+-      if (err)
+-              goto out_err;
+-
+       local->num_sta++;
+       local->sta_generation++;
+       smp_mb();
  
- void cfg80211_sme_auth_timeout(struct wireless_dev *wdev)
- {
--      cfg80211_sme_free(wdev);
-+      struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
-+
-+      if (!wdev->conn)
-+              return;
++      /* simplify things and don't accept BA sessions yet */
++      set_sta_flag(sta, WLAN_STA_BLOCK_BA);
 +
-+      wdev->conn->state = CFG80211_CONN_AUTH_FAILED;
-+      schedule_work(&rdev->conn_work);
- }
+       /* make the station visible */
+       sta_info_hash_add(local, sta);
  
- void cfg80211_sme_disassoc(struct wireless_dev *wdev)
-@@ -399,7 +416,13 @@ void cfg80211_sme_disassoc(struct wirele
+       list_add_rcu(&sta->list, &local->sta_list);
  
- void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
- {
--      cfg80211_sme_disassoc(wdev);
-+      struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
-+
-+      if (!wdev->conn)
-+              return;
++      /* notify driver */
++      err = sta_info_insert_drv_state(local, sdata, sta);
++      if (err)
++              goto out_remove;
 +
-+      wdev->conn->state = CFG80211_CONN_ASSOC_FAILED;
-+      schedule_work(&rdev->conn_work);
- }
+       set_sta_flag(sta, WLAN_STA_INSERTED);
++      /* accept BA sessions now */
++      clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
  
- static int cfg80211_sme_connect(struct wireless_dev *wdev,
---- a/net/mac80211/rc80211_minstrel.c
-+++ b/net/mac80211/rc80211_minstrel.c
-@@ -290,7 +290,7 @@ minstrel_get_rate(void *priv, struct iee
-       struct minstrel_rate *msr, *mr;
-       unsigned int ndx;
-       bool mrr_capable;
--      bool prev_sample = mi->prev_sample;
-+      bool prev_sample;
-       int delta;
-       int sampling_ratio;
-@@ -314,6 +314,7 @@ minstrel_get_rate(void *priv, struct iee
-                       (mi->sample_count + mi->sample_deferred / 2);
-       /* delta < 0: no sampling required */
-+      prev_sample = mi->prev_sample;
-       mi->prev_sample = false;
-       if (delta < 0 || (!mrr_capable && prev_sample))
-               return;
---- a/drivers/net/wireless/rt2x00/rt2x00queue.c
-+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
-@@ -936,13 +936,8 @@ void rt2x00queue_index_inc(struct queue_
-       spin_unlock_irqrestore(&queue->index_lock, irqflags);
+       ieee80211_recalc_min_chandef(sdata);
+       ieee80211_sta_debugfs_add(sta);
+@@ -522,6 +537,12 @@ static int sta_info_insert_finish(struct
+               mesh_accept_plinks_update(sdata);
+       return 0;
++ out_remove:
++      sta_info_hash_del(local, sta);
++      list_del_rcu(&sta->list);
++      local->num_sta--;
++      synchronize_net();
++      __cleanup_single_sta(sta);
+  out_err:
+       mutex_unlock(&local->sta_mtx);
+       rcu_read_lock();
+@@ -1071,10 +1092,14 @@ struct ieee80211_sta *ieee80211_find_sta
  }
+ EXPORT_SYMBOL(ieee80211_find_sta);
  
--void rt2x00queue_pause_queue(struct data_queue *queue)
-+void rt2x00queue_pause_queue_nocheck(struct data_queue *queue)
+-static void clear_sta_ps_flags(void *_sta)
++/* powersave support code */
++void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
  {
--      if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
--          !test_bit(QUEUE_STARTED, &queue->flags) ||
--          test_and_set_bit(QUEUE_PAUSED, &queue->flags))
--              return;
+-      struct sta_info *sta = _sta;
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
++      struct ieee80211_local *local = sdata->local;
++      struct sk_buff_head pending;
++      int filtered = 0, buffered = 0, ac;
++      unsigned long flags;
+       struct ps_data *ps;
+       if (sdata->vif.type == NL80211_IFTYPE_AP ||
+@@ -1085,20 +1110,6 @@ static void clear_sta_ps_flags(void *_st
+       else
+               return;
+-      clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
+-      if (test_and_clear_sta_flag(sta, WLAN_STA_PS_STA))
+-              atomic_dec(&ps->num_sta_ps);
+-}
 -
-       switch (queue->qid) {
-       case QID_AC_VO:
-       case QID_AC_VI:
-@@ -958,6 +953,15 @@ void rt2x00queue_pause_queue(struct data
-               break;
+-/* powersave support code */
+-void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
+-{
+-      struct ieee80211_sub_if_data *sdata = sta->sdata;
+-      struct ieee80211_local *local = sdata->local;
+-      struct sk_buff_head pending;
+-      int filtered = 0, buffered = 0, ac;
+-      unsigned long flags;
+-
+       clear_sta_flag(sta, WLAN_STA_SP);
+       BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1);
+@@ -1109,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(str
+       skb_queue_head_init(&pending);
++      /* sync with ieee80211_tx_h_unicast_ps_buf */
++      spin_lock(&sta->ps_lock);
+       /* Send all buffered frames to the station */
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               int count = skb_queue_len(&pending), tmp;
+@@ -1127,7 +1140,12 @@ void ieee80211_sta_ps_deliver_wakeup(str
+               buffered += tmp - count;
        }
- }
-+void rt2x00queue_pause_queue(struct data_queue *queue)
-+{
-+      if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
-+          !test_bit(QUEUE_STARTED, &queue->flags) ||
-+          test_and_set_bit(QUEUE_PAUSED, &queue->flags))
-+              return;
+-      ieee80211_add_pending_skbs_fn(local, &pending, clear_sta_ps_flags, sta);
++      ieee80211_add_pending_skbs(local, &pending);
++      clear_sta_flag(sta, WLAN_STA_PS_DRIVER);
++      clear_sta_flag(sta, WLAN_STA_PS_STA);
++      spin_unlock(&sta->ps_lock);
 +
-+      rt2x00queue_pause_queue_nocheck(queue);
-+}
- EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue);
++      atomic_dec(&ps->num_sta_ps);
  
- void rt2x00queue_unpause_queue(struct data_queue *queue)
-@@ -1019,7 +1023,7 @@ void rt2x00queue_stop_queue(struct data_
-               return;
+       /* This station just woke up and isn't aware of our SMPS state */
+       if (!ieee80211_smps_is_restrictive(sta->known_smps_mode,
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -267,6 +267,7 @@ struct ieee80211_tx_latency_stat {
+  * @drv_unblock_wk: used for driver PS unblocking
+  * @listen_interval: listen interval of this station, when we're acting as AP
+  * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly
++ * @ps_lock: used for powersave (when mac80211 is the AP) related locking
+  * @ps_tx_buf: buffers (per AC) of frames to transmit to this station
+  *    when it leaves power saving state or polls
+  * @tx_filtered: buffers (per AC) of frames we already tried to
+@@ -356,10 +357,8 @@ struct sta_info {
+       /* use the accessors defined below */
+       unsigned long _flags;
+-      /*
+-       * STA powersave frame queues, no more than the internal
+-       * locking required.
+-       */
++      /* STA powersave lock and frame queues */
++      spinlock_t ps_lock;
+       struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS];
+       struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS];
+       unsigned long driver_buffered_tids;
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -435,9 +435,8 @@ void ieee80211_add_pending_skb(struct ie
+       spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+ }
+-void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
+-                                 struct sk_buff_head *skbs,
+-                                 void (*fn)(void *data), void *data)
++void ieee80211_add_pending_skbs(struct ieee80211_local *local,
++                              struct sk_buff_head *skbs)
+ {
+       struct ieee80211_hw *hw = &local->hw;
+       struct sk_buff *skb;
+@@ -461,9 +460,6 @@ void ieee80211_add_pending_skbs_fn(struc
+               __skb_queue_tail(&local->pending[queue], skb);
        }
  
--      rt2x00queue_pause_queue(queue);
-+      rt2x00queue_pause_queue_nocheck(queue);
+-      if (fn)
+-              fn(data);
+-
+       for (i = 0; i < hw->queues; i++)
+               __ieee80211_wake_queue(hw, i,
+                       IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regu
+               return;
+       case NL80211_REGDOM_SET_BY_USER:
+               treatment = reg_process_hint_user(reg_request);
+-              if (treatment == REG_REQ_OK ||
++              if (treatment == REG_REQ_IGNORE ||
+                   treatment == REG_REQ_ALREADY_SET)
+                       return;
+               schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -138,43 +138,41 @@ static ssize_t read_file_ani(struct file
+       unsigned int len = 0, size = 1024;
+       ssize_t retval = 0;
+       char *buf;
++      int i;
++      struct {
++              const char *name;
++              unsigned int val;
++      } ani_info[] = {
++              { "ANI RESET", ah->stats.ast_ani_reset },
++              { "OFDM LEVEL", ah->ani.ofdmNoiseImmunityLevel },
++              { "CCK LEVEL", ah->ani.cckNoiseImmunityLevel },
++              { "SPUR UP", ah->stats.ast_ani_spurup },
++              { "SPUR DOWN", ah->stats.ast_ani_spurup },
++              { "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon },
++              { "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff },
++              { "MRC-CCK ON", ah->stats.ast_ani_ccklow },
++              { "MRC-CCK OFF", ah->stats.ast_ani_cckhigh },
++              { "FIR-STEP UP", ah->stats.ast_ani_stepup },
++              { "FIR-STEP DOWN", ah->stats.ast_ani_stepdown },
++              { "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero },
++              { "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs },
++              { "CCK ERRORS", ah->stats.ast_ani_cckerrs },
++      };
  
-       queue->rt2x00dev->ops->lib->stop_queue(queue);
+       buf = kzalloc(size, GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+-      if (common->disable_ani) {
+-              len += scnprintf(buf + len, size - len, "%s: %s\n",
+-                               "ANI", "DISABLED");
++      len += scnprintf(buf + len, size - len, "%15s: %s\n", "ANI",
++                       common->disable_ani ? "DISABLED" : "ENABLED");
++
++      if (common->disable_ani)
+               goto exit;
+-      }
+-      len += scnprintf(buf + len, size - len, "%15s: %s\n",
+-                       "ANI", "ENABLED");
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "ANI RESET", ah->stats.ast_ani_reset);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "SPUR UP", ah->stats.ast_ani_spurup);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "SPUR DOWN", ah->stats.ast_ani_spurup);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "OFDM WS-DET ON", ah->stats.ast_ani_ofdmon);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "OFDM WS-DET OFF", ah->stats.ast_ani_ofdmoff);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "MRC-CCK ON", ah->stats.ast_ani_ccklow);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "MRC-CCK OFF", ah->stats.ast_ani_cckhigh);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "FIR-STEP UP", ah->stats.ast_ani_stepup);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "FIR-STEP DOWN", ah->stats.ast_ani_stepdown);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "INV LISTENTIME", ah->stats.ast_ani_lneg_or_lzero);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "OFDM ERRORS", ah->stats.ast_ani_ofdmerrs);
+-      len += scnprintf(buf + len, size - len, "%15s: %u\n",
+-                       "CCK ERRORS", ah->stats.ast_ani_cckerrs);
++      for (i = 0; i < ARRAY_SIZE(ani_info); i++)
++              len += scnprintf(buf + len, size - len, "%15s: %u\n",
++                               ani_info[i].name, ani_info[i].val);
++
+ exit:
+       if (len > size)
+               len = size;
+@@ -866,6 +864,12 @@ static ssize_t read_file_reset(struct fi
+                        "%17s: %2d\n", "PLL RX Hang",
+                        sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
+       len += scnprintf(buf + len, sizeof(buf) - len,
++                       "%17s: %2d\n", "MAC Hang",
++                       sc->debug.stats.reset[RESET_TYPE_MAC_HANG]);
++      len += scnprintf(buf + len, sizeof(buf) - len,
++                       "%17s: %2d\n", "Stuck Beacon",
++                       sc->debug.stats.reset[RESET_TYPE_BEACON_STUCK]);
++      len += scnprintf(buf + len, sizeof(buf) - len,
+                        "%17s: %2d\n", "MCI Reset",
+                        sc->debug.stats.reset[RESET_TYPE_MCI]);
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -868,10 +868,6 @@ static void ar9003_hw_set_rfmode(struct 
+       if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+               rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
+-      if (IS_CHAN_QUARTER_RATE(chan))
+-              rfMode |= AR_PHY_MODE_QUARTER;
+-      if (IS_CHAN_HALF_RATE(chan))
+-              rfMode |= AR_PHY_MODE_HALF;
+       if (rfMode & (AR_PHY_MODE_QUARTER | AR_PHY_MODE_HALF))
+               REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL,
+--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+@@ -706,6 +706,7 @@ ath5k_get_survey(struct ieee80211_hw *hw
+       survey->channel = conf->chandef.chan;
+       survey->noise = ah->ah_noise_floor;
+       survey->filled = SURVEY_INFO_NOISE_DBM |
++                      SURVEY_INFO_IN_USE |
+                       SURVEY_INFO_CHANNEL_TIME |
+                       SURVEY_INFO_CHANNEL_TIME_BUSY |
+                       SURVEY_INFO_CHANNEL_TIME_RX |
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -732,11 +732,18 @@ static struct ath_rxbuf *ath_get_next_rx
+                       return NULL;
  
---- a/net/mac80211/mlme.c
-+++ b/net/mac80211/mlme.c
-@@ -31,10 +31,12 @@
- #include "led.h"
- #define IEEE80211_AUTH_TIMEOUT                (HZ / 5)
-+#define IEEE80211_AUTH_TIMEOUT_LONG   (HZ / 2)
- #define IEEE80211_AUTH_TIMEOUT_SHORT  (HZ / 10)
- #define IEEE80211_AUTH_MAX_TRIES      3
- #define IEEE80211_AUTH_WAIT_ASSOC     (HZ * 5)
- #define IEEE80211_ASSOC_TIMEOUT               (HZ / 5)
-+#define IEEE80211_ASSOC_TIMEOUT_LONG  (HZ / 2)
- #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10)
- #define IEEE80211_ASSOC_MAX_TRIES     3
-@@ -209,8 +211,9 @@ ieee80211_determine_chantype(struct ieee
-                            struct ieee80211_channel *channel,
-                            const struct ieee80211_ht_operation *ht_oper,
-                            const struct ieee80211_vht_operation *vht_oper,
--                           struct cfg80211_chan_def *chandef, bool verbose)
-+                           struct cfg80211_chan_def *chandef, bool tracking)
- {
-+      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-       struct cfg80211_chan_def vht_chandef;
-       u32 ht_cfreq, ret;
-@@ -229,7 +232,7 @@ ieee80211_determine_chantype(struct ieee
-       ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
-                                                 channel->band);
-       /* check that channel matches the right operating channel */
--      if (channel->center_freq != ht_cfreq) {
-+      if (!tracking && channel->center_freq != ht_cfreq) {
                /*
-                * It's possible that some APs are confused here;
-                * Netgear WNDR3700 sometimes reports 4 higher than
-@@ -237,11 +240,10 @@ ieee80211_determine_chantype(struct ieee
-                * since we look at probe response/beacon data here
-                * it should be OK.
+-               * mark descriptor as zero-length and set the 'more'
+-               * flag to ensure that both buffers get discarded
++               * Re-check previous descriptor, in case it has been filled
++               * in the mean time.
                 */
--              if (verbose)
--                      sdata_info(sdata,
--                                 "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
--                                 channel->center_freq, ht_cfreq,
--                                 ht_oper->primary_chan, channel->band);
-+              sdata_info(sdata,
-+                         "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
-+                         channel->center_freq, ht_cfreq,
-+                         ht_oper->primary_chan, channel->band);
-               ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
-               goto out;
-       }
-@@ -295,7 +297,7 @@ ieee80211_determine_chantype(struct ieee
-                               channel->band);
-               break;
-       default:
--              if (verbose)
-+              if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
-                       sdata_info(sdata,
-                                  "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
-                                  vht_oper->chan_width);
-@@ -304,7 +306,7 @@ ieee80211_determine_chantype(struct ieee
+-              rs->rs_datalen = 0;
+-              rs->rs_more = true;
++              ret = ath9k_hw_rxprocdesc(ah, ds, rs);
++              if (ret == -EINPROGRESS) {
++                      /*
++                       * mark descriptor as zero-length and set the 'more'
++                       * flag to ensure that both buffers get discarded
++                       */
++                      rs->rs_datalen = 0;
++                      rs->rs_more = true;
++              }
        }
  
-       if (!cfg80211_chandef_valid(&vht_chandef)) {
--              if (verbose)
-+              if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
-                       sdata_info(sdata,
-                                  "AP VHT information is invalid, disable VHT\n");
-               ret = IEEE80211_STA_DISABLE_VHT;
-@@ -317,7 +319,7 @@ ieee80211_determine_chantype(struct ieee
-       }
+       list_del(&bf->list);
+@@ -985,32 +992,32 @@ static int ath9k_rx_skb_preprocess(struc
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_hdr *hdr;
+       bool discard_current = sc->rx.discard_next;
+-      int ret = 0;
+       /*
+        * Discard corrupt descriptors which are marked in
+        * ath_get_next_rx_buf().
+        */
+-      sc->rx.discard_next = rx_stats->rs_more;
+       if (discard_current)
+-              return -EINVAL;
++              goto corrupt;
++
++      sc->rx.discard_next = false;
  
-       if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
--              if (verbose)
-+              if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
-                       sdata_info(sdata,
-                                  "AP VHT information doesn't match HT, disable VHT\n");
-               ret = IEEE80211_STA_DISABLE_VHT;
-@@ -333,18 +335,27 @@ out:
-       if (ret & IEEE80211_STA_DISABLE_VHT)
-               vht_chandef = *chandef;
+       /*
+        * Discard zero-length packets.
+        */
+       if (!rx_stats->rs_datalen) {
+               RX_STAT_INC(rx_len_err);
+-              return -EINVAL;
++              goto corrupt;
+       }
  
+-        /*
+-         * rs_status follows rs_datalen so if rs_datalen is too large
+-         * we can take a hint that hardware corrupted it, so ignore
+-         * those frames.
+-         */
 +      /*
-+       * Ignore the DISABLED flag when we're already connected and only
-+       * tracking the APs beacon for bandwidth changes - otherwise we
-+       * might get disconnected here if we connect to an AP, update our
-+       * regulatory information based on the AP's country IE and the
-+       * information we have is wrong/outdated and disables the channel
-+       * that we're actually using for the connection to the AP.
++       * rs_status follows rs_datalen so if rs_datalen is too large
++       * we can take a hint that hardware corrupted it, so ignore
++       * those frames.
 +       */
-       while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
--                                      IEEE80211_CHAN_DISABLED)) {
-+                                      tracking ? 0 :
-+                                                 IEEE80211_CHAN_DISABLED)) {
-               if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
-                       ret = IEEE80211_STA_DISABLE_HT |
-                             IEEE80211_STA_DISABLE_VHT;
--                      goto out;
-+                      break;
-               }
-               ret |= chandef_downgrade(chandef);
+       if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) {
+               RX_STAT_INC(rx_len_err);
+-              return -EINVAL;
++              goto corrupt;
        }
  
--      if (chandef->width != vht_chandef.width && verbose)
-+      if (chandef->width != vht_chandef.width && !tracking)
-               sdata_info(sdata,
-                          "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
-@@ -384,7 +395,7 @@ static int ieee80211_config_bw(struct ie
+       /* Only use status info from the last fragment */
+@@ -1024,10 +1031,8 @@ static int ath9k_rx_skb_preprocess(struc
+        * This is different from the other corrupt descriptor
+        * condition handled above.
+        */
+-      if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC) {
+-              ret = -EINVAL;
+-              goto exit;
+-      }
++      if (rx_stats->rs_status & ATH9K_RXERR_CORRUPT_DESC)
++              goto corrupt;
  
-       /* calculate new channel (type) based on HT/VHT operation IEs */
-       flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
--                                           vht_oper, &chandef, false);
-+                                           vht_oper, &chandef, true);
+       hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len);
  
-       /*
-        * Downgrade the new channel if we associated with restricted
-@@ -3394,10 +3405,13 @@ static int ieee80211_probe_auth(struct i
-       if (tx_flags == 0) {
-               auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
--              ifmgd->auth_data->timeout_started = true;
-+              auth_data->timeout_started = true;
-               run_again(sdata, auth_data->timeout);
-       } else {
--              auth_data->timeout_started = false;
-+              auth_data->timeout =
-+                      round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
-+              auth_data->timeout_started = true;
-+              run_again(sdata, auth_data->timeout);
-       }
+@@ -1043,18 +1048,15 @@ static int ath9k_rx_skb_preprocess(struc
+               if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
+                       RX_STAT_INC(rx_spectral);
  
-       return 0;
-@@ -3434,7 +3448,11 @@ static int ieee80211_do_assoc(struct iee
-               assoc_data->timeout_started = true;
-               run_again(sdata, assoc_data->timeout);
-       } else {
--              assoc_data->timeout_started = false;
-+              assoc_data->timeout =
-+                      round_jiffies_up(jiffies +
-+                                       IEEE80211_ASSOC_TIMEOUT_LONG);
-+              assoc_data->timeout_started = true;
-+              run_again(sdata, assoc_data->timeout);
+-              ret = -EINVAL;
+-              goto exit;
++              return -EINVAL;
        }
  
-       return 0;
-@@ -3829,7 +3847,7 @@ static int ieee80211_prep_channel(struct
-       ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
-                                                    cbss->channel,
-                                                    ht_oper, vht_oper,
--                                                   &chandef, true);
-+                                                   &chandef, false);
-       sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
-                                     local->rx_chains);
---- a/net/wireless/core.c
-+++ b/net/wireless/core.c
-@@ -772,6 +772,7 @@ void cfg80211_leave(struct cfg80211_regi
-               cfg80211_leave_mesh(rdev, dev);
-               break;
-       case NL80211_IFTYPE_AP:
-+      case NL80211_IFTYPE_P2P_GO:
-               cfg80211_stop_ap(rdev, dev);
-               break;
-       default:
---- a/drivers/net/wireless/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -5404,19 +5404,20 @@ int rt2800_enable_radio(struct rt2x00_de
-                    rt2800_init_registers(rt2x00dev)))
-               return -EIO;
+       /*
+        * everything but the rate is checked here, the rate check is done
+        * separately to avoid doing two lookups for a rate for each frame.
+        */
+-      if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) {
+-              ret = -EINVAL;
+-              goto exit;
+-      }
++      if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
++              return -EINVAL;
  
-+      if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev)))
-+              return -EIO;
-+
+       if (ath_is_mybeacon(common, hdr)) {
+               RX_STAT_INC(rx_beacons);
+@@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struc
        /*
-        * Send signal to firmware during boot time.
+        * This shouldn't happen, but have a safety check anyway.
         */
-       rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
-       rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
--      if (rt2x00_is_usb(rt2x00dev)) {
-+      if (rt2x00_is_usb(rt2x00dev))
-               rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);
--              rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
+-      if (WARN_ON(!ah->curchan)) {
+-              ret = -EINVAL;
+-              goto exit;
 -      }
-+      rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0);
-       msleep(1);
++      if (WARN_ON(!ah->curchan))
++              return -EINVAL;
  
--      if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) ||
--                   rt2800_wait_bbp_ready(rt2x00dev)))
-+      if (unlikely(rt2800_wait_bbp_ready(rt2x00dev)))
-               return -EIO;
+-      if (ath9k_process_rate(common, hw, rx_stats, rx_status)) {
+-              ret =-EINVAL;
+-              goto exit;
+-      }
++      if (ath9k_process_rate(common, hw, rx_stats, rx_status))
++              return -EINVAL;
  
-       rt2800_init_bbp(rt2x00dev);
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -101,7 +101,7 @@ static u32 ieee80211_hw_conf_chan(struct
-       struct ieee80211_sub_if_data *sdata;
-       struct cfg80211_chan_def chandef = {};
-       u32 changed = 0;
--      int power;
-+      int power = 0;
-       u32 offchannel_flag;
-       offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
-@@ -155,16 +155,16 @@ static u32 ieee80211_hw_conf_chan(struct
-               changed |= IEEE80211_CONF_CHANGE_SMPS;
-       }
+       ath9k_process_rssi(common, hw, rx_stats, rx_status);
  
--      power = chandef.chan->max_power;
--
-       rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-               if (!rcu_access_pointer(sdata->vif.chanctx_conf))
-                       continue;
--              power = min(power, sdata->vif.bss_conf.txpower);
-+              power = max(power, sdata->vif.bss_conf.txpower);
-       }
-       rcu_read_unlock();
+@@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struc
+               sc->rx.num_pkts++;
+ #endif
  
-+      power = min(power, chandef.chan->max_power);
+-exit:
+-      sc->rx.discard_next = false;
+-      return ret;
++      return 0;
 +
-       if (local->hw.conf.power_level != power) {
-               changed |= IEEE80211_CONF_CHANGE_POWER;
-               local->hw.conf.power_level = power;
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -3332,7 +3332,7 @@ static int ieee80211_probe_client(struct
-               return -EINVAL;
-       }
-       band = chanctx_conf->def.chan->band;
--      sta = sta_info_get(sdata, peer);
-+      sta = sta_info_get_bss(sdata, peer);
-       if (sta) {
-               qos = test_sta_flag(sta, WLAN_STA_WME);
-       } else {
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -180,6 +180,9 @@ static void ieee80211_frame_acked(struct
-       struct ieee80211_local *local = sta->local;
-       struct ieee80211_sub_if_data *sdata = sta->sdata;
++corrupt:
++      sc->rx.discard_next = rx_stats->rs_more;
++      return -EINVAL;
+ }
  
-+      if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
-+              sta->last_rx = jiffies;
+ static void ath9k_rx_skb_postprocess(struct ath_common *common,
+--- a/drivers/net/wireless/ath/ath9k/ani.c
++++ b/drivers/net/wireless/ath/ath9k/ani.c
+@@ -176,16 +176,26 @@ static void ath9k_hw_set_ofdm_nil(struct
+       if (ah->opmode == NL80211_IFTYPE_STATION &&
+           BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH)
+               weak_sig = true;
+-
+       /*
+-       * OFDM Weak signal detection is always enabled for AP mode.
++       * Newer chipsets are better at dealing with high PHY error counts -
++       * keep weak signal detection enabled when no RSSI threshold is
++       * available to determine if it is needed (mode != STA)
+        */
+-      if (ah->opmode != NL80211_IFTYPE_AP &&
+-          aniState->ofdmWeakSigDetect != weak_sig) {
+-              ath9k_hw_ani_control(ah,
+-                                   ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+-                                   entry_ofdm->ofdm_weak_signal_on);
+-      }
++      else if (AR_SREV_9300_20_OR_LATER(ah) &&
++               ah->opmode != NL80211_IFTYPE_STATION)
++              weak_sig = true;
 +
-       if (ieee80211_is_data_qos(mgmt->frame_control)) {
-               struct ieee80211_hdr *hdr = (void *) skb->data;
-               u8 *qc = ieee80211_get_qos_ctl(hdr);
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -1101,7 +1101,8 @@ ieee80211_tx_prepare(struct ieee80211_su
-               tx->sta = rcu_dereference(sdata->u.vlan.sta);
-               if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
-                       return TX_DROP;
--      } else if (info->flags & IEEE80211_TX_CTL_INJECTED ||
-+      } else if (info->flags & (IEEE80211_TX_CTL_INJECTED |
-+                                IEEE80211_TX_INTFL_NL80211_FRAME_TX) ||
-                  tx->sdata->control_port_protocol == tx->skb->protocol) {
-               tx->sta = sta_info_get_bss(sdata, hdr->addr1);
-       }
---- a/drivers/net/wireless/ath/ath5k/base.c
-+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1628,15 +1628,15 @@ ath5k_tx_frame_completed(struct ath5k_hw
-       ah->stats.tx_bytes_count += skb->len;
-       info = IEEE80211_SKB_CB(skb);
-+      size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates));
-+      memcpy(info->status.rates, bf->rates, size);
++      /* Older chipsets are more sensitive to high PHY error counts */
++      else if (!AR_SREV_9300_20_OR_LATER(ah) &&
++               aniState->ofdmNoiseImmunityLevel >= 8)
++              weak_sig = false;
 +
-       tries[0] = info->status.rates[0].count;
-       tries[1] = info->status.rates[1].count;
-       tries[2] = info->status.rates[2].count;
++      if (aniState->ofdmWeakSigDetect != weak_sig)
++              ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
++                                   weak_sig);
++
++      if (!AR_SREV_9300_20_OR_LATER(ah))
++              return;
  
-       ieee80211_tx_info_clear_status(info);
+       if (aniState->ofdmNoiseImmunityLevel >= ATH9K_ANI_OFDM_DEF_LEVEL) {
+               ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
+@@ -308,17 +318,6 @@ void ath9k_ani_reset(struct ath_hw *ah, 
+       BUG_ON(aniState == NULL);
+       ah->stats.ast_ani_reset++;
  
--      size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates));
--      memcpy(info->status.rates, bf->rates, size);
+-      /* only allow a subset of functions in AP mode */
+-      if (ah->opmode == NL80211_IFTYPE_AP) {
+-              if (IS_CHAN_2GHZ(chan)) {
+-                      ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL |
+-                                          ATH9K_ANI_FIRSTEP_LEVEL);
+-                      if (AR_SREV_9300_20_OR_LATER(ah))
+-                              ah->ani_function |= ATH9K_ANI_MRC_CCK;
+-              } else
+-                      ah->ani_function = 0;
+-      }
 -
-       for (i = 0; i < ts->ts_final_idx; i++) {
-               struct ieee80211_tx_rate *r =
-                       &info->status.rates[i];
---- a/drivers/net/wireless/rt2x00/rt2800usb.c
-+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
-@@ -176,8 +176,8 @@ static bool rt2800usb_tx_sta_fifo_read_c
-               queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
-       if (rt2800usb_txstatus_pending(rt2x00dev)) {
--              /* Read register after 250 us */
--              hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000),
-+              /* Read register after 1 ms */
-+              hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 1000000),
-                             HRTIMER_MODE_REL);
-               return false;
-       }
-@@ -202,8 +202,8 @@ static void rt2800usb_async_read_tx_stat
-       if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
-               return;
+       ofdm_nil = max_t(int, ATH9K_ANI_OFDM_DEF_LEVEL,
+                        aniState->ofdmNoiseImmunityLevel);
+       cck_nil = max_t(int, ATH9K_ANI_CCK_DEF_LEVEL,
+@@ -483,10 +482,17 @@ void ath9k_hw_ani_init(struct ath_hw *ah
  
--      /* Read TX_STA_FIFO register after 500 us */
--      hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 500000),
-+      /* Read TX_STA_FIFO register after 2 ms */
-+      hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 2000000),
-                     HRTIMER_MODE_REL);
- }
+       ath_dbg(common, ANI, "Initialize ANI\n");
+-      ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
+-      ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
+-      ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
+-      ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
++      if (AR_SREV_9300_20_OR_LATER(ah)) {
++              ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH;
++              ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW;
++              ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH;
++              ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW;
++      } else {
++              ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD;
++              ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD;
++              ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD;
++              ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD;
++      }
+       ani->spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+       ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+--- a/drivers/net/wireless/ath/ath9k/ani.h
++++ b/drivers/net/wireless/ath/ath9k/ani.h
+@@ -22,12 +22,16 @@
+ /* units are errors per second */
+ #define ATH9K_ANI_OFDM_TRIG_HIGH           3500
+ #define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000
++#define ATH9K_ANI_OFDM_TRIG_HIGH_OLD       500
+ #define ATH9K_ANI_OFDM_TRIG_LOW           400
+ #define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900
++#define ATH9K_ANI_OFDM_TRIG_LOW_OLD       200
+ #define ATH9K_ANI_CCK_TRIG_HIGH           600
++#define ATH9K_ANI_CCK_TRIG_HIGH_OLD       200
+ #define ATH9K_ANI_CCK_TRIG_LOW            300
++#define ATH9K_ANI_CCK_TRIG_LOW_OLD        100
+ #define ATH9K_ANI_SPUR_IMMUNE_LVL         3
+ #define ATH9K_ANI_FIRSTEP_LVL             2
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -26,10 +26,6 @@ static const int firstep_table[] =
+ /* level:  0   1   2   3   4   5   6   7   8  */
+       { -4, -2,  0,  2,  4,  6,  8, 10, 12 }; /* lvl 0-8, default 2 */
+-static const int cycpwrThr1_table[] =
+-/* level:  0   1   2   3   4   5   6   7   8  */
+-      { -6, -4, -2,  0,  2,  4,  6,  8 };     /* lvl 0-7, default 3 */
+-
+ /*
+  * register values to turn OFDM weak signal detection OFF
+  */
+@@ -921,7 +917,7 @@ static bool ar5008_hw_ani_control_new(st
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_channel *chan = ah->curchan;
+       struct ar5416AniState *aniState = &ah->ani;
+-      s32 value, value2;
++      s32 value;
+       switch (cmd & ah->ani_function) {
+       case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+@@ -1008,42 +1004,11 @@ static bool ar5008_hw_ani_control_new(st
+       case ATH9K_ANI_FIRSTEP_LEVEL:{
+               u32 level = param;
+-              if (level >= ARRAY_SIZE(firstep_table)) {
+-                      ath_dbg(common, ANI,
+-                              "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n",
+-                              level, ARRAY_SIZE(firstep_table));
+-                      return false;
+-              }
+-
+-              /*
+-               * make register setting relative to default
+-               * from INI file & cap value
+-               */
+-              value = firstep_table[level] -
+-                      firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
+-                      aniState->iniDef.firstep;
+-              if (value < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+-                      value = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+-              if (value > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+-                      value = ATH9K_SIG_FIRSTEP_SETTING_MAX;
++              value = level * 2;
+               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+-                            AR_PHY_FIND_SIG_FIRSTEP,
+-                            value);
+-              /*
+-               * we need to set first step low register too
+-               * make register setting relative to default
+-               * from INI file & cap value
+-               */
+-              value2 = firstep_table[level] -
+-                       firstep_table[ATH9K_ANI_FIRSTEP_LVL] +
+-                       aniState->iniDef.firstepLow;
+-              if (value2 < ATH9K_SIG_FIRSTEP_SETTING_MIN)
+-                      value2 = ATH9K_SIG_FIRSTEP_SETTING_MIN;
+-              if (value2 > ATH9K_SIG_FIRSTEP_SETTING_MAX)
+-                      value2 = ATH9K_SIG_FIRSTEP_SETTING_MAX;
+-
++                            AR_PHY_FIND_SIG_FIRSTEP, value);
+               REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
+-                            AR_PHY_FIND_SIG_FIRSTEP_LOW, value2);
++                            AR_PHY_FIND_SIG_FIRSTEP_LOW, value);
+               if (level != aniState->firstepLevel) {
+                       ath_dbg(common, ANI,
+@@ -1060,7 +1025,7 @@ static bool ar5008_hw_ani_control_new(st
+                               aniState->firstepLevel,
+                               level,
+                               ATH9K_ANI_FIRSTEP_LVL,
+-                              value2,
++                              value,
+                               aniState->iniDef.firstepLow);
+                       if (level > aniState->firstepLevel)
+                               ah->stats.ast_ani_stepup++;
+@@ -1073,41 +1038,13 @@ static bool ar5008_hw_ani_control_new(st
+       case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+               u32 level = param;
+-              if (level >= ARRAY_SIZE(cycpwrThr1_table)) {
+-                      ath_dbg(common, ANI,
+-                              "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n",
+-                              level, ARRAY_SIZE(cycpwrThr1_table));
+-                      return false;
+-              }
+-              /*
+-               * make register setting relative to default
+-               * from INI file & cap value
+-               */
+-              value = cycpwrThr1_table[level] -
+-                      cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
+-                      aniState->iniDef.cycpwrThr1;
+-              if (value < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+-                      value = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+-              if (value > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+-                      value = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
++              value = (level + 1) * 2;
+               REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+-                            AR_PHY_TIMING5_CYCPWR_THR1,
+-                            value);
++                            AR_PHY_TIMING5_CYCPWR_THR1, value);
+-              /*
+-               * set AR_PHY_EXT_CCA for extension channel
+-               * make register setting relative to default
+-               * from INI file & cap value
+-               */
+-              value2 = cycpwrThr1_table[level] -
+-                       cycpwrThr1_table[ATH9K_ANI_SPUR_IMMUNE_LVL] +
+-                       aniState->iniDef.cycpwrThr1Ext;
+-              if (value2 < ATH9K_SIG_SPUR_IMM_SETTING_MIN)
+-                      value2 = ATH9K_SIG_SPUR_IMM_SETTING_MIN;
+-              if (value2 > ATH9K_SIG_SPUR_IMM_SETTING_MAX)
+-                      value2 = ATH9K_SIG_SPUR_IMM_SETTING_MAX;
+-              REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+-                            AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2);
++              if (IS_CHAN_HT40(ah->curchan))
++                      REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
++                                    AR_PHY_EXT_TIMING5_CYCPWR_THR1, value);
  
+               if (level != aniState->spurImmunityLevel) {
+                       ath_dbg(common, ANI,
+@@ -1124,7 +1061,7 @@ static bool ar5008_hw_ani_control_new(st
+                               aniState->spurImmunityLevel,
+                               level,
+                               ATH9K_ANI_SPUR_IMMUNE_LVL,
+-                              value2,
++                              value,
+                               aniState->iniDef.cycpwrThr1Ext);
+                       if (level > aniState->spurImmunityLevel)
+                               ah->stats.ast_ani_spurup++;
index d7479f296563f9ffdc6ad53013c2d7fdad0633ad..389a00370d6e5b1363f201676c8b1a0753ef2748 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -2092,7 +2092,7 @@ static int ieee80211_scan(struct wiphy *
+@@ -2148,7 +2148,7 @@ static int ieee80211_scan(struct wiphy *
                 * the  frames sent while scanning on other channel will be
                 * lost)
                 */
index aa5ce94d1edd48125717a30f06e6f6859cac128d..0dba7ac12555b4de8b0959925b39f951a88d7ecb 100644 (file)
@@ -1,18 +1,18 @@
 --- a/drivers/net/wireless/ath/Makefile
 +++ b/drivers/net/wireless/ath/Makefile
-@@ -11,7 +11,7 @@ obj-$(CPTCFG_ATH_COMMON)     += ath.o
- ath-objs :=   main.o \
+@@ -13,8 +13,8 @@ ath-objs :=  main.o \
                regd.o \
                hw.o \
--              key.o
-+              key.o \
-+              debug.o
+               key.o \
++              debug.o \
+               dfs_pattern_detector.o \
+               dfs_pri_detector.o
  
 -ath-$(CPTCFG_ATH_DEBUG) += debug.o
  ccflags-y += -D__CHECK_ENDIAN__
 --- a/drivers/net/wireless/ath/ath.h
 +++ b/drivers/net/wireless/ath/ath.h
-@@ -280,13 +280,6 @@ void _ath_dbg(struct ath_common *common,
+@@ -282,13 +282,6 @@ void _ath_dbg(struct ath_common *common,
  #endif /* CPTCFG_ATH_DEBUG */
  
  /** Returns string describing opmode, or NULL if unknown mode. */
index b2a70733073afd52218ed62a502cc418928f2080..63ab0dba6ed39a60b55edf6ca06bc50f81d1b422 100644 (file)
@@ -1,14 +1,14 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -17,6 +17,7 @@
- #include <linux/io.h>
- #include <linux/slab.h>
+@@ -19,6 +19,7 @@
  #include <linux/module.h>
+ #include <linux/time.h>
+ #include <linux/bitops.h>
 +#include <linux/etherdevice.h>
  #include <asm/unaligned.h>
  
  #include "hw.h"
-@@ -518,8 +519,16 @@ static int ath9k_hw_init_macaddr(struct 
+@@ -449,8 +450,16 @@ static int ath9k_hw_init_macaddr(struct 
                common->macaddr[2 * i] = eeval >> 8;
                common->macaddr[2 * i + 1] = eeval & 0xff;
        }
index 303c4d7792dd5cd2dfd99a3d9414bf03f439a000..07c54ccf819eb6629b0e0fe22e632a73b1b4d9aa 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/regd.c
 +++ b/drivers/net/wireless/ath/regd.c
-@@ -196,6 +196,10 @@ ath_reg_apply_beaconing_flags(struct wip
+@@ -341,6 +341,10 @@ ath_reg_apply_beaconing_flags(struct wip
        struct ieee80211_channel *ch;
        unsigned int i;
  
@@ -9,11 +9,11 @@
 +#endif
 +
        for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
                if (!wiphy->bands[band])
-@@ -250,6 +254,10 @@ ath_reg_apply_active_scan_flags(struct w
-       struct ieee80211_channel *ch;
-       const struct ieee80211_reg_rule *reg_rule;
+                       continue;
+@@ -374,6 +378,10 @@ ath_reg_apply_ir_flags(struct wiphy *wip
+ {
+       struct ieee80211_supported_band *sband;
  
 +#ifdef CPTCFG_ATH_USER_REGD
 +      return;
@@ -22,7 +22,7 @@
        sband = wiphy->bands[IEEE80211_BAND_2GHZ];
        if (!sband)
                return;
-@@ -299,6 +307,10 @@ static void ath_reg_apply_radar_flags(st
+@@ -402,6 +410,10 @@ static void ath_reg_apply_radar_flags(st
        struct ieee80211_channel *ch;
        unsigned int i;
  
@@ -33,7 +33,7 @@
        if (!wiphy->bands[IEEE80211_BAND_5GHZ])
                return;
  
-@@ -503,6 +515,10 @@ ath_regd_init_wiphy(struct ath_regulator
+@@ -631,6 +643,10 @@ ath_regd_init_wiphy(struct ath_regulator
  {
        const struct ieee80211_regdomain *regd;
  
@@ -42,8 +42,8 @@
 +#endif
 +
        wiphy->reg_notifier = reg_notifier;
-       wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+       wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
+                                  REGULATORY_CUSTOM_REG;
 --- a/drivers/net/wireless/ath/Kconfig
 +++ b/drivers/net/wireless/ath/Kconfig
 @@ -21,6 +21,9 @@ menuconfig ATH_CARDS
        ---help---
 --- a/.local-symbols
 +++ b/.local-symbols
-@@ -123,6 +123,7 @@ RTL8187_LEDS=
+@@ -119,6 +119,7 @@ RTL8187_LEDS=
  ATH_COMMON=
  ATH_CARDS=
  ATH_DEBUG=
 +ATH_USER_REGD=
+ ATH_REG_DYNAMIC_USER_REG_HINTS=
+ ATH_REG_DYNAMIC_USER_CERT_TESTING=
  ATH5K=
- ATH5K_DEBUG=
- ATH5K_TRACER=
index 7a5840eb1878a0ca28379f9692562192ae407706..2b04309ce53ad52874a887fa13f52669f5b80230 100644 (file)
@@ -1,16 +1,16 @@
 --- a/drivers/net/wireless/ath/regd.c
 +++ b/drivers/net/wireless/ath/regd.c
-@@ -42,7 +42,8 @@ static int __ath_regd_init(struct ath_re
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
+@@ -43,7 +43,8 @@ static int __ath_regd_init(struct ath_re
+                                        NL80211_RRF_NO_OFDM)
  
  /* We allow IBSS on these on a case by case basis by regulatory domain */
 -#define ATH9K_5GHZ_5150_5350  REG_RULE(5150-10, 5350+10, 80, 0, 30,\
-+#define ATH9K_5GHZ_5150_5350  REG_RULE(5150-10, 5250, 80, 0, 30, 0), \
-+                              REG_RULE(5250, 5350+10, 80, 0, 30,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
++#define ATH9K_5GHZ_5150_5350  REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\
++                              REG_RULE(5260-10, 5350+10, 80, 0, 30,\
+                                        NL80211_RRF_NO_IR)
  #define ATH9K_5GHZ_5470_5850  REG_RULE(5470-10, 5850+10, 80, 0, 30,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
-@@ -60,57 +61,56 @@ static int __ath_regd_init(struct ath_re
+                                        NL80211_RRF_NO_IR)
+@@ -61,57 +62,56 @@ static int __ath_regd_init(struct ath_re
  #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
                                ATH9K_5GHZ_5725_5850
  
@@ -81,4 +81,4 @@
 +      )
  };
  
- static inline bool is_wwr_sku(u16 regd)
+ static bool dynamic_country_user_possible(struct ath_regulatory *reg)
index 5380853df65a56a9aed72a6e4a6c28e76cf08ebe..6ad4fda272351cc0bad1306f2be5a355f38ef0c5 100644 (file)
@@ -1,6 +1,6 @@
 --- a/net/wireless/reg.c
 +++ b/net/wireless/reg.c
-@@ -1696,6 +1696,8 @@ void regulatory_hint_11d(struct wiphy *w
+@@ -1878,6 +1878,8 @@ void regulatory_hint_country_ie(struct w
        enum environment_cap env = ENVIRON_ANY;
        struct regulatory_request *request = NULL, *lr;
  
@@ -9,7 +9,7 @@
        /* IE len must be evenly divisible by 2 */
        if (country_ie_len & 0x01)
                return;
-@@ -1890,6 +1892,7 @@ static void restore_regulatory_settings(
+@@ -2072,6 +2074,7 @@ static void restore_regulatory_settings(
  
  void regulatory_hint_disconnect(void)
  {
index f6182dd31bfbdc268965807dc420c3eb6a385615..1f71e0b8aa3c547579ca241301d1546e34c7a35f 100644 (file)
@@ -1,10 +1,10 @@
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -755,6 +755,7 @@ static const struct ieee80211_iface_limi
+@@ -866,6 +866,7 @@ static const struct ieee80211_iface_limi
  #endif
                                 BIT(NL80211_IFTYPE_AP) |
                                 BIT(NL80211_IFTYPE_P2P_GO) },
 +      { .max = 1,     .types = BIT(NL80211_IFTYPE_ADHOC) },
  };
  
+ static const struct ieee80211_iface_limit if_dfs_limits[] = {
index 12e03e1bb13876affaf06f91c8fa3979cf3354ab..3487ab26f2e4b03714953b2ffdc4f32d0cfba51a 100644 (file)
@@ -18,7 +18,7 @@
                goto end;
 --- a/drivers/net/wireless/ath/ath5k/base.c
 +++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1916,7 +1916,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+@@ -1934,7 +1934,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
        }
  
        if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
@@ -27,7 +27,7 @@
                        ah->opmode == NL80211_IFTYPE_MESH_POINT) {
                u64 tsf = ath5k_hw_get_tsf64(ah);
                u32 tsftu = TSF_TO_TU(tsf);
-@@ -2002,7 +2002,7 @@ ath5k_beacon_update_timers(struct ath5k_
+@@ -2020,7 +2020,7 @@ ath5k_beacon_update_timers(struct ath5k_
  
        intval = ah->bintval & AR5K_BEACON_PERIOD;
        if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
@@ -36,7 +36,7 @@
                intval /= ATH_BCBUF;    /* staggered multi-bss beacons */
                if (intval < 15)
                        ATH5K_WARN(ah, "intval %u is too low, min 15\n",
-@@ -2469,6 +2469,7 @@ static const struct ieee80211_iface_limi
+@@ -2487,6 +2487,7 @@ static const struct ieee80211_iface_limi
                                 BIT(NL80211_IFTYPE_MESH_POINT) |
  #endif
                                 BIT(NL80211_IFTYPE_AP) },
index 01c28bcca262f94cb3263a28d2aee51e6b1dcec1..a8ebdf51261610a9dcd5f490a471d6f56895f2e0 100644 (file)
@@ -11,7 +11,7 @@ drivers/net/wireless/ath/ath5k/debug.c |   86 ++++++++++++++++++++++++++++++++
 
 --- a/drivers/net/wireless/ath/ath5k/debug.c
 +++ b/drivers/net/wireless/ath/ath5k/debug.c
-@@ -811,6 +811,89 @@ static const struct file_operations fops
+@@ -821,6 +821,97 @@ static const struct file_operations fops
        .llseek = default_llseek,
  };
  
@@ -24,7 +24,7 @@ drivers/net/wireless/ath/ath5k/debug.c |   86 ++++++++++++++++++++++++++++++++
 +      char buf[15];
 +      unsigned int len = 0;
 +
-+      int cur_ah_bwmode = ah->ah_bwmode;
++      int cur_ah_bwmode = ah->ah_bwmode_debug;
 +
 +#define print_selected(MODE, LABEL) \
 +      if (cur_ah_bwmode == MODE) \
@@ -77,16 +77,24 @@ drivers/net/wireless/ath/ath5k/debug.c |   86 ++++++++++++++++++++++++++++++++
 +              bw, tobwmode);
 +
 +      switch (ah->ah_radio) {
-+              /* TODO: only define radios that actually support 5/10mhz channels */
-+              case AR5K_RF5413: case AR5K_RF5110: case AR5K_RF5111: case AR5K_RF5112: case AR5K_RF2413: case AR5K_RF2316: case AR5K_RF2317: case AR5K_RF2425:
-+                      if(ah->ah_bwmode != tobwmode) {
-+                              mutex_lock(&ah->lock);
-+                              ah->ah_bwmode = tobwmode;
-+                              mutex_unlock(&ah->lock);
-+                      }
-+                      break;
-+              default:
-+                      return -EOPNOTSUPP;
++      /* TODO: only define radios that actually support 5/10mhz channels */
++      case AR5K_RF5413:
++      case AR5K_RF5110:
++      case AR5K_RF5111:
++      case AR5K_RF5112:
++      case AR5K_RF2413:
++      case AR5K_RF2316:
++      case AR5K_RF2317:
++      case AR5K_RF2425:
++              if(ah->ah_bwmode_debug != tobwmode) {
++                      mutex_lock(&ah->lock);
++                      ah->ah_bwmode = tobwmode;
++                      ah->ah_bwmode_debug = tobwmode;
++                      mutex_unlock(&ah->lock);
++              }
++              break;
++      default:
++              return -EOPNOTSUPP;
 +      }
 +      return count;
 +}
@@ -101,7 +109,7 @@ drivers/net/wireless/ath/ath5k/debug.c |   86 ++++++++++++++++++++++++++++++++
  
  /* debugfs: queues etc */
  
-@@ -902,6 +985,9 @@ ath5k_debug_init_device(struct ath5k_hw 
+@@ -914,6 +1005,9 @@ ath5k_debug_init_device(struct ath5k_hw 
        debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
                            &fops_beacon);
  
@@ -111,3 +119,25 @@ drivers/net/wireless/ath/ath5k/debug.c |   86 ++++++++++++++++++++++++++++++++
        debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
  
        debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
+--- a/drivers/net/wireless/ath/ath5k/ath5k.h
++++ b/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1369,6 +1369,7 @@ struct ath5k_hw {
+       u8                      ah_coverage_class;
+       bool                    ah_ack_bitrate_high;
+       u8                      ah_bwmode;
++      u8                      ah_bwmode_debug;
+       bool                    ah_short_slot;
+       /* Antenna Control */
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -466,6 +466,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru
+               return -EINVAL;
+       }
++      if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT)
++              ah->ah_bwmode = ah->ah_bwmode_debug;
++
+       /*
+        * To switch channels clear any pending DMA operations;
+        * wait long enough for the RX fifo to drain, reset the
index 7f4e68d5ea36dd0092e27f73817866b9f41a555a..664cf45175837a08946dc9e7647b1906157b4bc2 100644 (file)
@@ -1,7 +1,7 @@
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1735,6 +1735,53 @@ void ath9k_deinit_debug(struct ath_softc
-       }
+@@ -1481,6 +1481,53 @@ void ath9k_deinit_debug(struct ath_softc
+       ath9k_spectral_deinit_debug(sc);
  }
  
 +static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
@@ -54,9 +54,9 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
-@@ -1752,6 +1799,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-       ath9k_dfs_init_debug(sc);
+@@ -1500,6 +1547,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+       ath9k_tx99_init_debug(sc);
+       ath9k_spectral_init_debug(sc);
  
 +      debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
 +                          &fops_eeprom);
index b98e8f50f02352df0758974225829a82a9d8c755..96e7c6d8cc4228bcde3085c376de4b1dec644c82 100644 (file)
@@ -71,7 +71,7 @@
  
 --- a/drivers/net/wireless/ath/ath9k/hw.h
 +++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -739,6 +739,7 @@ enum ath_cal_list {
+@@ -724,6 +724,7 @@ enum ath_cal_list {
  #define AH_USE_EEPROM   0x1
  #define AH_UNPLUGGED    0x2 /* The card has been physically removed. */
  #define AH_FASTCC       0x4
@@ -81,7 +81,7 @@
        struct ath_ops reg_ops;
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -613,6 +613,8 @@ static int ath9k_init_softc(u16 devid, s
+@@ -722,6 +722,8 @@ static int ath9k_init_softc(u16 devid, s
                ah->is_clk_25mhz = pdata->is_clk_25mhz;
                ah->get_mac_revision = pdata->get_mac_revision;
                ah->external_reset = pdata->external_reset;
@@ -89,7 +89,7 @@
 +                      ah->ah_flags |= AH_NO_EEP_SWAP;
        }
  
-       common = ath9k_hw_common(ah);
+       common->ops = &ah->reg_ops;
 --- a/include/linux/ath9k_platform.h
 +++ b/include/linux/ath9k_platform.h
 @@ -31,6 +31,7 @@ struct ath9k_platform_data {
@@ -98,5 +98,5 @@
  
 +      bool endian_check;
        bool is_clk_25mhz;
-       int (*get_mac_revision)(void);
-       int (*external_reset)(void);
+       bool tx_gain_buffalo;
index 03199d8f377cb86db20d525a64f60c632026c1d8..4edc63bede32ee54dcd204924963bb2ab47774e5 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -1011,23 +1011,23 @@ static int __init ath9k_init(void)
+@@ -1112,23 +1112,23 @@ static int __init ath9k_init(void)
                goto err_out;
        }
  
index 647bde2ca0e998e0c4b435f40381a596a79af1c5..d7478ff590f88264c82407897cd9b6f96d5687c8 100644 (file)
@@ -1,13 +1,18 @@
 --- a/drivers/net/wireless/ath/ath9k/hw.c
 +++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2010,8 +2010,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-               REG_WRITE(ah, AR_OBS, 8);
+@@ -359,13 +359,8 @@ static void ath9k_hw_init_config(struct 
  
-       if (ah->config.rx_intr_mitigation) {
--              REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
--              REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
-+              REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 250);
-+              REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 500);
-       }
+       ah->config.rx_intr_mitigation = true;
  
-       if (ah->config.tx_intr_mitigation) {
+-      if (AR_SREV_9300_20_OR_LATER(ah)) {
+-              ah->config.rimt_last = 500;
+-              ah->config.rimt_first = 2000;
+-      } else {
+-              ah->config.rimt_last = 250;
+-              ah->config.rimt_first = 700;
+-      }
++      ah->config.rimt_last = 250;
++      ah->config.rimt_first = 500;
+       /*
+        * We need this for PCI devices only (Cardbus, PCI, miniPCI)
index 8d8c5fd7fe6c9b0b38253dd45d66175ec2c0efbc..ef0b9a1e2aa34d2e1fea874d01c98358031567cd 100644 (file)
@@ -1,8 +1,8 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -119,7 +119,7 @@ int ath_descdma_setup(struct ath_softc *
- /* RX / TX */
- /***********/
+@@ -90,7 +90,7 @@ int ath_descdma_setup(struct ath_softc *
+               (_l) &= ((_sz) - 1);            \
+       } while (0)
  
 -#define ATH_RXBUF               512
 +#define ATH_RXBUF               256
index a42daf5c3ec681551d9a57cdf760338e07188649..8f3cc030439ee6587b91eacc372848e47feb8f0a 100644 (file)
@@ -1,24 +1,6 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -701,6 +701,7 @@ struct ath_softc {
-       struct ieee80211_hw *hw;
-       struct device *dev;
-+      u32 chan_bw;
-       struct survey_info *cur_survey;
-       struct survey_info survey[ATH9K_NUM_CHANNELS];
-@@ -905,6 +906,7 @@ struct fft_sample_ht20 {
-       u8 data[SPECTRAL_HT20_NUM_BINS];
- } __packed;
-+int ath9k_config(struct ieee80211_hw *hw, u32 changed);
- void ath9k_tasklet(unsigned long data);
- int ath_cabq_update(struct ath_softc *);
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1782,6 +1782,50 @@ static const struct file_operations fops
+@@ -1528,6 +1528,52 @@ static const struct file_operations fops
        .owner = THIS_MODULE
  };
  
 +                           size_t count, loff_t *ppos)
 +{
 +      struct ath_softc *sc = file->private_data;
++      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 +      char buf[32];
 +      unsigned int len;
 +
-+      len = sprintf(buf, "0x%08x\n", sc->chan_bw);
++      len = sprintf(buf, "0x%08x\n", common->chan_bw);
 +      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 +}
 +
@@ -38,6 +21,7 @@
 +                           size_t count, loff_t *ppos)
 +{
 +      struct ath_softc *sc = file->private_data;
++      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 +      unsigned long chan_bw;
 +      char buf[32];
 +      ssize_t len;
@@ -50,9 +34,9 @@
 +      if (kstrtoul(buf, 0, &chan_bw))
 +              return -EINVAL;
 +
-+      sc->chan_bw = chan_bw;
++      common->chan_bw = chan_bw;
 +      if (!test_bit(SC_OP_INVALID, &sc->sc_flags))
-+              ath9k_config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL);
++              ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL);
 +
 +      return count;
 +}
@@ -69,7 +53,7 @@
  int ath9k_init_debug(struct ath_hw *ah)
  {
        struct ath_common *common = ath9k_hw_common(ah);
-@@ -1801,6 +1845,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1549,6 +1595,8 @@ int ath9k_init_debug(struct ath_hw *ah)
  
        debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_eeprom);
        debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
                            &fops_dma);
        debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1138,7 +1138,7 @@ int ath9k_spectral_scan_config(struct ie
-       return 0;
- }
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -130,6 +130,7 @@ struct ath_common {
+       struct ieee80211_hw *hw;
+       int debug_mask;
+       enum ath_device_state state;
++      u32 chan_bw;
  
--static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
-+int ath9k_config(struct ieee80211_hw *hw, u32 changed)
+       struct ath_ani ani;
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -52,11 +52,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke
+ /*
+  * Update internal channel flags.
+  */
+-static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
++static void ath9k_cmn_update_ichannel(struct ath_common *common,
++                                    struct ath9k_channel *ichan,
+                                     struct cfg80211_chan_def *chandef)
  {
-       struct ath_softc *sc = hw->priv;
-       struct ath_hw *ah = sc->sc_ah;
-@@ -1194,9 +1194,11 @@ static int ath9k_config(struct ieee80211
-               struct ieee80211_channel *curchan = hw->conf.chandef.chan;
-               enum nl80211_channel_type channel_type =
-                       cfg80211_get_chandef_type(&conf->chandef);
-+              struct ath9k_channel *hchan;
-               int pos = curchan->hw_value;
-               int old_pos = -1;
-               unsigned long flags;
-+              u32 oldflags;
+       struct ieee80211_channel *chan = chandef->chan;
+       u16 flags = 0;
++      int width;
  
-               if (ah->curchan)
-                       old_pos = ah->curchan - &ah->channels[0];
-@@ -1232,7 +1234,23 @@ static int ath9k_config(struct ieee80211
-                       memset(&sc->survey[pos], 0, sizeof(struct survey_info));
-               }
+       ichan->channel = chan->center_freq;
+       ichan->chan = chan;
+@@ -64,7 +66,19 @@ static void ath9k_cmn_update_ichannel(st
+       if (chan->band == IEEE80211_BAND_5GHZ)
+               flags |= CHANNEL_5GHZ;
  
--              if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) {
-+              hchan = &sc->sc_ah->channels[pos];
-+              oldflags = hchan->channelFlags;
-+              switch (sc->chan_bw) {
-+              case 5:
-+                      hchan->channelFlags &= ~CHANNEL_HALF;
-+                      hchan->channelFlags |= CHANNEL_QUARTER;
-+                      break;
-+              case 10:
-+                      hchan->channelFlags &= ~CHANNEL_QUARTER;
-+                      hchan->channelFlags |= CHANNEL_HALF;
-+                      break;
-+              default:
-+                      hchan->channelFlags &= ~(CHANNEL_HALF | CHANNEL_QUARTER);
-+                      break;
-+              }
+-      switch (chandef->width) {
++      switch (common->chan_bw) {
++      case 5:
++              width = NL80211_CHAN_WIDTH_5;
++              break;
++      case 10:
++              width = NL80211_CHAN_WIDTH_10;
++              break;
++      default:
++              width = chandef->width;
++              break;
++      }
 +
-+              if (ath_set_channel(sc, hw, hchan) < 0) {
-                       ath_err(common, "Unable to set channel\n");
-                       mutex_unlock(&sc->mutex);
-                       ath9k_ps_restore(sc);
++      switch (width) {
+       case NL80211_CHAN_WIDTH_5:
+               flags |= CHANNEL_QUARTER;
+               break;
+@@ -97,10 +111,11 @@ struct ath9k_channel *ath9k_cmn_get_chan
+                                           struct cfg80211_chan_def *chandef)
+ {
+       struct ieee80211_channel *curchan = chandef->chan;
++      struct ath_common *common = ath9k_hw_common(ah);
+       struct ath9k_channel *channel;
+       channel = &ah->channels[curchan->hw_value];
+-      ath9k_cmn_update_ichannel(channel, chandef);
++      ath9k_cmn_update_ichannel(common, channel, chandef);
+       return channel;
+ }
diff --git a/package/mac80211/patches/513-ath9k_add_pci_ids.patch b/package/mac80211/patches/513-ath9k_add_pci_ids.patch
new file mode 100644 (file)
index 0000000..db4e6a1
--- /dev/null
@@ -0,0 +1,30 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -614,6 +614,7 @@ int ath9k_hw_init(struct ath_hw *ah)
+       /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */
+       switch (ah->hw_version.devid) {
++      case AR9300_DEVID_INVALID:
+       case AR5416_DEVID_PCI:
+       case AR5416_DEVID_PCIE:
+       case AR5416_AR9100_DEVID:
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -34,6 +34,7 @@
+ #define ATHEROS_VENDOR_ID     0x168c
++#define AR9300_DEVID_INVALID  0xabcd
+ #define AR5416_DEVID_PCI      0x0023
+ #define AR5416_DEVID_PCIE     0x0024
+ #define AR9160_DEVID_PCI      0x0027
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -658,6 +658,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_i
+       { PCI_VDEVICE(ATHEROS, 0x0036),
+         .driver_data = ATH9K_PCI_BT_ANT_DIV },
++      { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E  internal chip default ID */
+       { 0 }
+ };
index 837d9f633f180f2f54e43e34acdd8a48d9251ce2..6df95bceaec7cb227b46a483c843559f8e521d76 100644 (file)
@@ -1,6 +1,6 @@
 --- a/include/net/mac80211.h
 +++ b/include/net/mac80211.h
-@@ -1616,6 +1616,7 @@ struct ieee80211_hw {
+@@ -1711,6 +1711,7 @@ struct ieee80211_hw {
        u8 max_tx_aggregation_subframes;
        u8 offchannel_tx_hw_queue;
        u8 radiotap_mcs_details;
@@ -10,7 +10,7 @@
        u8 uapsd_queues;
 --- a/net/mac80211/cfg.c
 +++ b/net/mac80211/cfg.c
-@@ -2273,7 +2273,9 @@ static int ieee80211_get_tx_power(struct
+@@ -2329,7 +2329,9 @@ static int ieee80211_get_tx_power(struct
        struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
  
@@ -23,7 +23,7 @@
                *dbm = sdata->vif.bss_conf.txpower;
 --- a/net/mac80211/main.c
 +++ b/net/mac80211/main.c
-@@ -167,6 +167,7 @@ static u32 ieee80211_hw_conf_chan(struct
+@@ -158,6 +158,7 @@ static u32 ieee80211_hw_conf_chan(struct
  
        if (local->hw.conf.power_level != power) {
                changed |= IEEE80211_CONF_CHANGE_POWER;
index a14d0315f8c3efb3da22abb079d3bba5a7152a8f..0d6c360d384484da05f031e7d544a8e66a504021 100644 (file)
@@ -1,15 +1,20 @@
 --- a/drivers/net/wireless/ath/ath9k/main.c
 +++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1257,6 +1257,8 @@ int ath9k_config(struct ieee80211_hw *hw
-                       return -EINVAL;
-               }
+@@ -308,8 +308,12 @@ static int ath_reset_internal(struct ath
+           (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+               ath9k_mci_set_txpower(sc, true, false);
  
-+              hw->cur_power_level = sc->curtxpow / 2;
+-      if (!ath_complete_reset(sc, true))
++      if (!ath_complete_reset(sc, true)) {
+               r = -EIO;
++              goto out;
++      }
 +
-               /*
-                * The most recent snapshot of channel->noisefloor for the old
-                * channel is only available after the hardware reset. Copy it to
-@@ -1293,6 +1295,7 @@ int ath9k_config(struct ieee80211_hw *hw
++      sc->hw->cur_power_level = sc->curtxpow / 2;
+ out:
+       spin_unlock_bh(&sc->sc_pcu_lock);
+@@ -1371,6 +1375,7 @@ static int ath9k_config(struct ieee80211
                sc->config.txpowlimit = 2 * conf->power_level;
                ath9k_cmn_update_txpow(ah, sc->curtxpow,
                                       sc->config.txpowlimit, &sc->curtxpow);
diff --git a/package/mac80211/patches/522-ath9k_per_chain_signal_strength.patch b/package/mac80211/patches/522-ath9k_per_chain_signal_strength.patch
deleted file mode 100644 (file)
index 50dbcd9..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/mac.h
-+++ b/drivers/net/wireless/ath/ath9k/mac.h
-@@ -133,12 +133,8 @@ struct ath_rx_status {
-       u8 rs_rate;
-       u8 rs_antenna;
-       u8 rs_more;
--      int8_t rs_rssi_ctl0;
--      int8_t rs_rssi_ctl1;
--      int8_t rs_rssi_ctl2;
--      int8_t rs_rssi_ext0;
--      int8_t rs_rssi_ext1;
--      int8_t rs_rssi_ext2;
-+      int8_t rs_rssi_ctl[3];
-+      int8_t rs_rssi_ext[3];
-       u8 rs_isaggr;
-       u8 rs_moreaggr;
-       u8 rs_num_delims;
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -939,6 +939,7 @@ static int ath9k_rx_skb_preprocess(struc
-       struct ath_hw *ah = sc->sc_ah;
-       struct ath_common *common = ath9k_hw_common(ah);
-       bool discard_current = sc->rx.discard_next;
-+      int i, j;
-       sc->rx.discard_next = rx_stats->rs_more;
-       if (discard_current)
-@@ -968,6 +969,21 @@ static int ath9k_rx_skb_preprocess(struc
-       if (rx_stats->rs_moreaggr)
-               rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
-+      for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
-+              s8 rssi;
-+
-+              if (!(ah->rxchainmask & BIT(i)))
-+                      continue;
-+
-+              rssi = rx_stats->rs_rssi_ctl[i];
-+              if (rssi != ATH9K_RSSI_BAD) {
-+                  rx_status->chains |= BIT(j);
-+                  rx_status->chain_signal[j] = ah->noise + rssi;
-+              }
-+              j++;
-+      }
-+
-+
-       sc->rx.discard_next = false;
-       return 0;
- }
-@@ -1077,7 +1093,7 @@ static int ath_process_fft(struct ath_so
-       fft_sample.tlv.length = __cpu_to_be16(length);
-       fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq);
--      fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
-+      fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl[0]);
-       fft_sample.noise = ah->noise;
-       switch (len - SPECTRAL_HT20_TOTAL_DATA_LEN) {
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -476,12 +476,12 @@ int ath9k_hw_process_rxdesc_edma(struct 
-       /* XXX: Keycache */
-       rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
--      rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
--      rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
--      rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
--      rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
--      rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
--      rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
-+      rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_RxRSSIAnt00);
-+      rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_RxRSSIAnt01);
-+      rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_RxRSSIAnt02);
-+      rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_RxRSSIAnt10);
-+      rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_RxRSSIAnt11);
-+      rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_RxRSSIAnt12);
-       if (rxsp->status11 & AR_RxKeyIdxValid)
-               rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -554,25 +554,25 @@ int ath9k_hw_rxprocdesc(struct ath_hw *a
-       if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) {
-               rs->rs_rssi = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ext0 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ext1 = ATH9K_RSSI_BAD;
--              rs->rs_rssi_ext2 = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ctl[0] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ctl[1] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ctl[2] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ext[0] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ext[1] = ATH9K_RSSI_BAD;
-+              rs->rs_rssi_ext[2] = ATH9K_RSSI_BAD;
-       } else {
-               rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
--              rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0,
-+              rs->rs_rssi_ctl[0] = MS(ads.ds_rxstatus0,
-                                               AR_RxRSSIAnt00);
--              rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0,
-+              rs->rs_rssi_ctl[1] = MS(ads.ds_rxstatus0,
-                                               AR_RxRSSIAnt01);
--              rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0,
-+              rs->rs_rssi_ctl[2] = MS(ads.ds_rxstatus0,
-                                               AR_RxRSSIAnt02);
--              rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4,
-+              rs->rs_rssi_ext[0] = MS(ads.ds_rxstatus4,
-                                               AR_RxRSSIAnt10);
--              rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4,
-+              rs->rs_rssi_ext[1] = MS(ads.ds_rxstatus4,
-                                               AR_RxRSSIAnt11);
--              rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4,
-+              rs->rs_rssi_ext[2] = MS(ads.ds_rxstatus4,
-                                               AR_RxRSSIAnt12);
-       }
-       if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
---- a/drivers/net/wireless/ath/ath9k/dfs.c
-+++ b/drivers/net/wireless/ath/ath9k/dfs.c
-@@ -158,8 +158,8 @@ void ath9k_dfs_process_phyerr(struct ath
-               return;
-       }
--      ard.rssi = rs->rs_rssi_ctl0;
--      ard.ext_rssi = rs->rs_rssi_ext0;
-+      ard.rssi = rs->rs_rssi_ctl[0];
-+      ard.ext_rssi = rs->rs_rssi_ext[0];
-       /*
-        * hardware stores this as 8 bit signed value.
---- a/drivers/net/wireless/ath/ath9k/antenna.c
-+++ b/drivers/net/wireless/ath/ath9k/antenna.c
-@@ -546,14 +546,14 @@ void ath_ant_comb_scan(struct ath_softc 
-       struct ath_ant_comb *antcomb = &sc->ant_comb;
-       int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set;
-       int curr_main_set;
--      int main_rssi = rs->rs_rssi_ctl0;
--      int alt_rssi = rs->rs_rssi_ctl1;
-+      int main_rssi = rs->rs_rssi_ctl[0];
-+      int alt_rssi = rs->rs_rssi_ctl[1];
-       int rx_ant_conf,  main_ant_conf;
-       bool short_scan = false;
--      rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) &
-+      rx_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_CURRENT_SHIFT) &
-                      ATH_ANT_RX_MASK;
--      main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
-+      main_ant_conf = (rs->rs_rssi_ctl[2] >> ATH_ANT_RX_MAIN_SHIFT) &
-                        ATH_ANT_RX_MASK;
-       /* Record packet only when both main_rssi and  alt_rssi is positive */
diff --git a/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch
new file mode 100644 (file)
index 0000000..308ee6e
--- /dev/null
@@ -0,0 +1,172 @@
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -2156,6 +2156,7 @@ struct cfg80211_qos_map {
+  *    (as advertised by the nl80211 feature flag.)
+  * @get_tx_power: store the current TX power into the dbm variable;
+  *    return 0 if successful
++ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
+  *
+  * @set_wds_peer: set the WDS peer for a WDS interface
+  *
+@@ -2380,6 +2381,7 @@ struct cfg80211_ops {
+                               enum nl80211_tx_power_setting type, int mbm);
+       int     (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
+                               int *dbm);
++      int     (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
+       int     (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+                               const u8 *addr);
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -1033,6 +1033,7 @@ enum ieee80211_smps_mode {
+  *
+  * @power_level: requested transmit power (in dBm), backward compatibility
+  *    value only that is set to the minimum of all interfaces
++ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
+  *
+  * @chandef: the channel definition to tune to
+  * @radar_enabled: whether radar detection is enabled
+@@ -1054,6 +1055,7 @@ struct ieee80211_conf {
+       u32 flags;
+       int power_level, dynamic_ps_timeout;
+       int max_sleep_period;
++      int max_antenna_gain;
+       u16 listen_interval;
+       u8 ps_dtim_period;
+--- a/include/uapi/linux/nl80211.h
++++ b/include/uapi/linux/nl80211.h
+@@ -1555,6 +1555,9 @@ enum nl80211_commands {
+  *    data is in the format defined for the payload of the QoS Map Set element
+  *    in IEEE Std 802.11-2012, 8.4.2.97.
+  *
++ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
++ *    transmit power to stay within regulatory limits. u32, dBi.
++ *
+  * @NL80211_ATTR_MAX: highest attribute number currently defined
+  * @__NL80211_ATTR_AFTER_LAST: internal use
+  */
+@@ -1883,6 +1886,8 @@ enum nl80211_attrs {
+       NL80211_ATTR_QOS_MAP,
++      NL80211_ATTR_WIPHY_ANTENNA_GAIN,
++
+       /* add attributes here, update the policy in nl80211.c */
+       __NL80211_ATTR_AFTER_LAST,
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -2339,6 +2339,19 @@ static int ieee80211_get_tx_power(struct
+       return 0;
+ }
++static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
++{
++      struct ieee80211_local *local = wiphy_priv(wiphy);
++
++      if (dbi < 0)
++              return -EINVAL;
++
++      local->user_antenna_gain = dbi;
++      ieee80211_hw_config(local, 0);
++
++      return 0;
++}
++
+ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
+                                 const u8 *addr)
+ {
+@@ -3924,6 +3937,7 @@ struct cfg80211_ops mac80211_config_ops 
+       .set_wiphy_params = ieee80211_set_wiphy_params,
+       .set_tx_power = ieee80211_set_tx_power,
+       .get_tx_power = ieee80211_get_tx_power,
++      .set_antenna_gain = ieee80211_set_antenna_gain,
+       .set_wds_peer = ieee80211_set_wds_peer,
+       .rfkill_poll = ieee80211_rfkill_poll,
+       CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -1221,6 +1221,7 @@ struct ieee80211_local {
+       int dynamic_ps_forced_timeout;
+       int user_power_level; /* in dBm, for all interfaces */
++      int user_antenna_gain; /* in dBi */
+       enum ieee80211_smps_mode smps_mode;
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -101,7 +101,7 @@ static u32 ieee80211_hw_conf_chan(struct
+       struct ieee80211_sub_if_data *sdata;
+       struct cfg80211_chan_def chandef = {};
+       u32 changed = 0;
+-      int power;
++      int power, ant_gain, max_power;
+       u32 offchannel_flag;
+       offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+@@ -156,8 +156,21 @@ static u32 ieee80211_hw_conf_chan(struct
+       }
+       rcu_read_unlock();
+-      if (local->hw.conf.power_level != power) {
++      max_power = chandef.chan->max_reg_power;
++      ant_gain = chandef.chan->max_antenna_gain;
++      if (local->user_antenna_gain > 0) {
++              if (local->user_antenna_gain > ant_gain) {
++                      max_power -= local->user_antenna_gain - ant_gain;
++                      ant_gain = 0;
++              } else
++                      ant_gain -= local->user_antenna_gain;
++              power = min(power, max_power);
++      }
++
++      if (local->hw.conf.power_level != power ||
++          local->hw.conf.max_antenna_gain != ant_gain) {
+               changed |= IEEE80211_CONF_CHANGE_POWER;
++              local->hw.conf.max_antenna_gain = ant_gain;
+               local->hw.cur_power_level = power;
+               local->hw.conf.power_level = power;
+       }
+@@ -584,6 +597,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(
+                                        IEEE80211_RADIOTAP_MCS_HAVE_BW;
+       local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
+                                        IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
++      local->user_antenna_gain = 0;
+       local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+       local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+       local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -384,6 +384,7 @@ static const struct nla_policy nl80211_p
+       [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
+       [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
+                                  .len = IEEE80211_QOS_MAP_LEN_MAX },
++      [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
+ };
+ /* policy for the key attributes */
+@@ -2105,6 +2106,22 @@ static int nl80211_set_wiphy(struct sk_b
+                       goto bad_res;
+       }
++      if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
++              int idx, dbi = 0;
++
++              if (!rdev->ops->set_antenna_gain) {
++                      result = -EOPNOTSUPP;
++                      goto bad_res;
++              }
++
++              idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
++              dbi = nla_get_u32(info->attrs[idx]);
++
++              result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
++              if (result)
++                      goto bad_res;
++      }
++
+       if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
+           info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
+               u32 tx_ant, rx_ant;
diff --git a/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch b/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch
new file mode 100644 (file)
index 0000000..30aa9ee
--- /dev/null
@@ -0,0 +1,34 @@
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -74,6 +74,7 @@ struct ath_regulatory {
+       u16 max_power_level;
+       u16 current_rd;
+       int16_t power_limit;
++      int16_t max_antenna_gain;
+       struct reg_dmn_pair_mapping *regpair;
+ };
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2721,7 +2721,7 @@ void ath9k_hw_apply_txpower(struct ath_h
+       channel = chan->chan;
+       chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
+       new_pwr = min_t(int, chan_pwr, reg->power_limit);
+-      max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
++      max_gain = chan_pwr - new_pwr + reg->max_antenna_gain * 2;
+       ant_gain = get_antenna_gain(ah, chan);
+       if (ant_gain > max_gain)
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1371,7 +1371,10 @@ static int ath9k_config(struct ieee80211
+       }
+       if (changed & IEEE80211_CONF_CHANGE_POWER) {
++              struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
++
+               ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
++              reg->max_antenna_gain = conf->max_antenna_gain;
+               sc->config.txpowlimit = 2 * conf->power_level;
+               ath9k_cmn_update_txpow(ah, sc->curtxpow,
+                                      sc->config.txpowlimit, &sc->curtxpow);
diff --git a/package/mac80211/patches/523-mac80211_configure_antenna_gain.patch b/package/mac80211/patches/523-mac80211_configure_antenna_gain.patch
deleted file mode 100644 (file)
index d247c56..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -999,6 +999,7 @@ enum ieee80211_smps_mode {
-  *
-  * @power_level: requested transmit power (in dBm), backward compatibility
-  *    value only that is set to the minimum of all interfaces
-+ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
-  *
-  * @chandef: the channel definition to tune to
-  * @radar_enabled: whether radar detection is enabled
-@@ -1020,6 +1021,7 @@ struct ieee80211_conf {
-       u32 flags;
-       int power_level, dynamic_ps_timeout;
-       int max_sleep_period;
-+      int max_antenna_gain;
-       u16 listen_interval;
-       u8 ps_dtim_period;
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1126,6 +1126,7 @@ struct ieee80211_local {
-       int dynamic_ps_forced_timeout;
-       int user_power_level; /* in dBm, for all interfaces */
-+      int user_antenna_gain; /* in dBi */
-       enum ieee80211_smps_mode smps_mode;
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -1736,6 +1736,8 @@ enum nl80211_attrs {
-       NL80211_ATTR_PEER_AID,
-+      NL80211_ATTR_WIPHY_ANTENNA_GAIN,
-+
-       /* add attributes here, update the policy in nl80211.c */
-       __NL80211_ATTR_AFTER_LAST,
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -349,6 +349,7 @@ static const struct nla_policy nl80211_p
-       [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
-                                 .len = IEEE80211_MAX_DATA_LEN },
-       [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },
-+      [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
- };
- /* policy for the key attributes */
-@@ -1993,6 +1994,22 @@ static int nl80211_set_wiphy(struct sk_b
-                       goto bad_res;
-       }
-+      if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
-+              int idx, dbi = 0;
-+
-+              if (!rdev->ops->set_antenna_gain) {
-+                      result = -EOPNOTSUPP;
-+                      goto bad_res;
-+              }
-+
-+              idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
-+              dbi = nla_get_u32(info->attrs[idx]);
-+
-+              result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
-+              if (result)
-+                      goto bad_res;
-+      }
-+
-       if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
-           info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
-               u32 tx_ant, rx_ant;
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -2283,6 +2283,19 @@ static int ieee80211_get_tx_power(struct
-       return 0;
- }
-+static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
-+{
-+      struct ieee80211_local *local = wiphy_priv(wiphy);
-+
-+      if (dbi < 0)
-+              return -EINVAL;
-+
-+      local->user_antenna_gain = dbi;
-+      ieee80211_hw_config(local, 0);
-+
-+      return 0;
-+}
-+
- static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
-                                 const u8 *addr)
- {
-@@ -3474,6 +3487,7 @@ struct cfg80211_ops mac80211_config_ops 
-       .set_wiphy_params = ieee80211_set_wiphy_params,
-       .set_tx_power = ieee80211_set_tx_power,
-       .get_tx_power = ieee80211_get_tx_power,
-+      .set_antenna_gain = ieee80211_set_antenna_gain,
-       .set_wds_peer = ieee80211_set_wds_peer,
-       .rfkill_poll = ieee80211_rfkill_poll,
-       CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -1970,6 +1970,7 @@ struct cfg80211_update_ft_ies_params {
-  *    (as advertised by the nl80211 feature flag.)
-  * @get_tx_power: store the current TX power into the dbm variable;
-  *    return 0 if successful
-+ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
-  *
-  * @set_wds_peer: set the WDS peer for a WDS interface
-  *
-@@ -2189,6 +2190,7 @@ struct cfg80211_ops {
-                               enum nl80211_tx_power_setting type, int mbm);
-       int     (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
-                               int *dbm);
-+      int     (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
-       int     (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
-                               const u8 *addr);
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -102,6 +102,7 @@ static u32 ieee80211_hw_conf_chan(struct
-       struct cfg80211_chan_def chandef = {};
-       u32 changed = 0;
-       int power = 0;
-+      int ant_gain, max_power;
-       u32 offchannel_flag;
-       offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
-@@ -165,8 +166,21 @@ static u32 ieee80211_hw_conf_chan(struct
-       power = min(power, chandef.chan->max_power);
--      if (local->hw.conf.power_level != power) {
-+      max_power = chandef.chan->max_reg_power;
-+      ant_gain = chandef.chan->max_antenna_gain;
-+      if (local->user_antenna_gain > 0) {
-+              if (local->user_antenna_gain > ant_gain) {
-+                      max_power -= local->user_antenna_gain - ant_gain;
-+                      ant_gain = 0;
-+              } else
-+                      ant_gain -= local->user_antenna_gain;
-+              power = min(power, max_power);
-+      }
-+
-+      if (local->hw.conf.power_level != power ||
-+              local->hw.conf.max_antenna_gain != ant_gain) {
-               changed |= IEEE80211_CONF_CHANGE_POWER;
-+              local->hw.conf.max_antenna_gain = ant_gain;
-               local->hw.cur_power_level = power;
-               local->hw.conf.power_level = power;
-       }
-@@ -597,6 +611,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(
-                                        IEEE80211_RADIOTAP_MCS_HAVE_BW;
-       local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
-                                        IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
-+      local->user_antenna_gain = 0;
-       local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
-       local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
-       local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
diff --git a/package/mac80211/patches/524-ath9k_use_configured_antenna_gain.patch b/package/mac80211/patches/524-ath9k_use_configured_antenna_gain.patch
deleted file mode 100644 (file)
index 9d627ac..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
---- a/drivers/net/wireless/ath/ath.h
-+++ b/drivers/net/wireless/ath/ath.h
-@@ -73,6 +73,7 @@ struct ath_regulatory {
-       u16 max_power_level;
-       u16 current_rd;
-       int16_t power_limit;
-+      int16_t max_antenna_gain;
-       struct reg_dmn_pair_mapping *regpair;
- };
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2847,7 +2847,7 @@ void ath9k_hw_apply_txpower(struct ath_h
-       channel = chan->chan;
-       chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
-       new_pwr = min_t(int, chan_pwr, reg->power_limit);
--      max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
-+      max_gain = chan_pwr - new_pwr + reg->max_antenna_gain * 2;
-       ant_gain = get_antenna_gain(ah, chan);
-       if (ant_gain > max_gain)
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1291,7 +1291,10 @@ int ath9k_config(struct ieee80211_hw *hw
-       }
-       if (changed & IEEE80211_CONF_CHANGE_POWER) {
-+              struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
-+
-               ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
-+              reg->max_antenna_gain = conf->max_antenna_gain;
-               sc->config.txpowlimit = 2 * conf->power_level;
-               ath9k_cmn_update_txpow(ah, sc->curtxpow,
-                                      sc->config.txpowlimit, &sc->curtxpow);
index b931d5f4cf001de08a1beb0eb4689e57afc4dda3..59f78d9dfa67f2c47dc7c36ee592eb3e2f49b648 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -557,6 +557,9 @@ struct ath9k_wow_pattern {
+@@ -563,6 +563,9 @@ static inline int ath9k_dump_btcoex(stru
  void ath_init_leds(struct ath_softc *sc);
  void ath_deinit_leds(struct ath_softc *sc);
  void ath_fill_led_pin(struct ath_softc *sc);
@@ -10,9 +10,9 @@
  #else
  static inline void ath_init_leds(struct ath_softc *sc)
  {
-@@ -697,6 +700,13 @@ enum spectral_mode {
-       SPECTRAL_CHANSCAN,
- };
+@@ -710,6 +713,13 @@ enum sc_op_flags {
+ #define PS_BEACON_SYNC            BIT(4)
+ #define PS_WAIT_FOR_ANI           BIT(5)
  
 +struct ath_led {
 +      struct list_head list;
@@ -24,7 +24,7 @@
  struct ath_softc {
        struct ieee80211_hw *hw;
        struct device *dev;
-@@ -739,9 +749,8 @@ struct ath_softc {
+@@ -751,9 +761,8 @@ struct ath_softc {
        struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
  
  #ifdef CPTCFG_MAC80211_LEDS
  void ath_fill_led_pin(struct ath_softc *sc)
 --- a/drivers/net/wireless/ath/ath9k/init.c
 +++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -918,7 +918,7 @@ int ath9k_init_device(u16 devid, struct 
+@@ -1018,7 +1018,7 @@ int ath9k_init_device(u16 devid, struct 
  
  #ifdef CPTCFG_MAC80211_LEDS
        /* must be initialized before ieee80211_register_hw */
  #endif
 --- a/drivers/net/wireless/ath/ath9k/debug.c
 +++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1825,6 +1825,61 @@ static const struct file_operations fops
+@@ -1573,6 +1573,61 @@ static const struct file_operations fops
        .llseek = default_llseek,
  };
  
  
  int ath9k_init_debug(struct ath_hw *ah)
  {
-@@ -1847,6 +1902,10 @@ int ath9k_init_debug(struct ath_hw *ah)
+@@ -1597,6 +1652,10 @@ int ath9k_init_debug(struct ath_hw *ah)
                            &fops_eeprom);
        debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
                            sc, &fops_chanbw);
index 764242cd1c44eb23fba46782ecd66fd101e52e00..6c9832c4a063bf1e73b6fd2cc6535a298242f04d 100644 (file)
@@ -1,7 +1,7 @@
 --- a/include/linux/ath9k_platform.h
 +++ b/include/linux/ath9k_platform.h
-@@ -35,6 +35,9 @@ struct ath9k_platform_data {
-       bool is_clk_25mhz;
+@@ -37,6 +37,9 @@ struct ath9k_platform_data {
        int (*get_mac_revision)(void);
        int (*external_reset)(void);
 +
diff --git a/package/mac80211/patches/540-ath9k_reduce_ani_interval.patch b/package/mac80211/patches/540-ath9k_reduce_ani_interval.patch
new file mode 100644 (file)
index 0000000..e899903
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/ath/ath9k/ani.h
++++ b/drivers/net/wireless/ath/ath9k/ani.h
+@@ -42,7 +42,7 @@
+ #define ATH9K_ANI_PERIOD                  300
+ /* in ms */
+-#define ATH9K_ANI_POLLINTERVAL            1000
++#define ATH9K_ANI_POLLINTERVAL            300
+ #define ATH9K_SIG_FIRSTEP_SETTING_MIN     0
+ #define ATH9K_SIG_FIRSTEP_SETTING_MAX     20
diff --git a/package/mac80211/patches/541-ath9k_optimize_interrupt_mitigation.patch b/package/mac80211/patches/541-ath9k_optimize_interrupt_mitigation.patch
deleted file mode 100644 (file)
index 95ceb35..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
-@@ -241,21 +241,19 @@ static bool ar9003_hw_get_isr(struct ath
-               *masked = isr & ATH9K_INT_COMMON;
--              if (ah->config.rx_intr_mitigation)
-+              if (ah->config.rx_intr_mitigation) {
-                       if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
-                               *masked |= ATH9K_INT_RXLP;
--
--              if (ah->config.tx_intr_mitigation)
--                      if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
--                              *masked |= ATH9K_INT_TX;
--
--              if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
-+              } else if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
-                       *masked |= ATH9K_INT_RXLP;
-               if (isr & AR_ISR_HP_RXOK)
-                       *masked |= ATH9K_INT_RXHP;
--              if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
-+              if (ah->config.tx_intr_mitigation) {
-+                      if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
-+                              *masked |= ATH9K_INT_TX;
-+              } else if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
-                       *masked |= ATH9K_INT_TX;
-                       if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
diff --git a/package/mac80211/patches/541-ath9k_rx_dma_stop_check.patch b/package/mac80211/patches/541-ath9k_rx_dma_stop_check.patch
new file mode 100644 (file)
index 0000000..a521525
--- /dev/null
@@ -0,0 +1,28 @@
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -700,7 +700,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
+ {
+ #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
+       struct ath_common *common = ath9k_hw_common(ah);
+-      u32 mac_status, last_mac_status = 0;
++      u32 mac_status = 0, last_mac_status = 0;
+       int i;
+       /* Enable access to the DMA observation bus */
+@@ -730,6 +730,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
+       }
+       if (i == 0) {
++              if (!AR_SREV_9300_20_OR_LATER(ah) &&
++                  (mac_status & 0x700) == 0) {
++                      /*
++                       * DMA is idle but the MAC is still stuck
++                       * processing events
++                       */
++                      *reset = true;
++                      return true;
++              }
++
+               ath_err(common,
+                       "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
+                       AH_RX_STOP_DMA_TIMEOUT / 1000,
diff --git a/package/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/mac80211/patches/542-ath9k_debugfs_diag.patch
new file mode 100644 (file)
index 0000000..e1b6ff1
--- /dev/null
@@ -0,0 +1,139 @@
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1629,6 +1629,50 @@ static const struct file_operations fops
+ #endif
++static ssize_t read_file_diag(struct file *file, char __user *user_buf,
++                           size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      struct ath_hw *ah = sc->sc_ah;
++      char buf[32];
++      unsigned int len;
++
++      len = sprintf(buf, "0x%08lx\n", ah->diag);
++      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_diag(struct file *file, const char __user *user_buf,
++                           size_t count, loff_t *ppos)
++{
++      struct ath_softc *sc = file->private_data;
++      struct ath_hw *ah = sc->sc_ah;
++      unsigned long diag;
++      char buf[32];
++      ssize_t len;
++
++      len = min(count, sizeof(buf) - 1);
++      if (copy_from_user(buf, user_buf, len))
++              return -EFAULT;
++
++      buf[len] = '\0';
++      if (kstrtoul(buf, 0, &diag))
++              return -EINVAL;
++
++      ah->diag = diag;
++      ath9k_hw_update_diag(ah);
++
++      return count;
++}
++
++static const struct file_operations fops_diag = {
++      .read = read_file_diag,
++      .write = write_file_diag,
++      .open = simple_open,
++      .owner = THIS_MODULE,
++      .llseek = default_llseek,
++};
++
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+       struct ath_common *common = ath9k_hw_common(ah);
+@@ -1656,6 +1700,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+       debugfs_create_file("gpio_led", S_IWUSR,
+                          sc->debug.debugfs_phy, sc, &fops_gpio_led);
+ #endif
++      debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++                          sc, &fops_diag);
+       debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
+                           &fops_dma);
+       debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -482,6 +482,12 @@ enum {
+       ATH9K_RESET_COLD,
+ };
++enum {
++      ATH_DIAG_DISABLE_RX,
++      ATH_DIAG_DISABLE_TX,
++      ATH_DIAG_TRIGGER_ERROR,
++};
++
+ struct ath9k_hw_version {
+       u32 magic;
+       u16 devid;
+@@ -762,6 +768,8 @@ struct ath_hw {
+       u32 rfkill_polarity;
+       u32 ah_flags;
++      unsigned long diag;
++
+       bool reset_power_on;
+       bool htc_reset_init;
+@@ -1013,6 +1021,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
+ bool ath9k_hw_check_alive(struct ath_hw *ah);
+ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
++void ath9k_hw_update_diag(struct ath_hw *ah);
+ /* Generic hw timer primitives */
+ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1735,6 +1735,20 @@ fail:
+       return -EINVAL;
+ }
++void ath9k_hw_update_diag(struct ath_hw *ah)
++{
++      if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag))
++              REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++      else
++              REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++
++      if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag))
++              REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++      else
++              REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++}
++EXPORT_SYMBOL(ath9k_hw_update_diag);
++
+ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+                  struct ath9k_hw_cal_data *caldata, bool fastcc)
+ {
+@@ -1940,6 +1954,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+               ar9003_hw_disable_phy_restart(ah);
+       ath9k_hw_apply_gpio_override(ah);
++      ath9k_hw_update_diag(ah);
+       if (AR_SREV_9565(ah) && common->bt_ant_diversity)
+               REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -602,6 +602,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+       ath9k_debug_sync_cause(sc, sync_cause);
+       status &= ah->imask;    /* discard unasked-for bits */
++      if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) {
++              status |= ATH9K_INT_FATAL;
++              clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag);
++      }
++
+       /*
+        * If there are no status bits set, then this interrupt was not
+        * for me (should have been caught above).
diff --git a/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch b/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch
new file mode 100644 (file)
index 0000000..d26a5af
--- /dev/null
@@ -0,0 +1,69 @@
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -34,6 +34,8 @@ struct ath9k_platform_data {
+       bool endian_check;
+       bool is_clk_25mhz;
+       bool tx_gain_buffalo;
++      bool disable_2ghz;
++      bool disable_5ghz;
+       int (*get_mac_revision)(void);
+       int (*external_reset)(void);
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2328,17 +2328,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
+       }
+       eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
+-      if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
+-              ath_err(common,
+-                      "no band has been marked as supported in EEPROM\n");
+-              return -EINVAL;
++
++      if (eeval & AR5416_OPFLAGS_11A) {
++              if (ah->disable_5ghz)
++                      ath_warn(common, "disabling 5GHz band\n");
++              else
++                      pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
+       }
+-      if (eeval & AR5416_OPFLAGS_11A)
+-              pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
++      if (eeval & AR5416_OPFLAGS_11G) {
++              if (ah->disable_2ghz)
++                      ath_warn(common, "disabling 2GHz band\n");
++              else
++                      pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
++      }
+-      if (eeval & AR5416_OPFLAGS_11G)
+-              pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
++      if ((pCap->hw_caps & (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) {
++              ath_err(common, "both bands are disabled\n");
++              return -EINVAL;
++      }
+       if (AR_SREV_9485(ah) ||
+           AR_SREV_9285(ah) ||
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -932,6 +932,8 @@ struct ath_hw {
+       bool is_clk_25mhz;
+       int (*get_mac_revision)(void);
+       int (*external_reset)(void);
++      bool disable_2ghz;
++      bool disable_5ghz;
+       const struct firmware *eeprom_blob;
+ };
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -722,6 +722,8 @@ static int ath9k_init_softc(u16 devid, s
+               ah->is_clk_25mhz = pdata->is_clk_25mhz;
+               ah->get_mac_revision = pdata->get_mac_revision;
+               ah->external_reset = pdata->external_reset;
++              ah->disable_2ghz = pdata->disable_2ghz;
++              ah->disable_5ghz = pdata->disable_5ghz;
+               if (!pdata->endian_check)
+                       ah->ah_flags |= AH_NO_EEP_SWAP;
+       }
diff --git a/package/mac80211/patches/550-ath9k_entropy_from_adc.patch b/package/mac80211/patches/550-ath9k_entropy_from_adc.patch
new file mode 100644 (file)
index 0000000..d126fd4
--- /dev/null
@@ -0,0 +1,200 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -678,6 +678,7 @@ struct ath_spec_scan {
+  * @config_pci_powersave:
+  * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
+  *
++ * @get_adc_entropy: get entropy from the raw ADC I/Q output
+  * @spectral_scan_config: set parameters for spectral scan and enable/disable it
+  * @spectral_scan_trigger: trigger a spectral scan run
+  * @spectral_scan_wait: wait for a spectral scan run to finish
+@@ -701,6 +702,7 @@ struct ath_hw_ops {
+                       struct ath_hw_antcomb_conf *antconf);
+       void (*antdiv_comb_conf_set)(struct ath_hw *ah,
+                       struct ath_hw_antcomb_conf *antconf);
++      void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len);
+       void (*spectral_scan_config)(struct ath_hw *ah,
+                                    struct ath_spec_scan *param);
+       void (*spectral_scan_trigger)(struct ath_hw *ah);
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -1764,6 +1764,26 @@ static void ar9003_hw_tx99_set_txpower(s
+                 ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_14],  0));
+ }
++static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
++{
++      int i, j;
++
++      REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
++      REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
++      REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0);
++
++      memset(buf, 0, len);
++      for (i = 0; i < len; i++) {
++              for (j = 0; j < 4; j++) {
++                      u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
++
++                      buf[i] <<= 2;
++                      buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9);
++                      udelay(1);
++              }
++      }
++}
++
+ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
+ {
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+@@ -1794,6 +1814,7 @@ void ar9003_hw_attach_phy_ops(struct ath
+       priv_ops->set_radar_params = ar9003_hw_set_radar_params;
+       priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
++      ops->get_adc_entropy = ar9003_hw_get_adc_entropy;
+       ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
+       ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
+       ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -846,7 +846,8 @@ static void ath9k_init_txpower_limits(st
+       if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+               ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
+-      ah->curchan = curchan;
++      if (curchan)
++              ah->curchan = curchan;
+ }
+ void ath9k_reload_chainmask_settings(struct ath_softc *sc)
+@@ -980,6 +981,18 @@ static void ath9k_set_hw_capab(struct at
+       SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
+ }
++static void ath_get_initial_entropy(struct ath_softc *sc)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      char buf[256];
++
++      /* reuse last channel initialized by the tx power test */
++      ath9k_hw_reset(ah, ah->curchan, NULL, false);
++
++      ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf));
++      add_device_randomness(buf, sizeof(buf));
++}
++
+ int ath9k_init_device(u16 devid, struct ath_softc *sc,
+                   const struct ath_bus_ops *bus_ops)
+ {
+@@ -1025,6 +1038,8 @@ int ath9k_init_device(u16 devid, struct 
+               ARRAY_SIZE(ath9k_tpt_blink));
+ #endif
++      ath_get_initial_entropy(sc);
++
+       /* Register with mac80211 */
+       error = ieee80211_register_hw(hw);
+       if (error)
+--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
+@@ -95,6 +95,12 @@ static inline void ath9k_hw_tx99_set_txp
+               ath9k_hw_ops(ah)->tx99_set_txpower(ah, power);
+ }
++static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah,
++              u8 *buf, size_t len)
++{
++      ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len);
++}
++
+ #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
+ static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
+--- a/drivers/net/wireless/ath/ath9k/link.c
++++ b/drivers/net/wireless/ath/ath9k/link.c
+@@ -307,6 +307,11 @@ void ath_ani_calibrate(unsigned long dat
+       unsigned int timestamp = jiffies_to_msecs(jiffies);
+       u32 cal_interval, short_cal_interval, long_cal_interval;
+       unsigned long flags;
++      char buf[256];
++
++      /* gather entropy */
++      ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf));
++      add_device_randomness(buf, sizeof(buf));
+       if (ah->caldata && test_bit(NFCAL_INTF, &ah->caldata->cal_flags))
+               long_cal_interval = ATH_LONG_CALINTERVAL_INT;
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -1233,9 +1233,30 @@ static void ar5008_hw_set_radar_conf(str
+       conf->radar_inband = 8;
+ }
++static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
++{
++      int i, j;
++
++      REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
++      REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
++      REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0);
++
++      memset(buf, 0, len);
++      for (i = 0; i < len; i++) {
++              for (j = 0; j < 4; j++) {
++                      u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
++
++                      buf[i] <<= 2;
++                      buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8);
++                      udelay(1);
++              }
++      }
++}
++
+ int ar5008_hw_attach_phy_ops(struct ath_hw *ah)
+ {
+       struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
++      struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+       static const u32 ar5416_cca_regs[6] = {
+               AR_PHY_CCA,
+               AR_PHY_CH1_CCA,
+@@ -1250,6 +1271,8 @@ int ar5008_hw_attach_phy_ops(struct ath_
+       if (ret)
+           return ret;
++      ops->get_adc_entropy = ar5008_hw_get_adc_entropy;
++
+       priv_ops->rf_set_freq = ar5008_hw_set_channel;
+       priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
+--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+@@ -20,6 +20,12 @@
+ #define PHY_AGC_CLR             0x10000000
+ #define RFSILENT_BB             0x00002000
++#define AR_PHY_TEST_BBB_OBS_SEL       0x780000
++#define AR_PHY_TEST_BBB_OBS_SEL_S     19
++
++#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23
++#define AR_PHY_TEST_RX_OBS_SEL_BIT5   (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S)
++
+ #define AR_PHY_TURBO                0x9804
+ #define AR_PHY_FC_TURBO_MODE        0x00000001
+ #define AR_PHY_FC_TURBO_SHORT       0x00000002
+@@ -36,6 +42,9 @@
+ #define AR_PHY_TEST2                  0x9808
++#define AR_PHY_TEST2_RX_OBS_SEL        0x3C00
++#define AR_PHY_TEST2_RX_OBS_SEL_S      10
++
+ #define AR_PHY_TIMING2           0x9810
+ #define AR_PHY_TIMING3           0x9814
+ #define AR_PHY_TIMING3_DSC_MAN   0xFFFE0000
+@@ -390,6 +399,8 @@
+ #define AR_PHY_RFBUS_GRANT       0x9C20
+ #define AR_PHY_RFBUS_GRANT_EN    0x00000001
++#define AR_PHY_TST_ADC      0x9C24
++
+ #define AR_PHY_CHAN_INFO_GAIN_DIFF             0x9CF4
+ #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
diff --git a/package/mac80211/patches/550-ath9k_reduce_ani_interval.patch b/package/mac80211/patches/550-ath9k_reduce_ani_interval.patch
deleted file mode 100644 (file)
index 7c24f46..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ani.h
-+++ b/drivers/net/wireless/ath/ath9k/ani.h
-@@ -38,7 +38,7 @@
- #define ATH9K_ANI_PERIOD                  300
- /* in ms */
--#define ATH9K_ANI_POLLINTERVAL            1000
-+#define ATH9K_ANI_POLLINTERVAL            300
- #define ATH9K_SIG_FIRSTEP_SETTING_MIN     0
- #define ATH9K_SIG_FIRSTEP_SETTING_MAX     20
diff --git a/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch b/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch
new file mode 100644 (file)
index 0000000..ffffe0c
--- /dev/null
@@ -0,0 +1,33 @@
+From c997a1da25fe7c717ed099888b8eb35d4e139e70 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Sun, 8 Dec 2013 08:52:52 +0100
+Subject: [PATCH] ath9k: support only one P2P interface
+
+Preparation for adding P2P powersave and multi-channel support.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+ drivers/net/wireless/ath/ath9k/init.c | 4 ++--
+  1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -863,15 +863,15 @@ void ath9k_reload_chainmask_settings(str
+ static const struct ieee80211_iface_limit if_limits[] = {
+       { .max = 2048,  .types = BIT(NL80211_IFTYPE_STATION) |
+-                               BIT(NL80211_IFTYPE_P2P_CLIENT) |
+                                BIT(NL80211_IFTYPE_WDS) },
+       { .max = 8,     .types =
+ #ifdef CPTCFG_MAC80211_MESH
+                                BIT(NL80211_IFTYPE_MESH_POINT) |
+ #endif
+-                               BIT(NL80211_IFTYPE_AP) |
+-                               BIT(NL80211_IFTYPE_P2P_GO) },
++                               BIT(NL80211_IFTYPE_AP) },
+       { .max = 1,     .types = BIT(NL80211_IFTYPE_ADHOC) },
++      { .max = 1,     .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
++                               BIT(NL80211_IFTYPE_P2P_GO) },
+ };
+ static const struct ieee80211_iface_limit if_dfs_limits[] = {
diff --git a/package/mac80211/patches/552-ath9k_p2p_ps_support.patch b/package/mac80211/patches/552-ath9k_p2p_ps_support.patch
new file mode 100644 (file)
index 0000000..4a61db3
--- /dev/null
@@ -0,0 +1,247 @@
+From 6744d0a7ea037c7d65e13ca906da93009b241d00 Mon Sep 17 00:00:00 2001
+From: Felix Fietkau <nbd@openwrt.org>
+Date: Tue, 11 Feb 2014 11:16:24 +0100
+Subject: [PATCH] ath9k: implement p2p client powersave support
+
+Use generic TSF timers to trigger powersave state changes based
+information from the P2P NoA attribute.
+Opportunistic Powersave is not handled, because the driver does not
+support powersave at the moment.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h |  12 ++++
+ drivers/net/wireless/ath/ath9k/init.c  |   6 ++
+ drivers/net/wireless/ath/ath9k/main.c  | 104 +++++++++++++++++++++++++++++++++
+ drivers/net/wireless/ath/ath9k/recv.c  |   3 +
+ 4 files changed, 125 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -261,6 +261,8 @@ static bool ath_complete_reset(struct at
+       sc->gtt_cnt = 0;
+       ieee80211_wake_queues(sc->hw);
++      ath9k_p2p_ps_timer(sc);
++
+       return true;
+ }
+@@ -1126,6 +1128,8 @@ static int ath9k_add_interface(struct ie
+       if (ath9k_uses_beacons(vif->type))
+               ath9k_beacon_assign_slot(sc, vif);
++      avp->vif = vif;
++
+       an->sc = sc;
+       an->sta = NULL;
+       an->vif = vif;
+@@ -1170,6 +1174,29 @@ static int ath9k_change_interface(struct
+       return 0;
+ }
++static void
++ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp)
++{
++      struct ath_hw *ah = sc->sc_ah;
++      s32 tsf, target_tsf;
++
++      if (!avp || !avp->noa.has_next_tsf)
++              return;
++
++      ath9k_hw_gen_timer_stop(ah, sc->p2p_ps_timer);
++
++      tsf = ath9k_hw_gettsf32(sc->sc_ah);
++
++      target_tsf = avp->noa.next_tsf;
++      if (!avp->noa.absent)
++              target_tsf -= ATH_P2P_PS_STOP_TIME;
++
++      if (target_tsf - tsf < ATH_P2P_PS_STOP_TIME)
++              target_tsf = tsf + ATH_P2P_PS_STOP_TIME;
++
++      ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, (u32) target_tsf, 1000000);
++}
++
+ static void ath9k_remove_interface(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif)
+ {
+@@ -1181,6 +1208,13 @@ static void ath9k_remove_interface(struc
+       mutex_lock(&sc->mutex);
++      spin_lock_bh(&sc->sc_pcu_lock);
++      if (avp == sc->p2p_ps_vif) {
++              sc->p2p_ps_vif = NULL;
++              ath9k_update_p2p_ps_timer(sc, NULL);
++      }
++      spin_unlock_bh(&sc->sc_pcu_lock);
++
+       sc->nvifs--;
+       sc->tx99_vif = NULL;
+@@ -1649,6 +1683,70 @@ static void ath9k_bss_assoc_iter(void *d
+               ath9k_set_assoc_state(sc, vif);
+ }
++void ath9k_p2p_ps_timer(void *priv)
++{
++      struct ath_softc *sc = priv;
++      struct ath_vif *avp = sc->p2p_ps_vif;
++      struct ieee80211_vif *vif;
++      struct ieee80211_sta *sta;
++      struct ath_node *an;
++      u32 tsf;
++
++      if (!avp)
++              return;
++
++      tsf = ath9k_hw_gettsf32(sc->sc_ah);
++      if (!avp->noa.absent)
++              tsf += ATH_P2P_PS_STOP_TIME;
++
++      if (!avp->noa.has_next_tsf ||
++          avp->noa.next_tsf - tsf > BIT(31))
++              ieee80211_update_p2p_noa(&avp->noa, tsf);
++
++      ath9k_update_p2p_ps_timer(sc, avp);
++
++      rcu_read_lock();
++
++      vif = avp->vif;
++      sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
++      if (!sta)
++              goto out;
++
++      an = (void *) sta->drv_priv;
++      if (an->sleeping == !!avp->noa.absent)
++              goto out;
++
++      an->sleeping = avp->noa.absent;
++      if (an->sleeping)
++              ath_tx_aggr_sleep(sta, sc, an);
++      else
++              ath_tx_aggr_wakeup(sc, an);
++
++out:
++      rcu_read_unlock();
++}
++
++void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
++{
++      struct ath_vif *avp = (void *)vif->drv_priv;
++      u32 tsf;
++
++      if (!sc->p2p_ps_timer)
++              return;
++
++      if (vif->type != NL80211_IFTYPE_STATION || !vif->p2p)
++              return;
++
++      sc->p2p_ps_vif = avp;
++
++      if (sc->ps_flags & PS_BEACON_SYNC)
++              return;
++
++      tsf = ath9k_hw_gettsf32(sc->sc_ah);
++      ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
++      ath9k_update_p2p_ps_timer(sc, avp);
++}
++
+ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif,
+                                  struct ieee80211_bss_conf *bss_conf,
+@@ -1723,6 +1821,12 @@ static void ath9k_bss_info_changed(struc
+               }
+       }
++      if (changed & BSS_CHANGED_P2P_PS) {
++              spin_lock_bh(&sc->sc_pcu_lock);
++              ath9k_update_p2p_ps(sc, vif);
++              spin_unlock_bh(&sc->sc_pcu_lock);
++      }
++
+       if (changed & CHECK_ANI)
+               ath_check_ani(sc);
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -115,6 +115,9 @@ int ath_descdma_setup(struct ath_softc *
+ #define ATH_TXFIFO_DEPTH           8
+ #define ATH_TX_ERROR               0x01
++/* Stop tx traffic 1ms before the GO goes away */
++#define ATH_P2P_PS_STOP_TIME       1000
++
+ #define IEEE80211_SEQ_SEQ_SHIFT    4
+ #define IEEE80211_SEQ_MAX          4096
+ #define IEEE80211_WEP_IVLEN        3
+@@ -363,11 +366,15 @@ void ath9k_release_buffered_frames(struc
+ /********/
+ struct ath_vif {
++      struct ieee80211_vif *vif;
+       struct ath_node mcast_node;
+       int av_bslot;
+       bool primary_sta_vif;
+       __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
+       struct ath_buf *av_bcbuf;
++
++      /* P2P Client */
++      struct ieee80211_noa_data noa;
+ };
+ struct ath9k_vif_iter_data {
+@@ -472,6 +479,8 @@ int ath_update_survey_stats(struct ath_s
+ void ath_update_survey_nf(struct ath_softc *sc, int channel);
+ void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
+ void ath_ps_full_sleep(unsigned long data);
++void ath9k_p2p_ps_timer(void *priv);
++void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif);
+ /**********/
+ /* BTCOEX */
+@@ -741,6 +750,9 @@ struct ath_softc {
+       struct completion paprd_complete;
+       wait_queue_head_t tx_wait;
++      struct ath_gen_timer *p2p_ps_timer;
++      struct ath_vif *p2p_ps_vif;
++
+       unsigned long sc_flags;
+       unsigned long driver_data;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -797,6 +797,9 @@ static int ath9k_init_softc(u16 devid, s
+       if (ret)
+               goto err_btcoex;
++      sc->p2p_ps_timer = ath_gen_timer_alloc(sc->sc_ah, ath9k_p2p_ps_timer,
++              NULL, sc, AR_FIRST_NDP_TIMER);
++
+       ath9k_cmn_init_crypto(sc->sc_ah);
+       ath9k_init_misc(sc);
+       ath_fill_led_pin(sc);
+@@ -1082,6 +1085,9 @@ static void ath9k_deinit_softc(struct at
+ {
+       int i = 0;
++      if (sc->p2p_ps_timer)
++              ath_gen_timer_free(sc->sc_ah, sc->p2p_ps_timer);
++
+       ath9k_deinit_btcoex(sc);
+       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+--- a/drivers/net/wireless/ath/ath9k/recv.c
++++ b/drivers/net/wireless/ath/ath9k/recv.c
+@@ -539,6 +539,9 @@ static void ath_rx_ps_beacon(struct ath_
+               ath_dbg(common, PS,
+                       "Reconfigure beacon timers based on synchronized timestamp\n");
+               ath9k_set_beacon(sc);
++
++              if (sc->p2p_ps_vif)
++                      ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif);
+       }
+       if (ath_beacon_dtim_pending_cab(skb)) {
diff --git a/package/mac80211/patches/552-ath9k_rx_dma_stop_check.patch b/package/mac80211/patches/552-ath9k_rx_dma_stop_check.patch
deleted file mode 100644 (file)
index 5d063c7..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -705,7 +705,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
- {
- #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
-       struct ath_common *common = ath9k_hw_common(ah);
--      u32 mac_status, last_mac_status = 0;
-+      u32 mac_status = 0, last_mac_status = 0;
-       int i;
-       /* Enable access to the DMA observation bus */
-@@ -735,6 +735,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw 
-       }
-       if (i == 0) {
-+              if (!AR_SREV_9300_20_OR_LATER(ah) &&
-+                  (mac_status & 0x700) == 0) {
-+                      /*
-+                       * DMA is idle but the MAC is still stuck
-+                       * processing events
-+                       */
-+                      *reset = true;
-+                      return true;
-+              }
-+
-               ath_err(common,
-                       "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
-                       AH_RX_STOP_DMA_TIMEOUT / 1000,
diff --git a/package/mac80211/patches/553-ath9k_debugfs_diag.patch b/package/mac80211/patches/553-ath9k_debugfs_diag.patch
deleted file mode 100644 (file)
index 7230d32..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1881,6 +1881,50 @@ static const struct file_operations fops
- #endif
-+static ssize_t read_file_diag(struct file *file, char __user *user_buf,
-+                           size_t count, loff_t *ppos)
-+{
-+      struct ath_softc *sc = file->private_data;
-+      struct ath_hw *ah = sc->sc_ah;
-+      char buf[32];
-+      unsigned int len;
-+
-+      len = sprintf(buf, "0x%08lx\n", ah->diag);
-+      return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-+}
-+
-+static ssize_t write_file_diag(struct file *file, const char __user *user_buf,
-+                           size_t count, loff_t *ppos)
-+{
-+      struct ath_softc *sc = file->private_data;
-+      struct ath_hw *ah = sc->sc_ah;
-+      unsigned long diag;
-+      char buf[32];
-+      ssize_t len;
-+
-+      len = min(count, sizeof(buf) - 1);
-+      if (copy_from_user(buf, user_buf, len))
-+              return -EFAULT;
-+
-+      buf[len] = '\0';
-+      if (kstrtoul(buf, 0, &diag))
-+              return -EINVAL;
-+
-+      ah->diag = diag;
-+      ath9k_hw_update_diag(ah);
-+
-+      return count;
-+}
-+
-+static const struct file_operations fops_diag = {
-+      .read = read_file_diag,
-+      .write = write_file_diag,
-+      .open = simple_open,
-+      .owner = THIS_MODULE,
-+      .llseek = default_llseek,
-+};
-+
-+
- int ath9k_init_debug(struct ath_hw *ah)
- {
-       struct ath_common *common = ath9k_hw_common(ah);
-@@ -1906,6 +1950,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-       debugfs_create_file("gpio_led", S_IWUSR,
-                          sc->debug.debugfs_phy, sc, &fops_gpio_led);
- #endif
-+      debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-+                          sc, &fops_diag);
-       debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
-                           &fops_dma);
-       debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -499,6 +499,12 @@ enum {
-       ATH9K_RESET_COLD,
- };
-+enum {
-+      ATH_DIAG_DISABLE_RX,
-+      ATH_DIAG_DISABLE_TX,
-+      ATH_DIAG_TRIGGER_ERROR,
-+};
-+
- struct ath9k_hw_version {
-       u32 magic;
-       u16 devid;
-@@ -777,6 +783,8 @@ struct ath_hw {
-       u32 rfkill_polarity;
-       u32 ah_flags;
-+      unsigned long diag;
-+
-       bool reset_power_on;
-       bool htc_reset_init;
-@@ -1027,6 +1035,7 @@ void ath9k_hw_set_sta_beacon_timers(stru
- bool ath9k_hw_check_alive(struct ath_hw *ah);
- bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
-+void ath9k_hw_update_diag(struct ath_hw *ah);
- #ifdef CPTCFG_ATH9K_DEBUGFS
- void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause);
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1853,6 +1853,20 @@ fail:
-       return -EINVAL;
- }
-+void ath9k_hw_update_diag(struct ath_hw *ah)
-+{
-+      if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag))
-+              REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
-+      else
-+              REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
-+
-+      if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag))
-+              REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
-+      else
-+              REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
-+}
-+EXPORT_SYMBOL(ath9k_hw_update_diag);
-+
- int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
-                  struct ath9k_hw_cal_data *caldata, bool fastcc)
- {
-@@ -2055,6 +2069,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-       }
-       ath9k_hw_apply_gpio_override(ah);
-+      ath9k_hw_update_diag(ah);
-       if (AR_SREV_9565(ah) && ah->shared_chain_lnadiv)
-               REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -472,6 +472,11 @@ irqreturn_t ath_isr(int irq, void *dev)
-       ath9k_hw_getisr(ah, &status);   /* NB: clears ISR too */
-       status &= ah->imask;    /* discard unasked-for bits */
-+      if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) {
-+              status |= ATH9K_INT_FATAL;
-+              clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag);
-+      }
-+
-       /*
-        * If there are no status bits set, then this interrupt was not
-        * for me (should have been caught above).
diff --git a/package/mac80211/patches/554-ath9k_ani_mrc_fix.patch b/package/mac80211/patches/554-ath9k_ani_mrc_fix.patch
deleted file mode 100644 (file)
index 47df721..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -1173,6 +1173,10 @@ skip_ws_det:
-                * is_on == 0 means MRC CCK is OFF (more noise imm)
-                */
-               bool is_on = param ? 1 : 0;
-+
-+              if (ah->caps.rx_chainmask == 1)
-+                      break;
-+
-               REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
-                             AR_PHY_MRC_CCK_ENABLE, is_on);
-               REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL,
diff --git a/package/mac80211/patches/555-ath9k-allow-to-disable-bands-via-platform-data.patch b/package/mac80211/patches/555-ath9k-allow-to-disable-bands-via-platform-data.patch
deleted file mode 100644 (file)
index 584a7d7..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
---- a/include/linux/ath9k_platform.h
-+++ b/include/linux/ath9k_platform.h
-@@ -33,6 +33,9 @@ struct ath9k_platform_data {
-       bool endian_check;
-       bool is_clk_25mhz;
-+      bool disable_2ghz;
-+      bool disable_5ghz;
-+
-       int (*get_mac_revision)(void);
-       int (*external_reset)(void);
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2448,17 +2448,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw
-       }
-       eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
--      if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
--              ath_err(common,
--                      "no band has been marked as supported in EEPROM\n");
--              return -EINVAL;
-+
-+      if (eeval & AR5416_OPFLAGS_11A) {
-+              if (ah->disable_5ghz)
-+                      ath_warn(common, "disabling 5GHz band\n");
-+              else
-+                      pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
-       }
--      if (eeval & AR5416_OPFLAGS_11A)
--              pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
-+      if (eeval & AR5416_OPFLAGS_11G) {
-+              if (ah->disable_2ghz)
-+                      ath_warn(common, "disabling 2GHz band\n");
-+              else
-+                      pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
-+      }
--      if (eeval & AR5416_OPFLAGS_11G)
--              pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
-+      if ((pCap->hw_caps & (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) {
-+              ath_err(common, "both bands are disabled\n");
-+              return -EINVAL;
-+      }
-       if (AR_SREV_9485(ah) ||
-           AR_SREV_9285(ah) ||
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -947,6 +947,8 @@ struct ath_hw {
-       bool is_clk_25mhz;
-       int (*get_mac_revision)(void);
-       int (*external_reset)(void);
-+      bool disable_2ghz;
-+      bool disable_5ghz;
-       const struct firmware *eeprom_blob;
- };
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -613,6 +613,8 @@ static int ath9k_init_softc(u16 devid, s
-               ah->is_clk_25mhz = pdata->is_clk_25mhz;
-               ah->get_mac_revision = pdata->get_mac_revision;
-               ah->external_reset = pdata->external_reset;
-+              ah->disable_2ghz = pdata->disable_2ghz;
-+              ah->disable_5ghz = pdata->disable_5ghz;
-               if (!pdata->endian_check)
-                       ah->ah_flags |= AH_NO_EEP_SWAP;
-       }
diff --git a/package/mac80211/patches/556-ath9k_fix_rx_race.patch b/package/mac80211/patches/556-ath9k_fix_rx_race.patch
deleted file mode 100644 (file)
index 69030d2..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -79,10 +79,6 @@ struct ath_config {
-                      sizeof(struct ath_buf_state));           \
-       } while (0)
--#define ATH_RXBUF_RESET(_bf) do {             \
--              (_bf)->bf_stale = false;        \
--      } while (0)
--
- /**
-  * enum buffer_type - Buffer type flags
-  *
-@@ -317,6 +313,7 @@ struct ath_rx {
-       struct ath_descdma rxdma;
-       struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
-+      struct ath_buf *buf_hold;
-       struct sk_buff *frag;
-       u32 ampdu_ref;
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -42,8 +42,6 @@ static void ath_rx_buf_link(struct ath_s
-       struct ath_desc *ds;
-       struct sk_buff *skb;
--      ATH_RXBUF_RESET(bf);
--
-       ds = bf->bf_desc;
-       ds->ds_link = 0; /* link to null */
-       ds->ds_data = bf->bf_buf_addr;
-@@ -70,6 +68,14 @@ static void ath_rx_buf_link(struct ath_s
-       sc->rx.rxlink = &ds->ds_link;
- }
-+static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf)
-+{
-+      if (sc->rx.buf_hold)
-+              ath_rx_buf_link(sc, sc->rx.buf_hold);
-+
-+      sc->rx.buf_hold = bf;
-+}
-+
- static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
- {
-       /* XXX block beacon interrupts */
-@@ -117,7 +123,6 @@ static bool ath_rx_edma_buf_link(struct 
-       skb = bf->bf_mpdu;
--      ATH_RXBUF_RESET(bf);
-       memset(skb->data, 0, ah->caps.rx_status_len);
-       dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
-                               ah->caps.rx_status_len, DMA_TO_DEVICE);
-@@ -432,6 +437,7 @@ int ath_startrecv(struct ath_softc *sc)
-       if (list_empty(&sc->rx.rxbuf))
-               goto start_recv;
-+      sc->rx.buf_hold = NULL;
-       sc->rx.rxlink = NULL;
-       list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
-               ath_rx_buf_link(sc, bf);
-@@ -677,6 +683,9 @@ static struct ath_buf *ath_get_next_rx_b
-       }
-       bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
-+      if (bf == sc->rx.buf_hold)
-+              return NULL;
-+
-       ds = bf->bf_desc;
-       /*
-@@ -1391,7 +1400,7 @@ requeue:
-               if (edma) {
-                       ath_rx_edma_buf_link(sc, qtype);
-               } else {
--                      ath_rx_buf_link(sc, bf);
-+                      ath_rx_buf_relink(sc, bf);
-                       ath9k_hw_rxena(ah);
-               }
-       } while (1);
diff --git a/package/mac80211/patches/560-ath9k_tx_queueing_rework.patch b/package/mac80211/patches/560-ath9k_tx_queueing_rework.patch
deleted file mode 100644 (file)
index 47ecd74..0000000
+++ /dev/null
@@ -1,546 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -133,7 +133,6 @@ int ath_descdma_setup(struct ath_softc *
- #define ATH_AGGR_ENCRYPTDELIM      10
- /* minimum h/w qdepth to be sustained to maximize aggregation */
- #define ATH_AGGR_MIN_QDEPTH        2
--#define ATH_AMPDU_SUBFRAME_DEFAULT 32
- #define IEEE80211_SEQ_SEQ_SHIFT    4
- #define IEEE80211_SEQ_MAX          4096
-@@ -208,8 +207,9 @@ struct ath_frame_info {
-       int framelen;
-       enum ath9k_key_type keytype;
-       u8 keyix;
--      u8 retries;
-       u8 rtscts_rate;
-+      u8 retries : 7;
-+      u8 baw_tracked : 1;
- };
- struct ath_buf_state {
-@@ -237,6 +237,7 @@ struct ath_buf {
- struct ath_atx_tid {
-       struct list_head list;
-       struct sk_buff_head buf_q;
-+      struct sk_buff_head retry_q;
-       struct ath_node *an;
-       struct ath_atx_ac *ac;
-       unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)];
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -607,6 +607,28 @@ static ssize_t read_file_xmit(struct fil
-       return retval;
- }
-+static ssize_t print_queue(struct ath_softc *sc, struct ath_txq *txq,
-+                         char *buf, ssize_t size)
-+{
-+      ssize_t len = 0;
-+
-+      ath_txq_lock(sc, txq);
-+
-+      len += snprintf(buf + len, size - len, "%s: %d ",
-+                      "qnum", txq->axq_qnum);
-+      len += snprintf(buf + len, size - len, "%s: %2d ",
-+                      "qdepth", txq->axq_depth);
-+      len += snprintf(buf + len, size - len, "%s: %2d ",
-+                      "ampdu-depth", txq->axq_ampdu_depth);
-+      len += snprintf(buf + len, size - len, "%s: %3d ",
-+                      "pending", txq->pending_frames);
-+      len += snprintf(buf + len, size - len, "%s: %d\n",
-+                      "stopped", txq->stopped);
-+
-+      ath_txq_unlock(sc, txq);
-+      return len;
-+}
-+
- static ssize_t read_file_queues(struct file *file, char __user *user_buf,
-                               size_t count, loff_t *ppos)
- {
-@@ -624,24 +646,13 @@ static ssize_t read_file_queues(struct f
-       for (i = 0; i < IEEE80211_NUM_ACS; i++) {
-               txq = sc->tx.txq_map[i];
--              len += snprintf(buf + len, size - len, "(%s): ", qname[i]);
--
--              ath_txq_lock(sc, txq);
--
--              len += snprintf(buf + len, size - len, "%s: %d ",
--                              "qnum", txq->axq_qnum);
--              len += snprintf(buf + len, size - len, "%s: %2d ",
--                              "qdepth", txq->axq_depth);
--              len += snprintf(buf + len, size - len, "%s: %2d ",
--                              "ampdu-depth", txq->axq_ampdu_depth);
--              len += snprintf(buf + len, size - len, "%s: %3d ",
--                              "pending", txq->pending_frames);
--              len += snprintf(buf + len, size - len, "%s: %d\n",
--                              "stopped", txq->stopped);
--
--              ath_txq_unlock(sc, txq);
-+              len += snprintf(buf + len, size - len, "(%s):  ", qname[i]);
-+              len += print_queue(sc, txq, buf + len, size - len);
-       }
-+      len += snprintf(buf + len, size - len, "(CAB): ");
-+      len += print_queue(sc, sc->beacon.cabq, buf + len, size - len);
-+
-       if (len > size)
-               len = size;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1402,9 +1402,6 @@ static void ath9k_sta_notify(struct ieee
-       struct ath_softc *sc = hw->priv;
-       struct ath_node *an = (struct ath_node *) sta->drv_priv;
--      if (!sta->ht_cap.ht_supported)
--              return;
--
-       switch (cmd) {
-       case STA_NOTIFY_SLEEP:
-               an->sleeping = true;
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -168,6 +168,36 @@ static void ath_txq_skb_done(struct ath_
-       }
- }
-+static struct ath_atx_tid *
-+ath_get_skb_tid(struct ath_softc *sc, struct ath_node *an, struct sk_buff *skb)
-+{
-+      struct ieee80211_hdr *hdr;
-+      u8 tidno = 0;
-+
-+      hdr = (struct ieee80211_hdr *) skb->data;
-+      if (ieee80211_is_data_qos(hdr->frame_control))
-+              tidno = ieee80211_get_qos_ctl(hdr)[0];
-+
-+      tidno &= IEEE80211_QOS_CTL_TID_MASK;
-+      return ATH_AN_2_TID(an, tidno);
-+}
-+
-+static bool ath_tid_has_buffered(struct ath_atx_tid *tid)
-+{
-+      return !skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q);
-+}
-+
-+static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid)
-+{
-+      struct sk_buff *skb;
-+
-+      skb = __skb_dequeue(&tid->retry_q);
-+      if (!skb)
-+              skb = __skb_dequeue(&tid->buf_q);
-+
-+      return skb;
-+}
-+
- static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
- {
-       struct ath_txq *txq = tid->ac->txq;
-@@ -182,7 +212,7 @@ static void ath_tx_flush_tid(struct ath_
-       memset(&ts, 0, sizeof(ts));
--      while ((skb = __skb_dequeue(&tid->buf_q))) {
-+      while ((skb = ath_tid_dequeue(tid))) {
-               fi = get_frame_info(skb);
-               bf = fi->bf;
-@@ -195,7 +225,7 @@ static void ath_tx_flush_tid(struct ath_
-                       }
-               }
--              if (fi->retries) {
-+              if (fi->baw_tracked) {
-                       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);
-@@ -232,13 +262,16 @@ static void ath_tx_update_baw(struct ath
- }
- static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
--                           u16 seqno)
-+                           struct ath_buf *bf)
- {
-+      struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
-+      u16 seqno = bf->bf_state.seqno;
-       int index, cindex;
-       index  = ATH_BA_INDEX(tid->seq_start, seqno);
-       cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
-       __set_bit(cindex, tid->tx_buf);
-+      fi->baw_tracked = 1;
-       if (index >= ((tid->baw_tail - tid->baw_head) &
-               (ATH_TID_MAX_BUFS - 1))) {
-@@ -266,7 +299,7 @@ static void ath_tid_drain(struct ath_sof
-       memset(&ts, 0, sizeof(ts));
-       INIT_LIST_HEAD(&bf_head);
--      while ((skb = __skb_dequeue(&tid->buf_q))) {
-+      while ((skb = ath_tid_dequeue(tid))) {
-               fi = get_frame_info(skb);
-               bf = fi->bf;
-@@ -403,7 +436,6 @@ static void ath_tx_complete_aggr(struct 
-       struct ieee80211_tx_rate rates[4];
-       struct ath_frame_info *fi;
-       int nframes;
--      u8 tidno;
-       bool flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
-       int i, retries;
-       int bar_index = -1;
-@@ -440,8 +472,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);
-+      tid = ath_get_skb_tid(sc, an, skb);
-       seq_first = tid->seq_start;
-       isba = ts->ts_flags & ATH9K_TX_BA;
-@@ -453,7 +484,7 @@ static void ath_tx_complete_aggr(struct 
-        * Only BlockAcks have a TID and therefore normal Acks cannot be
-        * checked
-        */
--      if (isba && tidno != ts->tid)
-+      if (isba && tid->tidno != ts->tid)
-               txok = false;
-       isaggr = bf_isaggr(bf);
-@@ -489,7 +520,8 @@ static void ath_tx_complete_aggr(struct 
-               tx_info = IEEE80211_SKB_CB(skb);
-               fi = get_frame_info(skb);
--              if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) {
-+              if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno) ||
-+                  !tid->active) {
-                       /*
-                        * Outside of the current BlockAck window,
-                        * maybe part of a previous session
-@@ -583,7 +615,7 @@ static void ath_tx_complete_aggr(struct 
-               if (an->sleeping)
-                       ieee80211_sta_set_buffered(sta, tid->tidno, true);
--              skb_queue_splice(&bf_pending, &tid->buf_q);
-+              skb_queue_splice_tail(&bf_pending, &tid->retry_q);
-               if (!an->sleeping) {
-                       ath_tx_queue_tid(txq, tid);
-@@ -641,7 +673,7 @@ static void ath_tx_process_buffer(struct
-       } else
-               ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok);
--      if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !flush)
-+      if (!flush)
-               ath_txq_schedule(sc, txq);
- }
-@@ -815,15 +847,20 @@ static int ath_compute_num_delims(struct
- static struct ath_buf *
- ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
--                      struct ath_atx_tid *tid)
-+                      struct ath_atx_tid *tid, struct sk_buff_head **q)
- {
-+      struct ieee80211_tx_info *tx_info;
-       struct ath_frame_info *fi;
-       struct sk_buff *skb;
-       struct ath_buf *bf;
-       u16 seqno;
-       while (1) {
--              skb = skb_peek(&tid->buf_q);
-+              *q = &tid->retry_q;
-+              if (skb_queue_empty(*q))
-+                      *q = &tid->buf_q;
-+
-+              skb = skb_peek(*q);
-               if (!skb)
-                       break;
-@@ -833,12 +870,22 @@ ath_tx_get_tid_subframe(struct ath_softc
-                       bf = ath_tx_setup_buffer(sc, txq, tid, skb);
-               if (!bf) {
--                      __skb_unlink(skb, &tid->buf_q);
-+                      __skb_unlink(skb, *q);
-                       ath_txq_skb_done(sc, txq, skb);
-                       ieee80211_free_txskb(sc->hw, skb);
-                       continue;
-               }
-+              bf->bf_next = NULL;
-+              bf->bf_lastbf = bf;
-+
-+              tx_info = IEEE80211_SKB_CB(skb);
-+              tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
-+              if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
-+                      bf->bf_state.bf_type = 0;
-+                      return bf;
-+              }
-+
-               bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR;
-               seqno = bf->bf_state.seqno;
-@@ -852,14 +899,12 @@ ath_tx_get_tid_subframe(struct ath_softc
-                       INIT_LIST_HEAD(&bf_head);
-                       list_add(&bf->list, &bf_head);
--                      __skb_unlink(skb, &tid->buf_q);
-+                      __skb_unlink(skb, *q);
-                       ath_tx_update_baw(sc, tid, seqno);
-                       ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
-                       continue;
-               }
--              bf->bf_next = NULL;
--              bf->bf_lastbf = bf;
-               return bf;
-       }
-@@ -874,16 +919,17 @@ static enum ATH_AGGR_STATUS ath_tx_form_
- {
- #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4)
-       struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
--      int rl = 0, nframes = 0, ndelim, prev_al = 0;
-+      int nframes = 0, ndelim;
-       u16 aggr_limit = 0, al = 0, bpad = 0,
--              al_delta, h_baw = tid->baw_size / 2;
-+          al_delta, h_baw = tid->baw_size / 2;
-       enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
-       struct ieee80211_tx_info *tx_info;
-       struct ath_frame_info *fi;
-       struct sk_buff *skb;
-+      struct sk_buff_head *tid_q;
-       do {
--              bf = ath_tx_get_tid_subframe(sc, txq, tid);
-+              bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
-               if (!bf) {
-                       status = ATH_AGGR_BAW_CLOSED;
-                       break;
-@@ -892,33 +938,24 @@ static enum ATH_AGGR_STATUS ath_tx_form_
-               skb = bf->bf_mpdu;
-               fi = get_frame_info(skb);
--              if (!bf_first)
-+              if (!bf_first) {
-                       bf_first = bf;
--
--              if (!rl) {
-                       ath_set_rates(tid->an->vif, tid->an->sta, bf);
-                       aggr_limit = ath_lookup_rate(sc, bf, tid);
--                      rl = 1;
-               }
-               /* do not exceed aggregation limit */
-               al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;
-+              if (nframes) {
-+                      if (aggr_limit < al + bpad + al_delta ||
-+                          ath_lookup_legacy(bf) || nframes >= h_baw) {
-+                              status = ATH_AGGR_LIMITED;
-+                              break;
-+                      }
--              if (nframes &&
--                  ((aggr_limit < (al + bpad + al_delta + prev_al)) ||
--                   ath_lookup_legacy(bf))) {
--                      status = ATH_AGGR_LIMITED;
--                      break;
--              }
--
--              tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
--              if (nframes && (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
--                      break;
--
--              /* do not exceed subframe limit */
--              if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) {
--                      status = ATH_AGGR_LIMITED;
--                      break;
-+                      tx_info = IEEE80211_SKB_CB(bf->bf_mpdu);
-+                      if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
-+                              break;
-               }
-               /* add padding for previous frame to aggregation length */
-@@ -936,18 +973,18 @@ static enum ATH_AGGR_STATUS ath_tx_form_
-               bf->bf_next = NULL;
-               /* link buffers of this frame to the aggregate */
--              if (!fi->retries)
--                      ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
-+              if (!fi->baw_tracked)
-+                      ath_tx_addto_baw(sc, tid, bf);
-               bf->bf_state.ndelim = ndelim;
--              __skb_unlink(skb, &tid->buf_q);
-+              __skb_unlink(skb, tid_q);
-               list_add_tail(&bf->list, bf_q);
-               if (bf_prev)
-                       bf_prev->bf_next = bf;
-               bf_prev = bf;
--      } while (!skb_queue_empty(&tid->buf_q));
-+      } while (ath_tid_has_buffered(tid));
-       *aggr_len = al;
-@@ -1222,7 +1259,7 @@ static void ath_tx_sched_aggr(struct ath
-       int aggr_len;
-       do {
--              if (skb_queue_empty(&tid->buf_q))
-+              if (!ath_tid_has_buffered(tid))
-                       return;
-               INIT_LIST_HEAD(&bf_q);
-@@ -1301,7 +1338,7 @@ void ath_tx_aggr_stop(struct ath_softc *
-       ath_txq_lock(sc, txq);
-       txtid->active = false;
--      txtid->paused = true;
-+      txtid->paused = false;
-       ath_tx_flush_tid(sc, txtid);
-       ath_txq_unlock_complete(sc, txq);
- }
-@@ -1326,7 +1363,7 @@ void ath_tx_aggr_sleep(struct ieee80211_
-               ath_txq_lock(sc, txq);
--              buffered = !skb_queue_empty(&tid->buf_q);
-+              buffered = ath_tid_has_buffered(tid);
-               tid->sched = false;
-               list_del(&tid->list);
-@@ -1358,7 +1395,7 @@ void ath_tx_aggr_wakeup(struct ath_softc
-               ath_txq_lock(sc, txq);
-               ac->clear_ps_filter = true;
--              if (!skb_queue_empty(&tid->buf_q) && !tid->paused) {
-+              if (!tid->paused && ath_tid_has_buffered(tid)) {
-                       ath_tx_queue_tid(txq, tid);
-                       ath_txq_schedule(sc, txq);
-               }
-@@ -1383,7 +1420,7 @@ void ath_tx_aggr_resume(struct ath_softc
-       tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
-       tid->paused = false;
--      if (!skb_queue_empty(&tid->buf_q)) {
-+      if (ath_tid_has_buffered(tid)) {
-               ath_tx_queue_tid(txq, tid);
-               ath_txq_schedule(sc, txq);
-       }
-@@ -1403,6 +1440,7 @@ void ath9k_release_buffered_frames(struc
-       struct ieee80211_tx_info *info;
-       struct list_head bf_q;
-       struct ath_buf *bf_tail = NULL, *bf;
-+      struct sk_buff_head *tid_q;
-       int sent = 0;
-       int i;
-@@ -1418,15 +1456,15 @@ void ath9k_release_buffered_frames(struc
-                       continue;
-               ath_txq_lock(sc, tid->ac->txq);
--              while (!skb_queue_empty(&tid->buf_q) && nframes > 0) {
--                      bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid);
-+              while (nframes > 0) {
-+                      bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q);
-                       if (!bf)
-                               break;
--                      __skb_unlink(bf->bf_mpdu, &tid->buf_q);
-+                      __skb_unlink(bf->bf_mpdu, tid_q);
-                       list_add_tail(&bf->list, &bf_q);
-                       ath_set_rates(tid->an->vif, tid->an->sta, bf);
--                      ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
-+                      ath_tx_addto_baw(sc, tid, bf);
-                       bf->bf_state.bf_type &= ~BUF_AGGR;
-                       if (bf_tail)
-                               bf_tail->bf_next = bf;
-@@ -1436,7 +1474,7 @@ void ath9k_release_buffered_frames(struc
-                       sent++;
-                       TX_STAT_INC(txq->axq_qnum, a_queued_hw);
--                      if (skb_queue_empty(&tid->buf_q))
-+                      if (!ath_tid_has_buffered(tid))
-                               ieee80211_sta_set_buffered(an->sta, i, false);
-               }
-               ath_txq_unlock_complete(sc, tid->ac->txq);
-@@ -1722,7 +1760,7 @@ void ath_txq_schedule(struct ath_softc *
-                        * add tid to round-robin queue if more frames
-                        * are pending for the tid
-                        */
--                      if (!skb_queue_empty(&tid->buf_q))
-+                      if (ath_tid_has_buffered(tid))
-                               ath_tx_queue_tid(txq, tid);
-                       if (tid == last_tid ||
-@@ -1831,7 +1869,7 @@ static void ath_tx_send_ampdu(struct ath
-        * - seqno is not within block-ack window
-        * - h/w queue depth exceeds low water mark
-        */
--      if ((!skb_queue_empty(&tid->buf_q) || tid->paused ||
-+      if ((ath_tid_has_buffered(tid) || tid->paused ||
-            !BAW_WITHIN(tid->seq_start, tid->baw_size, tid->seq_next) ||
-            txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) &&
-           txq != sc->tx.uapsdq) {
-@@ -1859,7 +1897,7 @@ static void ath_tx_send_ampdu(struct ath
-       list_add(&bf->list, &bf_head);
-       /* Add sub-frame to BAW */
--      ath_tx_addto_baw(sc, tid, bf->bf_state.seqno);
-+      ath_tx_addto_baw(sc, tid, bf);
-       /* Queue to h/w without aggregation */
-       TX_STAT_INC(txq->axq_qnum, a_queued_hw);
-@@ -2066,7 +2104,6 @@ int ath_tx_start(struct ieee80211_hw *hw
-       struct ath_txq *txq = txctl->txq;
-       struct ath_atx_tid *tid = NULL;
-       struct ath_buf *bf;
--      u8 tidno;
-       int q;
-       int ret;
-@@ -2097,9 +2134,7 @@ int ath_tx_start(struct ieee80211_hw *hw
-       }
-       if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) {
--              tidno = ieee80211_get_qos_ctl(hdr)[0] &
--                      IEEE80211_QOS_CTL_TID_MASK;
--              tid = ATH_AN_2_TID(txctl->an, tidno);
-+              tid = ath_get_skb_tid(sc, txctl->an, skb);
-               WARN_ON(tid->ac->txq != txctl->txq);
-       }
-@@ -2372,8 +2407,7 @@ static void ath_tx_processq(struct ath_s
-               if (list_empty(&txq->axq_q)) {
-                       txq->axq_link = NULL;
--                      if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
--                              ath_txq_schedule(sc, txq);
-+                      ath_txq_schedule(sc, txq);
-                       break;
-               }
-               bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
-@@ -2595,6 +2629,7 @@ void ath_tx_node_init(struct ath_softc *
-               tid->paused    = false;
-               tid->active        = false;
-               __skb_queue_head_init(&tid->buf_q);
-+              __skb_queue_head_init(&tid->retry_q);
-               acno = TID_TO_WME_AC(tidno);
-               tid->ac = &an->ac[acno];
-       }
-@@ -2602,6 +2637,7 @@ void ath_tx_node_init(struct ath_softc *
-       for (acno = 0, ac = &an->ac[acno];
-            acno < IEEE80211_NUM_ACS; acno++, ac++) {
-               ac->sched    = false;
-+              ac->clear_ps_filter = true;
-               ac->txq = sc->tx.txq_map[acno];
-               INIT_LIST_HEAD(&ac->tid_q);
-       }
diff --git a/package/mac80211/patches/561-ath9k-ar933x-usb-hang-workaround.patch b/package/mac80211/patches/561-ath9k-ar933x-usb-hang-workaround.patch
deleted file mode 100644 (file)
index 40b6fef..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -313,6 +313,19 @@ void ath9k_hw_get_channel_centers(struct
-               centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
- }
-+static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah)
-+{
-+      /* On AR9330 and AR9340 devices, some PHY registers must be
-+       * tuned to gain better stability/performance. These registers
-+       * might be changed while doing wlan reset so the registers must
-+       * be reprogrammed after each reset.
-+       */
-+      REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20));
-+      REG_RMW(ah, AR_PHY_USB_CTRL2,
-+              (1 << 21) | (0xf << 22),
-+              (1 << 21) | (0x3 << 22));
-+}
-+
- /******************/
- /* Chip Revisions */
- /******************/
-@@ -1397,6 +1410,9 @@ static bool ath9k_hw_set_reset(struct at
-       if (AR_SREV_9100(ah))
-               udelay(50);
-+      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+              ath9k_hw_disable_pll_lock_detect(ah);
-+
-       return true;
- }
-@@ -1498,6 +1514,9 @@ static bool ath9k_hw_chip_reset(struct a
-       ath9k_hw_init_pll(ah, chan);
-       ath9k_hw_set_rfmode(ah, chan);
-+      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+              ath9k_hw_disable_pll_lock_detect(ah);
-+
-       return true;
- }
-@@ -1848,8 +1867,14 @@ static int ath9k_hw_do_fastcc(struct ath
-       if (AR_SREV_9271(ah))
-               ar9002_hw_load_ani_reg(ah, chan);
-+      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+              ath9k_hw_disable_pll_lock_detect(ah);
-+
-       return 0;
- fail:
-+      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+              ath9k_hw_disable_pll_lock_detect(ah);
-+
-       return -EINVAL;
- }
-@@ -2074,6 +2099,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
-       if (AR_SREV_9565(ah) && ah->shared_chain_lnadiv)
-               REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
-+      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+              ath9k_hw_disable_pll_lock_detect(ah);
-+
-       return 0;
- }
- EXPORT_SYMBOL(ath9k_hw_reset);
---- a/drivers/net/wireless/ath/ath9k/phy.h
-+++ b/drivers/net/wireless/ath/ath9k/phy.h
-@@ -48,4 +48,7 @@
- #define AR_PHY_PLL_CONTROL 0x16180
- #define AR_PHY_PLL_MODE 0x16184
-+#define AR_PHY_USB_CTRL1      0x16c84
-+#define AR_PHY_USB_CTRL2      0x16c88
-+
- #endif
diff --git a/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch b/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch
new file mode 100644 (file)
index 0000000..af94c9e
--- /dev/null
@@ -0,0 +1,79 @@
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -217,6 +217,19 @@ void ath9k_hw_get_channel_centers(struct
+               centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
+ }
++static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah)
++{
++      /* On AR9330 and AR9340 devices, some PHY registers must be
++       * tuned to gain better stability/performance. These registers
++       * might be changed while doing wlan reset so the registers must
++       * be reprogrammed after each reset.
++       */
++      REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20));
++      REG_RMW(ah, AR_PHY_USB_CTRL2,
++              (1 << 21) | (0xf << 22),
++              (1 << 21) | (0x3 << 22));
++}
++
+ /******************/
+ /* Chip Revisions */
+ /******************/
+@@ -1337,6 +1350,9 @@ static bool ath9k_hw_set_reset(struct at
+       if (AR_SREV_9100(ah))
+               udelay(50);
++      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++              ath9k_hw_disable_pll_lock_detect(ah);
++
+       return true;
+ }
+@@ -1436,6 +1452,9 @@ static bool ath9k_hw_chip_reset(struct a
+               ar9003_hw_internal_regulator_apply(ah);
+       ath9k_hw_init_pll(ah, chan);
++      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++              ath9k_hw_disable_pll_lock_detect(ah);
++
+       return true;
+ }
+@@ -1730,8 +1749,14 @@ static int ath9k_hw_do_fastcc(struct ath
+       if (AR_SREV_9271(ah))
+               ar9002_hw_load_ani_reg(ah, chan);
++      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++              ath9k_hw_disable_pll_lock_detect(ah);
++
+       return 0;
+ fail:
++      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++              ath9k_hw_disable_pll_lock_detect(ah);
++
+       return -EINVAL;
+ }
+@@ -1959,6 +1984,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+       if (AR_SREV_9565(ah) && common->bt_ant_diversity)
+               REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
++      if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++              ath9k_hw_disable_pll_lock_detect(ah);
++
+       return 0;
+ }
+ EXPORT_SYMBOL(ath9k_hw_reset);
+--- a/drivers/net/wireless/ath/ath9k/phy.h
++++ b/drivers/net/wireless/ath/ath9k/phy.h
+@@ -48,6 +48,9 @@
+ #define AR_PHY_PLL_CONTROL 0x16180
+ #define AR_PHY_PLL_MODE 0x16184
++#define AR_PHY_USB_CTRL1      0x16c84
++#define AR_PHY_USB_CTRL2      0x16c88
++
+ enum ath9k_ant_div_comb_lna_conf {
+       ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
+       ATH_ANT_DIV_COMB_LNA2,
index d9a20bc1071dbcc95409ed95d119306b6f5e3452..08c8fa651cbb6ea25e1b3fac7f6ef1b70f2173e5 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c
 +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
-@@ -96,8 +96,10 @@ int rt2x00pci_probe(struct pci_dev *pci_
+@@ -94,8 +94,10 @@ int rt2x00pci_probe(struct pci_dev *pci_
  
        pci_set_master(pci_dev);
  
index 6c80c3dfa81d65c3adb1724ac8fb1ebbf1d6a7d0..8c71075b5cdce6afce5236d03661248f79bea644 100644 (file)
 +#endif /* _RT2X00_PLATFORM_H */
 --- a/drivers/net/wireless/rt2x00/rt2x00.h
 +++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -39,6 +39,7 @@
- #include <linux/input-polldev.h>
+@@ -38,6 +38,7 @@
  #include <linux/kfifo.h>
  #include <linux/hrtimer.h>
+ #include <linux/average.h>
 +#include <linux/rt2x00_platform.h>
  
  #include <net/mac80211.h>
index f47c1a5321d025e7b3cc9c2aa911ad52101a7c17..2bbc6f162a4aca912f6a4f48b3606f1c36a40b87 100644 (file)
@@ -1,6 +1,158 @@
+--- a/.local-symbols
++++ b/.local-symbols
+@@ -279,6 +279,7 @@ RT2X00_LIB_FIRMWARE=
+ RT2X00_LIB_CRYPTO=
+ RT2X00_LIB_LEDS=
+ RT2X00_LIB_DEBUGFS=
++RT2X00_LIB_EEPROM=
+ RT2X00_DEBUG=
+ RTL_CARDS=
+ RTL8192CE=
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -69,6 +69,7 @@ config RT2800PCI
+       select RT2X00_LIB_MMIO
+       select RT2X00_LIB_PCI
+       select RT2X00_LIB_FIRMWARE
++      select RT2X00_LIB_EEPROM
+       select RT2X00_LIB_CRYPTO
+       depends on CRC_CCITT
+       depends on EEPROM_93CX6
+@@ -215,6 +216,7 @@ config RT2800SOC
+       select RT2X00_LIB_MMIO
+       select RT2X00_LIB_CRYPTO
+       select RT2X00_LIB_FIRMWARE
++      select RT2X00_LIB_EEPROM
+       select RT2800_LIB
+       select RT2800_LIB_MMIO
+       ---help---
+@@ -266,6 +268,9 @@ config RT2X00_LIB_FIRMWARE
+ config RT2X00_LIB_CRYPTO
+       boolean
++config RT2X00_LIB_EEPROM
++      boolean
++
+ config RT2X00_LIB_LEDS
+       boolean
+       default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
+--- a/drivers/net/wireless/rt2x00/Makefile
++++ b/drivers/net/wireless/rt2x00/Makefile
+@@ -7,6 +7,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) +
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE)       += rt2x00firmware.o
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS)   += rt2x00leds.o
++rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o
+ obj-$(CPTCFG_RT2X00_LIB)              += rt2x00lib.o
+ obj-$(CPTCFG_RT2X00_LIB_MMIO)         += rt2x00mmio.o
+--- a/drivers/net/wireless/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/rt2x00/rt2800lib.h
+@@ -20,6 +20,8 @@
+ #ifndef RT2800LIB_H
+ #define RT2800LIB_H
++#include "rt2800.h"
++
+ struct rt2800_ops {
+       void (*register_read)(struct rt2x00_dev *rt2x00dev,
+                             const unsigned int offset, u32 *value);
+@@ -119,6 +121,15 @@ static inline int rt2800_read_eeprom(str
+ {
+       const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
++      if (rt2x00dev->eeprom_file) {
++              memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data,
++                     EEPROM_SIZE);
++              return 0;
++      }
++
++      if (!rt2800ops->read_eeprom)
++              return -EINVAL;
++
+       return rt2800ops->read_eeprom(rt2x00dev);
+ }
+--- a/drivers/net/wireless/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/rt2x00/rt2800soc.c
+@@ -95,19 +95,6 @@ static int rt2800soc_set_device_state(st
+       return retval;
+ }
+-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
+-{
+-      void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
+-
+-      if (!base_addr)
+-              return -ENOMEM;
+-
+-      memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
+-
+-      iounmap(base_addr);
+-      return 0;
+-}
+-
+ /* Firmware functions */
+ static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -171,7 +158,6 @@ static const struct rt2800_ops rt2800soc
+       .register_multiread     = rt2x00mmio_register_multiread,
+       .register_multiwrite    = rt2x00mmio_register_multiwrite,
+       .regbusy_read           = rt2x00mmio_regbusy_read,
+-      .read_eeprom            = rt2800soc_read_eeprom,
+       .hwcrypt_disabled       = rt2800soc_hwcrypt_disabled,
+       .drv_write_firmware     = rt2800soc_write_firmware,
+       .drv_init_registers     = rt2800mmio_init_registers,
+--- a/drivers/net/wireless/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/rt2x00/rt2x00.h
+@@ -694,6 +694,7 @@ enum rt2x00_capability_flags {
+       REQUIRE_SW_SEQNO,
+       REQUIRE_HT_TX_DESC,
+       REQUIRE_PS_AUTOWAKE,
++      REQUIRE_EEPROM_FILE,
+       /*
+        * Capabilities
+@@ -963,6 +964,11 @@ struct rt2x00_dev {
+       const struct firmware *fw;
+       /*
++       * EEPROM image.
++       */
++      const struct firmware *eeprom_file;
++
++      /*
+        * FIFO for storing tx status reports between isr and tasklet.
+        */
+       DECLARE_KFIFO_PTR(txstatus_fifo, u32);
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -1324,6 +1324,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+       INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
+       INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
++      retval = rt2x00lib_load_eeprom_file(rt2x00dev);
++      if (retval)
++              goto exit;
++
+       /*
+        * Let the driver probe the device to detect the capabilities.
+        */
+@@ -1454,6 +1458,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
+        */
+       if (rt2x00dev->drv_data)
+               kfree(rt2x00dev->drv_data);
++
++      /*
++       * Free EEPROM image.
++       */
++      rt2x00lib_free_eeprom_file(rt2x00dev);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
 --- /dev/null
 +++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c
-@@ -0,0 +1,98 @@
+@@ -0,0 +1,111 @@
 +/*
 +      Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 +      Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
 +#include "rt2x00.h"
 +#include "rt2x00lib.h"
 +
++static const char *
++rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
++{
++      struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
++
++      if (pdata && pdata->eeprom_file_name)
++              return pdata->eeprom_file_name;
++
++      return NULL
++}
++
 +static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
 +{
 +      const struct firmware *ee;
-+      char *ee_name;
++      const char *ee_name;
 +      int retval;
 +
-+      ee_name = rt2x00dev->ops->lib->get_eeprom_file_name(rt2x00dev);
++      ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
 +      if (!ee_name) {
 +              rt2x00_err(rt2x00dev,
 +                         "Invalid EEPROM filename.\n"
 +{
 +      int retval;
 +
-+      if (!test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags))
++      if (!rt2x00lib_get_eeprom_file_name(rt2x00dev))
 +              return 0;
 +
++      set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
++
 +      if (!rt2x00dev->eeprom_file) {
 +              retval = rt2x00lib_request_eeprom_file(rt2x00dev);
 +              if (retval)
 +      release_firmware(rt2x00dev->eeprom_file);
 +      rt2x00dev->eeprom_file = NULL;
 +}
---- a/drivers/net/wireless/rt2x00/rt2x00.h
-+++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -549,6 +549,7 @@ struct rt2x00lib_ops {
-                              const u8 *data, const size_t len);
-       int (*load_firmware) (struct rt2x00_dev *rt2x00dev,
-                             const u8 *data, const size_t len);
-+      char *(*get_eeprom_file_name) (struct rt2x00_dev *rt2x00dev);
-       /*
-        * Device initialization/deinitialization handlers.
-@@ -705,6 +706,7 @@ enum rt2x00_capability_flags {
-       REQUIRE_SW_SEQNO,
-       REQUIRE_HT_TX_DESC,
-       REQUIRE_PS_AUTOWAKE,
-+      REQUIRE_EEPROM_FILE,
-       /*
-        * Capabilities
-@@ -974,6 +976,11 @@ struct rt2x00_dev {
-       const struct firmware *fw;
-       /*
-+       * EEPROM image.
-+       */
-+      const struct firmware *eeprom_file;
-+
-+      /*
-        * FIFO for storing tx status reports between isr and tasklet.
-        */
-       DECLARE_KFIFO_PTR(txstatus_fifo, u32);
 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h
 +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
-@@ -322,6 +322,22 @@ static inline void rt2x00lib_free_firmwa
+@@ -320,6 +320,22 @@ static inline void rt2x00lib_free_firmwa
  #endif /* CPTCFG_RT2X00_LIB_FIRMWARE */
  
  /*
   * Debugfs handlers.
   */
  #ifdef CPTCFG_RT2X00_LIB_DEBUGFS
---- a/drivers/net/wireless/rt2x00/Kconfig
-+++ b/drivers/net/wireless/rt2x00/Kconfig
-@@ -69,6 +69,7 @@ config RT2800PCI
-       select RT2X00_LIB_PCI if PCI
-       select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X
-       select RT2X00_LIB_FIRMWARE
-+      select RT2X00_LIB_EEPROM
-       select RT2X00_LIB_CRYPTO
-       depends on CRC_CCITT
-       depends on EEPROM_93CX6
-@@ -238,6 +239,9 @@ config RT2X00_LIB_FIRMWARE
- config RT2X00_LIB_CRYPTO
-       boolean
-+config RT2X00_LIB_EEPROM
-+      boolean
-+
- config RT2X00_LIB_LEDS
-       depends on !BACKPORT_KERNEL_2_6_25
-       boolean
---- a/drivers/net/wireless/rt2x00/Makefile
-+++ b/drivers/net/wireless/rt2x00/Makefile
-@@ -7,6 +7,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) +
- rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
- rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE)       += rt2x00firmware.o
- rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS)   += rt2x00leds.o
-+rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o
- obj-$(CPTCFG_RT2X00_LIB)              += rt2x00lib.o
- obj-$(CPTCFG_RT2X00_LIB_MMIO)         += rt2x00mmio.o
---- a/drivers/net/wireless/rt2x00/rt2800pci.c
-+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
-@@ -90,25 +90,11 @@ static void rt2800pci_mcu_status(struct 
-       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
- }
--#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
- static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
- {
--      void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
--
--      if (!base_addr)
--              return -ENOMEM;
--
--      memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
--
--      iounmap(base_addr);
-+      memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, EEPROM_SIZE);
-       return 0;
- }
--#else
--static inline int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
--{
--      return -ENOMEM;
--}
--#endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */
- #ifdef CONFIG_PCI
- static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
-@@ -332,6 +318,20 @@ static int rt2800pci_write_firmware(stru
- }
- /*
-+ * EEPROM file functions.
-+ */
-+static char *rt2800pci_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
-+{
-+      struct rt2x00_platform_data *pdata;
-+
-+      pdata = rt2x00dev->dev->platform_data;
-+      if (pdata)
-+              return pdata->eeprom_file_name;
-+
-+      return NULL;
-+}
-+
-+/*
-  * Initialization functions.
-  */
- static bool rt2800pci_get_entry_state(struct queue_entry *entry)
-@@ -1156,6 +1156,7 @@ static const struct rt2x00lib_ops rt2800
-       .get_firmware_name      = rt2800pci_get_firmware_name,
-       .check_firmware         = rt2800_check_firmware,
-       .load_firmware          = rt2800_load_firmware,
-+      .get_eeprom_file_name   = rt2800pci_get_eeprom_file_name,
-       .initialize             = rt2x00mmio_initialize,
-       .uninitialize           = rt2x00mmio_uninitialize,
-       .get_entry_state        = rt2800pci_get_entry_state,
---- a/drivers/net/wireless/rt2x00/rt2x00dev.c
-+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -1325,6 +1325,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
-       INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
-       INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
-+      retval = rt2x00lib_load_eeprom_file(rt2x00dev);
-+      if (retval)
-+              goto exit;
-+
-       /*
-        * Let the driver probe the device to detect the capabilities.
-        */
-@@ -1455,6 +1459,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
-        */
-       if (rt2x00dev->drv_data)
-               kfree(rt2x00dev->drv_data);
-+
-+      /*
-+       * Free EEPROM image.
-+       */
-+      rt2x00lib_free_eeprom_file(rt2x00dev);
- }
- EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c
 +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c
-@@ -94,6 +94,7 @@ int rt2x00soc_probe(struct platform_devi
+@@ -92,6 +92,7 @@ int rt2x00soc_probe(struct platform_devi
        rt2x00dev->hw = hw;
        rt2x00dev->irq = platform_get_irq(pdev, 0);
        rt2x00dev->name = pdev->dev.driver->name;
  
        rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
  
---- a/.local-symbols
-+++ b/.local-symbols
-@@ -272,6 +272,7 @@ RT2X00_LIB_FIRMWARE=
- RT2X00_LIB_CRYPTO=
- RT2X00_LIB_LEDS=
- RT2X00_LIB_DEBUGFS=
-+RT2X00_LIB_EEPROM=
- RT2X00_DEBUG=
- RTLWIFI=
- RTLWIFI_DEBUG=
diff --git a/package/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch b/package/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch
new file mode 100644 (file)
index 0000000..4bc6f37
--- /dev/null
@@ -0,0 +1,33 @@
+--- a/drivers/net/wireless/rt2x00/rt2x00eeprom.c
++++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c
+@@ -26,6 +26,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/of.h>
+ #include "rt2x00.h"
+ #include "rt2x00lib.h"
+@@ -34,11 +35,21 @@ static const char *
+ rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
+ {
+       struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
++#ifdef CONFIG_OF
++      struct device_node *np;
++      const char *eep;
++#endif
+       if (pdata && pdata->eeprom_file_name)
+               return pdata->eeprom_file_name;
+-      return NULL
++#ifdef CONFIG_OF
++      np = rt2x00dev->dev->of_node;
++      if (np && of_property_read_string(np, "ralink,eeprom", &eep) == 0)
++          return eep;
++#endif
++
++      return NULL;
+ }
+ static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
diff --git a/package/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch b/package/mac80211/patches/605-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch
new file mode 100644 (file)
index 0000000..75f0415
--- /dev/null
@@ -0,0 +1,101 @@
+From 339fe73f340161a624cc08e738d2244814852c3e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 17 Mar 2013 00:55:04 +0100
+Subject: [PATCH] rt2x00: load eeprom on SoC from a mtd device defines inside
+ OF
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/wireless/rt2x00/Kconfig     |    1 +
+ drivers/net/wireless/rt2x00/rt2800pci.c |   44 ++++++++++++++++++++++++++-----
+ 2 files changed, 39 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/Kconfig
++++ b/drivers/net/wireless/rt2x00/Kconfig
+@@ -219,6 +219,7 @@ config RT2800SOC
+       select RT2X00_LIB_EEPROM
+       select RT2800_LIB
+       select RT2800_LIB_MMIO
++      select MTD if SOC_RT288X || SOC_RT305X
+       ---help---
+         This adds support for Ralink WiSoC devices.
+         Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
+--- a/drivers/net/wireless/rt2x00/rt2x00eeprom.c
++++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c
+@@ -26,11 +26,66 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
+ #include <linux/of.h>
+ #include "rt2x00.h"
+ #include "rt2x00lib.h"
++static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
++{
++      int ret = -EINVAL;
++#ifdef CONFIG_OF
++      static struct firmware mtd_fw;
++      struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
++      size_t retlen, len = rt2x00dev->ops->eeprom_size;
++      int size, offset = 0;
++      struct mtd_info *mtd;
++      const char *part;
++      const __be32 *list;
++      phandle phandle;
++
++      list = of_get_property(np, "ralink,mtd-eeprom", &size);
++      if (!list) {
++              dev_err(rt2x00dev->dev, "failed to load eeprom property\n");
++              return -ENOENT;
++      }
++
++      phandle = be32_to_cpup(list++);
++      if (phandle)
++              mtd_np = of_find_node_by_phandle(phandle);
++      if (!mtd_np) {
++              dev_err(rt2x00dev->dev, "failed to load mtd phandle\n");
++              return -EINVAL;
++      }
++
++      part = of_get_property(mtd_np, "label", NULL);
++      if (!part)
++              part = mtd_np->name;
++
++      mtd = get_mtd_device_nm(part);
++      if (IS_ERR(mtd)) {
++              dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part);
++              return PTR_ERR(mtd);
++      }
++
++      if (size > sizeof(*list))
++              offset = be32_to_cpup(list);
++
++      ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom);
++      put_mtd_device(mtd);
++
++      if (!ret) {
++              rt2x00dev->eeprom_file = &mtd_fw;
++              mtd_fw.size = len;
++              mtd_fw.data = rt2x00dev->eeprom;
++      }
++#endif
++
++      return ret;
++}
++
+ static const char *
+ rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -58,6 +113,9 @@ static int rt2x00lib_request_eeprom_file
+       const char *ee_name;
+       int retval;
++      if (!rt2800lib_read_eeprom_mtd(rt2x00dev))
++              return 0;
++
+       ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
+       if (!ee_name) {
+               rt2x00_err(rt2x00dev,
diff --git a/package/mac80211/patches/605-rt2x00-pci-eeprom.patch b/package/mac80211/patches/605-rt2x00-pci-eeprom.patch
deleted file mode 100644 (file)
index bcbb435..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
---- a/drivers/net/wireless/rt2x00/rt2800pci.c
-+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
-@@ -90,7 +90,7 @@ static void rt2800pci_mcu_status(struct 
-       rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
- }
--static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
-+static int rt2800pci_read_eeprom_file(struct rt2x00_dev *rt2x00dev)
- {
-       memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data, EEPROM_SIZE);
-       return 0;
-@@ -1093,8 +1093,9 @@ static int rt2800pci_read_eeprom(struct 
- {
-       int retval;
--      if (rt2x00_is_soc(rt2x00dev))
--              retval = rt2800pci_read_eeprom_soc(rt2x00dev);
-+      if (rt2x00_is_soc(rt2x00dev) ||
-+          test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags))
-+              retval = rt2800pci_read_eeprom_file(rt2x00dev);
-       else if (rt2800pci_efuse_detect(rt2x00dev))
-               retval = rt2800pci_read_eeprom_efuse(rt2x00dev);
-       else
---- a/drivers/net/wireless/rt2x00/rt2x00pci.c
-+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
-@@ -78,6 +78,7 @@ exit:
- int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)
- {
-       struct ieee80211_hw *hw;
-+      struct rt2x00_platform_data *pdata;
-       struct rt2x00_dev *rt2x00dev;
-       int retval;
-       u16 chip;
-@@ -125,6 +126,12 @@ int rt2x00pci_probe(struct pci_dev *pci_
-       rt2x00dev->irq = pci_dev->irq;
-       rt2x00dev->name = pci_name(pci_dev);
-+      /* if we get passed the name of a eeprom_file_name, then use this in
-+         favour of the eeprom */
-+      pdata = rt2x00dev->dev->platform_data;
-+      if (pdata && pdata->eeprom_file_name)
-+              set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
-+
-       if (pci_is_pcie(pci_dev))
-               rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);
-       else
index 9608df2e20894dafc76623262dbf606e9c4c20f8..7e321922f1ba9b4ed271a655a5491a37fadc17b8 100644 (file)
@@ -24,7 +24,7 @@ Helmut
 
 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c
 +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
-@@ -163,36 +163,14 @@ void rt2x00queue_align_frame(struct sk_b
+@@ -161,36 +161,14 @@ void rt2x00queue_align_frame(struct sk_b
  void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
  {
        unsigned int payload_length = skb->len - header_length;
index 5e6e27de98467a58cb0f42727b1f3798812b6969..4116735982c3f2d2e90df5be81a684e1e726757b 100644 (file)
@@ -12,7 +12,7 @@
  #endif /* _RT2X00_PLATFORM_H */
 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
 +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -938,6 +938,22 @@ static int rt2x00lib_probe_hw_modes(stru
+@@ -937,6 +937,22 @@ static int rt2x00lib_probe_hw_modes(stru
        unsigned int num_rates;
        unsigned int i;
  
@@ -37,7 +37,7 @@
                num_rates += 4;
 --- a/drivers/net/wireless/rt2x00/rt2x00.h
 +++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -414,6 +414,7 @@ struct hw_mode_spec {
+@@ -403,6 +403,7 @@ struct hw_mode_spec {
        unsigned int supported_bands;
  #define SUPPORT_BAND_2GHZ     0x00000001
  #define SUPPORT_BAND_5GHZ     0x00000002
index 0695b893b597daac15f585f6a76b99f60c155a9c..a910cc36c051a1fc8e4ddc6190fb49d08e28b705 100644 (file)
@@ -10,7 +10,7 @@
        int disable_5ghz;
 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
 +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
-@@ -929,6 +929,18 @@ static void rt2x00lib_rate(struct ieee80
+@@ -928,6 +928,18 @@ static void rt2x00lib_rate(struct ieee80
                entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE;
  }
  
@@ -31,7 +31,7 @@
  {
 --- a/drivers/net/wireless/rt2x00/rt2x00.h
 +++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -1326,6 +1326,7 @@ static inline void rt2x00debug_dump_fram
+@@ -1401,6 +1401,7 @@ static inline void rt2x00debug_dump_fram
   */
  u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev,
                         struct ieee80211_vif *vif);
@@ -41,7 +41,7 @@
   * Interrupt context handlers.
 --- a/drivers/net/wireless/rt2x00/rt61pci.c
 +++ b/drivers/net/wireless/rt2x00/rt61pci.c
-@@ -2395,6 +2395,7 @@ static int rt61pci_validate_eeprom(struc
+@@ -2392,6 +2392,7 @@ static int rt61pci_validate_eeprom(struc
        u32 reg;
        u16 word;
        u8 *mac;
@@ -49,7 +49,7 @@
        s8 value;
  
        rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, &reg);
-@@ -2415,7 +2416,11 @@ static int rt61pci_validate_eeprom(struc
+@@ -2412,7 +2413,11 @@ static int rt61pci_validate_eeprom(struc
        /*
         * Start validation of the data that has been read.
         */
index 8369a78ad9e4fcd9a682f3110b71ebcf2ba8dccc..83fbcd0fccf1c214c459dd6d92bb92f283a4ca44 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -2631,15 +2631,18 @@ static void rt2800_config_channel(struct
+@@ -3176,11 +3176,17 @@ static void rt2800_config_channel(struct
        /*
         * Change BBP settings
         */
                rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain);
 +              rt2800_bbp_write(rt2x00dev, 86, 0x38);
 +              rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+       } else if (rt2x00_rt(rt2x00dev, RT3593)) {
+               if (rf->channel > 14) {
+                       /* Disable CCK Packet detection on 5GHz */
+@@ -3194,14 +3200,8 @@ static void rt2800_config_channel(struct
+               else
+                       rt2800_bbp_write(rt2x00dev, 105, 0x34);
+-              rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+-              rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+-              rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+               rt2800_bbp_write(rt2x00dev, 77, 0x98);
        } else {
 -              rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
 -              rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
@@ -22,7 +33,7 @@
                rt2800_bbp_write(rt2x00dev, 86, 0);
        }
  
-@@ -4971,6 +4974,12 @@ static void rt2800_init_rfcsr_3290(struc
+@@ -6125,6 +6125,12 @@ static void rt2800_init_rfcsr_3290(struc
  
  static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev)
  {
@@ -35,7 +46,7 @@
        rt2800_rf_init_calibration(rt2x00dev, 30);
  
        rt2800_rfcsr_write(rt2x00dev, 0, 0xf0);
-@@ -5006,15 +5015,30 @@ static void rt2800_init_rfcsr_3352(struc
+@@ -6160,15 +6166,30 @@ static void rt2800_init_rfcsr_3352(struc
        rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
        rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
        rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
@@ -69,7 +80,7 @@
        rt2800_rfcsr_write(rt2x00dev, 43, 0xdb);
        rt2800_rfcsr_write(rt2x00dev, 44, 0xdb);
        rt2800_rfcsr_write(rt2x00dev, 45, 0xdb);
-@@ -5022,15 +5046,20 @@ static void rt2800_init_rfcsr_3352(struc
+@@ -6176,15 +6197,20 @@ static void rt2800_init_rfcsr_3352(struc
        rt2800_rfcsr_write(rt2x00dev, 47, 0x0d);
        rt2800_rfcsr_write(rt2x00dev, 48, 0x14);
        rt2800_rfcsr_write(rt2x00dev, 49, 0x00);
        rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
        rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
        rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
-@@ -5716,6 +5745,7 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7051,6 +7077,7 @@ static int rt2800_init_eeprom(struct rt2
         * RT53xx: defined in "EEPROM_CHIP_ID" field
         */
        if (rt2x00_rt(rt2x00dev, RT3290) ||
 +          rt2x00_rt(rt2x00dev, RT3352) ||
            rt2x00_rt(rt2x00dev, RT5390) ||
            rt2x00_rt(rt2x00dev, RT5392))
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
-@@ -5805,7 +5835,8 @@ static int rt2800_init_eeprom(struct rt2
+               rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+@@ -7142,7 +7169,8 @@ static int rt2800_init_eeprom(struct rt2
        /*
         * Detect if this device has Bluetooth co-existence.
         */
                __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);
  
        /*
-@@ -5834,6 +5865,22 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7171,6 +7199,22 @@ static int rt2800_init_eeprom(struct rt2
                                        EIRP_MAX_TX_POWER_LIMIT)
                __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags);
  
 +      /*
 +       * Detect if device uses internal or external PA
 +       */
-+      rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
++      rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
 +
 +      if (rt2x00_rt(rt2x00dev, RT3352)) {
 +              if (!rt2x00_get_field16(eeprom,
  
 --- a/drivers/net/wireless/rt2x00/rt2800.h
 +++ b/drivers/net/wireless/rt2x00/rt2800.h
-@@ -2153,6 +2153,12 @@ struct mac_iveiv_entry {
- #define RFCSR31_RX_CALIB              FIELD8(0x7f)
+@@ -2299,6 +2299,12 @@ struct mac_iveiv_entry {
+ #define RFCSR36_RF_BS                 FIELD8(0x80)
  
  /*
 + * RFCSR 34:
   * RFCSR 38:
   */
  #define RFCSR38_RX_LO1_EN             FIELD8(0x20)
-@@ -2163,6 +2169,18 @@ struct mac_iveiv_entry {
+@@ -2310,6 +2316,18 @@ struct mac_iveiv_entry {
  #define RFCSR39_RX_LO2_EN             FIELD8(0x80)
  
  /*
   * RFCSR 49:
   */
  #define RFCSR49_TX                    FIELD8(0x3f)
-@@ -2172,6 +2190,8 @@ struct mac_iveiv_entry {
+@@ -2322,6 +2340,8 @@ struct mac_iveiv_entry {
   * RFCSR 50:
   */
  #define RFCSR50_TX                    FIELD8(0x3f)
 +#define RFCSR50_TX0_EXT_PA            FIELD8(0x02)
 +#define RFCSR50_TX1_EXT_PA            FIELD8(0x10)
  #define RFCSR50_EP                    FIELD8(0xc0)
- /*
-@@ -2260,6 +2280,8 @@ struct mac_iveiv_entry {
+ /* bits for RT3593 */
+ #define RFCSR50_TX_LO1_EN             FIELD8(0x20)
+@@ -2469,6 +2489,8 @@ enum rt2800_eeprom_word {
   * INTERNAL_TX_ALC: 0: disable, 1: enable
   * BT_COEXIST: 0: disable, 1: enable
   * DAC_TEST: 0: disable, 1: enable
 + * EXTERNAL_TX0_PA: 0: disable, 1: enable (only on RT3352)
 + * EXTERNAL_TX1_PA: 0: disable, 1: enable (only on RT3352)
   */
- #define       EEPROM_NIC_CONF1                0x001b
  #define EEPROM_NIC_CONF1_HW_RADIO             FIELD16(0x0001)
-@@ -2277,6 +2299,8 @@ struct mac_iveiv_entry {
- #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC              FIELD16(0x2000)
+ #define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC      FIELD16(0x0002)
+@@ -2485,6 +2507,8 @@ enum rt2800_eeprom_word {
+ #define EEPROM_NIC_CONF1_INTERNAL_TX_ALC      FIELD16(0x2000)
  #define EEPROM_NIC_CONF1_BT_COEXIST           FIELD16(0x4000)
  #define EEPROM_NIC_CONF1_DAC_TEST             FIELD16(0x8000)
 +#define EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352 FIELD16(0x4000)
   * EEPROM frequency
 --- a/drivers/net/wireless/rt2x00/rt2x00.h
 +++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -726,6 +726,8 @@ enum rt2x00_capability_flags {
+@@ -714,6 +714,8 @@ enum rt2x00_capability_flags {
        CAPABILITY_DOUBLE_ANTENNA,
        CAPABILITY_BT_COEXIST,
        CAPABILITY_VCO_RECALIBRATION,
index e16d97026ab51b12530487ffb4481db69a54d1a2..478a0f277e89b667607898b293aefe6db80fb4a2 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -6157,6 +6157,27 @@ static const struct rf_channel rf_vals_5
+@@ -7491,6 +7491,27 @@ static const struct rf_channel rf_vals_5
        {196, 83, 0, 12, 1},
  };
  
  static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
  {
        struct hw_mode_spec *spec = &rt2x00dev->spec;
-@@ -6235,7 +6256,6 @@ static int rt2800_probe_hw_mode(struct r
-                  rt2x00_rf(rt2x00dev, RF3022) ||
-                  rt2x00_rf(rt2x00dev, RF3290) ||
-                  rt2x00_rf(rt2x00dev, RF3320) ||
--                 rt2x00_rf(rt2x00dev, RF3322) ||
-                  rt2x00_rf(rt2x00dev, RF5360) ||
-                  rt2x00_rf(rt2x00dev, RF5370) ||
-                  rt2x00_rf(rt2x00dev, RF5372) ||
-@@ -6243,6 +6263,12 @@ static int rt2800_probe_hw_mode(struct r
-                  rt2x00_rf(rt2x00dev, RF5392)) {
+@@ -7579,7 +7600,10 @@ static int rt2800_probe_hw_mode(struct r
+       case RF5390:
+       case RF5392:
                spec->num_channels = 14;
-               spec->channels = rf_vals_3x;
-+      } else if (rt2x00_rf(rt2x00dev, RF3322)) {
-+              spec->num_channels = 14;
+-              spec->channels = rf_vals_3x;
 +              if (spec->clk_is_20mhz)
 +                      spec->channels = rf_vals_xtal20mhz_3x;
 +              else
 +                      spec->channels = rf_vals_3x;
-       } else if (rt2x00_rf(rt2x00dev, RF3052)) {
-               spec->supported_bands |= SUPPORT_BAND_5GHZ;
-               spec->num_channels = ARRAY_SIZE(rf_vals_3x);
-@@ -6390,6 +6416,19 @@ static int rt2800_probe_rt(struct rt2x00
+               break;
+       case RF3052:
+@@ -7755,6 +7779,19 @@ static int rt2800_probe_rt(struct rt2x00
        return 0;
  }
  
@@ -69,7 +60,7 @@
  int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev)
  {
        int retval;
-@@ -6419,6 +6458,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
+@@ -7784,6 +7821,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r
        rt2800_register_write(rt2x00dev, GPIO_CTRL, reg);
  
        /*
@@ -87,7 +78,7 @@
        retval = rt2800_probe_hw_mode(rt2x00dev);
 --- a/drivers/net/wireless/rt2x00/rt2x00.h
 +++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -409,6 +409,7 @@ static inline struct rt2x00_intf* vif_to
+@@ -398,6 +398,7 @@ static inline struct rt2x00_intf* vif_to
   * @channels: Device/chipset specific channel values (See &struct rf_channel).
   * @channels_info: Additional information for channels (See &struct channel_info).
   * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap).
@@ -95,7 +86,7 @@
   */
  struct hw_mode_spec {
        unsigned int supported_bands;
-@@ -425,6 +426,7 @@ struct hw_mode_spec {
+@@ -414,6 +415,7 @@ struct hw_mode_spec {
        const struct channel_info *channels_info;
  
        struct ieee80211_sta_ht_cap ht;
index 81125a96c2af475fbc02b2828e30ae65ba36f71e..f6b4808e42674ce7cf4c76368e0fb9069e6d0b23 100644 (file)
@@ -11,10 +11,10 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  drivers/net/wireless/rt2x00/rt2800pci.c |    7 +++++++
  1 file changed, 7 insertions(+)
 
---- a/drivers/net/wireless/rt2x00/rt2800pci.c
-+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
-@@ -1309,11 +1309,18 @@ static int rt2800soc_probe(struct platfo
-       return rt2x00soc_probe(pdev, &rt2800pci_ops);
+--- a/drivers/net/wireless/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/rt2x00/rt2800soc.c
+@@ -227,11 +227,18 @@ static int rt2800soc_probe(struct platfo
+       return rt2x00soc_probe(pdev, &rt2800soc_ops);
  }
  
 +static const struct of_device_id rt2880_wmac_match[] = {
diff --git a/package/mac80211/patches/614-rt2x00-of_load_eeprom_filename.patch b/package/mac80211/patches/614-rt2x00-of_load_eeprom_filename.patch
deleted file mode 100644 (file)
index 293b71a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
---- a/drivers/net/wireless/rt2x00/rt2800pci.c
-+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
-@@ -39,6 +39,7 @@
- #include <linux/pci.h>
- #include <linux/platform_device.h>
- #include <linux/eeprom_93cx6.h>
-+#include <linux/of.h>
- #include "rt2x00.h"
- #include "rt2x00mmio.h"
-@@ -323,11 +324,17 @@ static int rt2800pci_write_firmware(stru
- static char *rt2800pci_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
- {
-       struct rt2x00_platform_data *pdata;
-+      struct device_node *np;
-+      char *eep;
-       pdata = rt2x00dev->dev->platform_data;
-       if (pdata)
-               return pdata->eeprom_file_name;
-+      np = rt2x00dev->dev->of_node;
-+      if (np && !of_property_read_string(np, "ralink,eeprom", &eep))
-+              return eep;
-+
-       return NULL;
- }
diff --git a/package/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch b/package/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch
new file mode 100644 (file)
index 0000000..d843b7a
--- /dev/null
@@ -0,0 +1,29 @@
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -36,6 +36,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/clk.h>
+ #include "rt2x00.h"
+ #include "rt2800lib.h"
+@@ -7781,13 +7782,14 @@ static int rt2800_probe_rt(struct rt2x00
+ int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev)
+ {
+-      struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
+       struct hw_mode_spec *spec = &rt2x00dev->spec;
++      struct clk *clk = clk_get(rt2x00dev->dev, NULL);
+-      if (!pdata)
+-              return -EINVAL;
++      if (IS_ERR(clk))
++              return PTR_ERR(clk);
+-      spec->clk_is_20mhz = pdata->clk_is_20mhz;
++      if (clk_get_rate(clk) == 20000000)
++              spec->clk_is_20mhz = 1;
+       return 0;
+ }
index 9dc5835605a612fac75e4c9f061bc809cd6014e2..8d3fcd245a630adf81c772e597bfc5bc5bc83244 100644 (file)
@@ -1,8 +1,8 @@
 --- a/drivers/net/wireless/rt2x00/rt2800.h
 +++ b/drivers/net/wireless/rt2x00/rt2800.h
 @@ -71,6 +71,7 @@
- #define RF3053                                0x000d
  #define RF5592                                0x000f
+ #define RF3070                                0x3070
  #define RF3290                                0x3290
 +#define RF5350                                0x5350
  #define RF5360                                0x5360
  #define RF5372                                0x5372
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -2140,6 +2140,15 @@ static void rt2800_config_channel_rf53xx
-       if (rf->channel <= 14) {
-               int idx = rf->channel-1;
+@@ -2705,6 +2705,13 @@ static void rt2800_config_channel_rf53xx
  
-+              if (rt2x00_rt(rt2x00dev, RT5350)) {
-+                      static const char r59_non_bt[] = {0x0b, 0x0b,
-+                              0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a,
-+                              0x0a, 0x09, 0x08, 0x07, 0x07, 0x06};
+                               rt2800_rfcsr_write(rt2x00dev, 59,
+                                                  r59_non_bt[idx]);
++                      } else if (rt2x00_rt(rt2x00dev, RT5350)) {
++                              static const char r59_non_bt[] = {0x0b, 0x0b,
++                                      0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a,
++                                      0x0a, 0x09, 0x08, 0x07, 0x07, 0x06};
 +
-+                      rt2800_rfcsr_write(rt2x00dev, 59,
-+                                         r59_non_bt[idx]);
-+              }
-+
-               if (test_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags)) {
-                       if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
-                               /* r55/r59 value array of channel 1~14 */
-@@ -2597,6 +2606,7 @@ static void rt2800_config_channel(struct
-       case RF3322:
++                              rt2800_rfcsr_write(rt2x00dev, 59,
++                                                 r59_non_bt[idx]);
+                       }
+               }
+       }
+@@ -3142,6 +3149,7 @@ static void rt2800_config_channel(struct
                rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
                break;
+       case RF3070:
 +      case RF5350:
        case RF5360:
        case RF5370:
        case RF5372:
-@@ -2613,6 +2623,7 @@ static void rt2800_config_channel(struct
-       if (rt2x00_rf(rt2x00dev, RF3290) ||
+@@ -3159,6 +3167,7 @@ static void rt2800_config_channel(struct
+       if (rt2x00_rf(rt2x00dev, RF3070) ||
+           rt2x00_rf(rt2x00dev, RF3290) ||
            rt2x00_rf(rt2x00dev, RF3322) ||
 +          rt2x00_rf(rt2x00dev, RF5350) ||
            rt2x00_rf(rt2x00dev, RF5360) ||
            rt2x00_rf(rt2x00dev, RF5370) ||
            rt2x00_rf(rt2x00dev, RF5372) ||
-@@ -2777,7 +2788,8 @@ static void rt2800_config_channel(struct
+@@ -3399,7 +3408,8 @@ static void rt2800_config_channel(struct
        /*
         * Clear update flag
         */
                rt2800_bbp_read(rt2x00dev, 49, &bbp);
                rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0);
                rt2800_bbp_write(rt2x00dev, 49, bbp);
-@@ -3223,6 +3235,7 @@ void rt2800_vco_calibration(struct rt2x0
-               rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
-               break;
+@@ -4273,6 +4283,7 @@ void rt2800_vco_calibration(struct rt2x0
+       case RF3053:
+       case RF3070:
        case RF3290:
 +      case RF5350:
        case RF5360:
        case RF5370:
        case RF5372:
-@@ -3562,7 +3575,8 @@ static int rt2800_init_registers(struct 
-       } else if (rt2x00_rt(rt2x00dev, RT3572)) {
-               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
-               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
--      } else if (rt2x00_rt(rt2x00dev, RT5390) ||
-+      } else if (rt2x00_rt(rt2x00dev, RT5350) ||
-+                 rt2x00_rt(rt2x00dev, RT5390) ||
-                  rt2x00_rt(rt2x00dev, RT5392) ||
-                  rt2x00_rt(rt2x00dev, RT5592)) {
+@@ -4669,6 +4680,8 @@ static int rt2800_init_registers(struct 
                rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
-@@ -4215,9 +4229,13 @@ static void rt2800_init_bbp_3352(struct 
+               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
++      } else if (rt2x00_rt(rt2x00dev, RT5350)) {
++              rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+       } else {
+               rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
+               rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+@@ -5310,9 +5323,13 @@ static void rt2800_init_bbp_3352(struct 
  
        rt2800_bbp_write(rt2x00dev, 82, 0x62);
  
@@ -87,7 +84,7 @@
  
        rt2800_bbp_write(rt2x00dev, 86, 0x38);
  
-@@ -4231,9 +4249,13 @@ static void rt2800_init_bbp_3352(struct 
+@@ -5326,9 +5343,13 @@ static void rt2800_init_bbp_3352(struct 
  
        rt2800_bbp_write(rt2x00dev, 104, 0x92);
  
  
        rt2800_bbp_write(rt2x00dev, 120, 0x50);
  
-@@ -4258,6 +4280,13 @@ static void rt2800_init_bbp_3352(struct 
+@@ -5353,6 +5374,13 @@ static void rt2800_init_bbp_3352(struct 
        rt2800_bbp_write(rt2x00dev, 143, 0xa2);
  
        rt2800_bbp_write(rt2x00dev, 148, 0xc8);
  }
  
  static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev)
-@@ -4542,6 +4571,7 @@ static void rt2800_init_bbp(struct rt2x0
+@@ -5653,6 +5681,7 @@ static void rt2800_init_bbp(struct rt2x0
                rt2800_init_bbp_3290(rt2x00dev);
                break;
        case RT3352:
                rt2800_init_bbp_3352(rt2x00dev);
                break;
        case RT3390:
-@@ -5181,6 +5211,76 @@ static void rt2800_init_rfcsr_3572(struc
-       rt2800_normal_mode_setup_3xxx(rt2x00dev);
+@@ -6463,6 +6492,76 @@ static void rt2800_init_rfcsr_3593(struc
+       /* TODO: enable stream mode support */
  }
  
 +static void rt2800_init_rfcsr_5350(struct rt2x00_dev *rt2x00dev)
  static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
  {
        rt2800_rf_init_calibration(rt2x00dev, 2);
-@@ -5409,6 +5509,9 @@ static void rt2800_init_rfcsr(struct rt2
-       case RT3572:
-               rt2800_init_rfcsr_3572(rt2x00dev);
+@@ -6700,6 +6799,9 @@ static void rt2800_init_rfcsr(struct rt2
+       case RT3593:
+               rt2800_init_rfcsr_3593(rt2x00dev);
                break;
 +      case RT5350:
 +              rt2800_init_rfcsr_5350(rt2x00dev);
        case RT5390:
                rt2800_init_rfcsr_5390(rt2x00dev);
                break;
-@@ -5621,6 +5724,12 @@ static int rt2800_validate_eeprom(struct
+@@ -6949,6 +7051,12 @@ static int rt2800_validate_eeprom(struct
                rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
-               rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
+               rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
                rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);
 +      } else if (rt2x00_rt(rt2x00dev, RT5350)) {
 +              rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 1);
        } else if (rt2x00_rt(rt2x00dev, RT2860) ||
                   rt2x00_rt(rt2x00dev, RT2872)) {
                /*
-@@ -5749,6 +5858,8 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7082,6 +7190,8 @@ static int rt2800_init_eeprom(struct rt2
            rt2x00_rt(rt2x00dev, RT5390) ||
            rt2x00_rt(rt2x00dev, RT5392))
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+               rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
 +      else if (rt2x00_rt(rt2x00dev, RT5350))
 +              rf = RF5350;
        else
                rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
  
-@@ -5765,6 +5876,7 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7100,6 +7210,7 @@ static int rt2800_init_eeprom(struct rt2
        case RF3290:
        case RF3320:
        case RF3322:
        case RF5360:
        case RF5370:
        case RF5372:
-@@ -6263,7 +6375,8 @@ static int rt2800_probe_hw_mode(struct r
-                  rt2x00_rf(rt2x00dev, RF5392)) {
-               spec->num_channels = 14;
-               spec->channels = rf_vals_3x;
--      } else if (rt2x00_rf(rt2x00dev, RF3322)) {
-+      } else if (rt2x00_rf(rt2x00dev, RF3322) ||
-+                 rt2x00_rf(rt2x00dev, RF5350)) {
-               spec->num_channels = 14;
-               if (spec->clk_is_20mhz)
-                       spec->channels = rf_vals_xtal20mhz_3x;
-@@ -6364,6 +6477,7 @@ static int rt2800_probe_hw_mode(struct r
+@@ -7595,6 +7706,7 @@ static int rt2800_probe_hw_mode(struct r
+       case RF3290:
        case RF3320:
-       case RF3052:
+       case RF3322:
++      case RF5350:
+       case RF5360:
+       case RF5370:
+       case RF5372:
+@@ -7727,6 +7839,7 @@ static int rt2800_probe_hw_mode(struct r
+       case RF3053:
+       case RF3070:
        case RF3290:
 +      case RF5350:
        case RF5360:
        case RF5370:
        case RF5372:
-@@ -6401,6 +6515,7 @@ static int rt2800_probe_rt(struct rt2x00
-       case RT3352:
+@@ -7765,6 +7878,7 @@ static int rt2800_probe_rt(struct rt2x00
        case RT3390:
        case RT3572:
+       case RT3593:
 +      case RT5350:
        case RT5390:
        case RT5392:
        case RT5592:
 --- a/drivers/net/wireless/rt2x00/rt2x00.h
 +++ b/drivers/net/wireless/rt2x00/rt2x00.h
-@@ -181,6 +181,7 @@ struct rt2x00_chip {
+@@ -169,6 +169,7 @@ struct rt2x00_chip {
  #define RT3572                0x3572
  #define RT3593                0x3593
  #define RT3883                0x3883  /* WSOC */
diff --git a/package/mac80211/patches/617-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch b/package/mac80211/patches/617-rt2x00-load-eeprom-on-SoC-from-a-mtd-device-defines-.patch
deleted file mode 100644 (file)
index d5af4c9..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-From 339fe73f340161a624cc08e738d2244814852c3e Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 17 Mar 2013 00:55:04 +0100
-Subject: [PATCH] rt2x00: load eeprom on SoC from a mtd device defines inside
- OF
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/net/wireless/rt2x00/Kconfig     |    1 +
- drivers/net/wireless/rt2x00/rt2800pci.c |   44 ++++++++++++++++++++++++++-----
- 2 files changed, 39 insertions(+), 6 deletions(-)
-
---- a/drivers/net/wireless/rt2x00/Kconfig
-+++ b/drivers/net/wireless/rt2x00/Kconfig
-@@ -71,6 +71,7 @@ config RT2800PCI
-       select RT2X00_LIB_FIRMWARE
-       select RT2X00_LIB_EEPROM
-       select RT2X00_LIB_CRYPTO
-+      select MTD if SOC_RT288X || SOC_RT305X
-       depends on CRC_CCITT
-       depends on EEPROM_93CX6
-       ---help---
---- a/drivers/net/wireless/rt2x00/rt2x00eeprom.c
-+++ b/drivers/net/wireless/rt2x00/rt2x00eeprom.c
-@@ -30,12 +30,77 @@
- #include "rt2x00.h"
- #include "rt2x00lib.h"
-+#ifdef CONFIG_OF
-+#include <linux/of.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/partitions.h>
-+
-+static struct firmware mtd_fw;
-+
-+static int rt2800pci_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
-+{
-+      struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
-+      size_t retlen, len = rt2x00dev->ops->eeprom_size;
-+      int ret, size, offset = 0;
-+      struct mtd_info *mtd;
-+      const char *part;
-+      const __be32 *list;
-+      phandle phandle;
-+
-+      list = of_get_property(np, "ralink,mtd-eeprom", &size);
-+      if (!list) {
-+              dev_err(rt2x00dev->dev, "failed to load eeprom property\n");
-+              return -ENOENT;
-+      }
-+
-+      phandle = be32_to_cpup(list++);
-+      if (phandle)
-+              mtd_np = of_find_node_by_phandle(phandle);
-+      if (!mtd_np) {
-+              dev_err(rt2x00dev->dev, "failed to load mtd phandle\n");
-+              return -EINVAL;
-+      }
-+
-+      part = of_get_property(mtd_np, "label", NULL);
-+      if (!part)
-+              part = mtd_np->name;
-+
-+      mtd = get_mtd_device_nm(part);
-+      if (IS_ERR(mtd)) {
-+              dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part);
-+              return PTR_ERR(mtd);
-+      }
-+
-+      if (size > sizeof(*list))
-+              offset = be32_to_cpup(list);
-+
-+      ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom);
-+      put_mtd_device(mtd);
-+
-+      if (!ret) {
-+              rt2x00dev->eeprom_file = &mtd_fw;
-+              mtd_fw.size = len;
-+              mtd_fw.data = rt2x00dev->eeprom;
-+      }
-+
-+      return ret;
-+}
-+#else
-+static inline int rt2800pci_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
-+{
-+      return -EINVAL;
-+}
-+#endif
-+
- static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
- {
-       const struct firmware *ee;
-       char *ee_name;
-       int retval;
-+      if (!rt2800pci_read_eeprom_mtd(rt2x00dev))
-+              return 0;
-+
-       ee_name = rt2x00dev->ops->lib->get_eeprom_file_name(rt2x00dev);
-       if (!ee_name) {
-               rt2x00_err(rt2x00dev,
diff --git a/package/mac80211/patches/618-rt2x00-msi-fix.patch b/package/mac80211/patches/618-rt2x00-msi-fix.patch
deleted file mode 100644 (file)
index ceddbe4..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/drivers/net/wireless/rt2x00/rt2x00pci.c
-+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
-@@ -108,7 +108,9 @@ int rt2x00pci_probe(struct pci_dev *pci_
-               goto exit_release_regions;
-       }
-+#ifdef CONFIG_PCI_MSI
-       pci_enable_msi(pci_dev);
-+#endif
-       hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
-       if (!hw) {
-@@ -162,7 +164,9 @@ exit_free_device:
-       ieee80211_free_hw(hw);
- exit_disable_msi:
-+#ifdef CONFIG_PCI_SET_MWI
-       pci_disable_msi(pci_dev);
-+#endif
- exit_release_regions:
-       pci_release_regions(pci_dev);
-@@ -188,7 +192,9 @@ void rt2x00pci_remove(struct pci_dev *pc
-       rt2x00pci_free_reg(rt2x00dev);
-       ieee80211_free_hw(hw);
-+#ifdef CONFIG_PCI_MSI
-       pci_disable_msi(pci_dev);
-+#endif
-       /*
-        * Free the PCI device data.
diff --git a/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch
new file mode 100644 (file)
index 0000000..f820b96
--- /dev/null
@@ -0,0 +1,40 @@
+--- a/drivers/net/wireless/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/rt2x00/rt2800lib.c
+@@ -37,6 +37,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/clk.h>
++#include <linux/of.h>
+ #include "rt2x00.h"
+ #include "rt2800lib.h"
+@@ -7299,6 +7300,17 @@ static int rt2800_init_eeprom(struct rt2
+       rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+       rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
++      {
++              struct device_node *np = rt2x00dev->dev->of_node;
++              unsigned int led_polarity;
++
++              /* Allow overriding polarity from OF */
++              if (!of_property_read_u32(np, "ralink,led-polarity",
++                                        &led_polarity))
++                      rt2x00_set_field16(&eeprom, EEPROM_FREQ_LED_POLARITY,
++                                         led_polarity);
++      }
++
+       rt2x00dev->led_mcu_reg = eeprom;
+ #endif /* CPTCFG_RT2X00_LIB_LEDS */
+--- a/drivers/net/wireless/rt2x00/rt2x00leds.c
++++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
+@@ -109,6 +109,9 @@ static int rt2x00leds_register_led(struc
+       led->led_dev.name = name;
+       led->led_dev.brightness = LED_OFF;
++      if (rt2x00_is_soc(rt2x00dev))
++              led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++
+       retval = led_classdev_register(device, &led->led_dev);
+       if (retval) {
+               rt2x00_err(rt2x00dev, "Failed to register led handler\n");
diff --git a/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch b/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch
new file mode 100644 (file)
index 0000000..419cb60
--- /dev/null
@@ -0,0 +1,11 @@
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -1262,7 +1262,7 @@ static inline void rt2x00lib_set_if_comb
+        */
+       if_limit = &rt2x00dev->if_limits_ap;
+       if_limit->max = rt2x00dev->ops->max_ap_intf;
+-      if_limit->types = BIT(NL80211_IFTYPE_AP);
++      if_limit->types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION);
+ #ifdef CPTCFG_MAC80211_MESH
+       if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
+ #endif
index ef6b1af62bc350b1bd8b8facf4ec1b916bf8aedc..51c223d12ca6eb63119443d1d0c9c63b883e0adf 100644 (file)
@@ -1,13 +1,13 @@
 --- a/drivers/net/wireless/rt2x00/rt2800lib.c
 +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
-@@ -5854,10 +5854,11 @@ static int rt2800_init_eeprom(struct rt2
+@@ -7187,10 +7187,11 @@ static int rt2800_init_eeprom(struct rt2
         * RT53xx: defined in "EEPROM_CHIP_ID" field
         */
        if (rt2x00_rt(rt2x00dev, RT3290) ||
 -          rt2x00_rt(rt2x00dev, RT3352) ||
            rt2x00_rt(rt2x00dev, RT5390) ||
            rt2x00_rt(rt2x00dev, RT5392))
-               rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
+               rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf);
 +      else if (rt2x00_rt(rt2x00dev, RT3352))
 +              rf = RF3322;
        else if (rt2x00_rt(rt2x00dev, RT5350))
index 3381ba56add0255fac435c269e9224e4b7ce5cb2..484c0758932d24242d22422d171e8eb4cf9437d8 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/mwl8k.c
 +++ b/drivers/net/wireless/mwl8k.c
-@@ -5530,6 +5530,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+@@ -5529,6 +5529,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
  MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
  
  static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
diff --git a/package/mac80211/patches/750-rtlwifi-Align-private-space-in-rtl_priv-struct.patch b/package/mac80211/patches/750-rtlwifi-Align-private-space-in-rtl_priv-struct.patch
deleted file mode 100644 (file)
index 050defa..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-From 60ce314d1750fef843e9db70050e09e49f838b69 Mon Sep 17 00:00:00 2001
-From: Larry Finger <Larry.Finger@lwfinger.net>
-Date: Thu, 19 Sep 2013 02:21:35 +0000
-Subject: rtlwifi: Align private space in rtl_priv struct
-
-The private array at the end of the rtl_priv struct is not aligned.
-On ARM architecture, this causes an alignment trap and is fixed by aligning
-that array with __align(sizeof(void *)). That should properly align that
-space according to the requirements of all architectures.
-
-Reported-by: Jason Andrews <jasona@cadence.com>
-Tested-by: Jason Andrews <jasona@cadence.com>
-Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
-Cc: Stable <stable@vger.kernel.org>
-Signed-off-by: John W. Linville <linville@tuxdriver.com>
----
---- a/drivers/net/wireless/rtlwifi/wifi.h
-+++ b/drivers/net/wireless/rtlwifi/wifi.h
-@@ -2057,7 +2057,7 @@ struct rtl_priv {
-          that it points to the data allocated
-          beyond  this structure like:
-          rtl_pci_priv or rtl_usb_priv */
--      u8 priv[0];
-+      u8 priv[0] __aligned(sizeof(void *));
- };
- #define rtl_priv(hw)          (((struct rtl_priv *)(hw)->priv))
index 46de746db139f27a7b6d757dffba6ce37b3c85c4..fc874ad0497232a20d7e424a605db7d2b98fb414 100644 (file)
@@ -22,7 +22,7 @@
  static int modparam_bad_frames_preempt;
  module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
  MODULE_PARM_DESC(bad_frames_preempt,
-@@ -2742,10 +2747,10 @@ static int b43_gpio_init(struct b43_wlde
+@@ -2747,10 +2752,10 @@ static int b43_gpio_init(struct b43_wlde
        u32 mask, set;
  
        b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
index 1206923e0df2d202734e88379af5f5719b6fad9e..5cd1b8bccdfbaccacc785e0ba774c4a5f46c868c 100644 (file)
@@ -5,7 +5,7 @@
  b43-y                         += wa.o
  b43-y                         += dma.o
 -b43-y                         += pio.o
-+b43-$(CONFIG_B43_PIO)         += pio.o
++b43-$(CPTCFG_B43_PIO)         += pio.o
  b43-y                         += rfkill.o
  b43-$(CPTCFG_B43_LEDS)                += leds.o
  b43-$(CPTCFG_B43_PCMCIA)      += pcmcia.o
@@ -15,7 +15,7 @@
                        dma_reason[0], dma_reason[1],
                        dma_reason[2], dma_reason[3],
                        dma_reason[4], dma_reason[5]);
-+#ifdef CONFIG_B43_PIO
++#ifdef CPTCFG_B43_PIO
                b43err(dev->wl, "This device does not support DMA "
                               "on your system. It will now be switched to PIO.\n");
                /* Fall back to PIO transfers if we get fatal DMA errors! */
@@ -31,7 +31,7 @@
  }
  
 -
-+#ifdef CONFIG_B43_PIO
++#ifdef CPTCFG_B43_PIO
  int b43_pio_init(struct b43_wldev *dev);
  void b43_pio_free(struct b43_wldev *dev);
  
@@ -70,7 +70,7 @@
 +static inline void b43_pio_tx_resume(struct b43_wldev *dev)
 +{
 +}
-+#endif /* CONFIG_B43_PIO */
++#endif /* CPTCFG_B43_PIO */
  
  #endif /* B43_PIO_H_ */
 --- a/drivers/net/wireless/b43/Kconfig
index 56aef894bcd07e2976e1931e19e0d705b167fc9f..dea98303cd5ac2ada230e2b024c8868816691b29 100644 (file)
@@ -9,7 +9,7 @@
        antenna = b43_antenna_to_phyctl(antenna);
        ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
        /* We can't send beacons with short preamble. Would get PHY errors. */
-@@ -3100,8 +3100,8 @@ static int b43_chip_init(struct b43_wlde
+@@ -3105,8 +3105,8 @@ static int b43_chip_init(struct b43_wlde
  
        /* Select the antennae */
        if (phy->ops->set_rx_antenna)
@@ -20,7 +20,7 @@
  
        if (phy->type == B43_PHYTYPE_B) {
                value16 = b43_read16(dev, 0x005E);
-@@ -3845,7 +3845,6 @@ static int b43_op_config(struct ieee8021
+@@ -3850,7 +3850,6 @@ static int b43_op_config(struct ieee8021
        struct b43_wldev *dev;
        struct b43_phy *phy;
        struct ieee80211_conf *conf = &hw->conf;
@@ -28,7 +28,7 @@
        int err = 0;
        bool reload_bss = false;
  
-@@ -3899,11 +3898,9 @@ static int b43_op_config(struct ieee8021
+@@ -3904,11 +3903,9 @@ static int b43_op_config(struct ieee8021
        }
  
        /* Antennas for RX and management frame TX. */
@@ -42,7 +42,7 @@
  
        if (wl->radio_enabled != phy->radio_on) {
                if (wl->radio_enabled) {
-@@ -5028,6 +5025,47 @@ static int b43_op_get_survey(struct ieee
+@@ -5041,6 +5038,47 @@ static int b43_op_get_survey(struct ieee
        return 0;
  }
  
@@ -90,7 +90,7 @@
  static const struct ieee80211_ops b43_hw_ops = {
        .tx                     = b43_op_tx,
        .conf_tx                = b43_op_conf_tx,
-@@ -5049,6 +5087,8 @@ static const struct ieee80211_ops b43_hw
+@@ -5062,6 +5100,8 @@ static const struct ieee80211_ops b43_hw
        .sw_scan_complete       = b43_op_sw_scan_complete_notifier,
        .get_survey             = b43_op_get_survey,
        .rfkill_poll            = b43_rfkill_poll,
@@ -99,7 +99,7 @@
  };
  
  /* Hard-reset the chip. Do not call this directly.
-@@ -5295,6 +5335,8 @@ static int b43_one_core_attach(struct b4
+@@ -5308,6 +5348,8 @@ static int b43_one_core_attach(struct b4
        if (!wldev)
                goto out;
  
        wldev->use_pio = b43_modparam_pio;
        wldev->dev = dev;
        wldev->wl = wl;
-@@ -5385,6 +5427,9 @@ static struct b43_wl *b43_wireless_init(
+@@ -5398,6 +5440,9 @@ static struct b43_wl *b43_wireless_init(
  
        hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
  
index e55d4fe4aa8905720db872fcc5aa65d7c58ccbbe..e76758ca636e8302d8c362a0de13890e89a5b023 100644 (file)
@@ -19,7 +19,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 
 --- a/drivers/net/wireless/b43/b43.h
 +++ b/drivers/net/wireless/b43/b43.h
-@@ -1061,6 +1061,32 @@ static inline bool b43_using_pio_transfe
+@@ -1061,6 +1061,31 @@ static inline bool b43_using_pio_transfe
        return dev->__using_pio_transfers;
  }
  
@@ -34,8 +34,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +{
 +      if (b43_bus_host_is_pci(dev->dev) &&
 +          bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA &&
-+          (bcm47xx_bus.bcma.bus.chipinfo.id == 0x4716 ||
-+           bcm47xx_bus.bcma.bus.chipinfo.id == 0x5300)) {
++          bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4716) {
 +              b43_write16(dev, offset, value);
 +              b43_read16(dev, offset);
 +      } else {
@@ -62,7 +61,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
 +{
 +      if (dev->bus_type == B43_BUS_SSB)
 +              return (dev->sdev->bus->bustype == SSB_BUSTYPE_PCI);
-+#ifdef CONFIG_B43_BCMA
++#ifdef CPTCFG_B43_BCMA
 +      if (dev->bus_type == B43_BUS_BCMA)
 +              return (dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI);
 +#endif
@@ -71,6 +70,30 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
  
  struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
  struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev);
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -4437,7 +4437,7 @@ static int b43_phy_versioning(struct b43
+               u16 radio24[3];
+               for (tmp = 0; tmp < 3; tmp++) {
+-                      b43_write16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
++                      b43_wflush16(dev, B43_MMIO_RADIO24_CONTROL, tmp);
+                       radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
+               }
+@@ -4456,10 +4456,10 @@ static int b43_phy_versioning(struct b43
+                       else
+                               tmp = 0x5205017F;
+               } else {
+-                      b43_write16(dev, B43_MMIO_RADIO_CONTROL,
++                      b43_wflush16(dev, B43_MMIO_RADIO_CONTROL,
+                                   B43_RADIOCTL_ID);
+                       tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+-                      b43_write16(dev, B43_MMIO_RADIO_CONTROL,
++                      b43_wflush16(dev, B43_MMIO_RADIO_CONTROL,
+                                   B43_RADIOCTL_ID);
+                       tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH)
+                               << 16;
 --- a/drivers/net/wireless/b43/phy_common.c
 +++ b/drivers/net/wireless/b43/phy_common.c
 @@ -266,6 +266,12 @@ void b43_phy_write(struct b43_wldev *dev
@@ -86,9 +109,95 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
        if (++dev->phy.writes_counter == B43_MAX_WRITES_IN_ROW) {
                b43_read16(dev, B43_MMIO_PHY_VER);
                dev->phy.writes_counter = 0;
+--- a/drivers/net/wireless/b43/phy_ht.c
++++ b/drivers/net/wireless/b43/phy_ht.c
+@@ -1073,20 +1073,20 @@ static unsigned int b43_phy_ht_op_get_de
+ static u16 b43_phy_ht_op_read(struct b43_wldev *dev, u16 reg)
+ {
+-      b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
+       return b43_read16(dev, B43_MMIO_PHY_DATA);
+ }
+ static void b43_phy_ht_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+ {
+-      b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_PHY_DATA, value);
+ }
+ static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+                                u16 set)
+ {
+-      b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_PHY_DATA,
+                   (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+ }
+@@ -1096,14 +1096,14 @@ static u16 b43_phy_ht_op_radio_read(stru
+       /* HT-PHY needs 0x200 for read access */
+       reg |= 0x200;
+-      b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+ }
+ static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg,
+                                     u16 value)
+ {
+-      b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+ }
+--- a/drivers/net/wireless/b43/phy_lcn.c
++++ b/drivers/net/wireless/b43/phy_lcn.c
+@@ -845,20 +845,20 @@ static void b43_phy_lcn_op_adjust_txpowe
+ static u16 b43_phy_lcn_op_read(struct b43_wldev *dev, u16 reg)
+ {
+-      b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
+       return b43_read16(dev, B43_MMIO_PHY_DATA);
+ }
+ static void b43_phy_lcn_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+ {
+-      b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_PHY_DATA, value);
+ }
+ static void b43_phy_lcn_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+                                  u16 set)
+ {
+-      b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_PHY_DATA,
+                   (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+ }
+@@ -868,14 +868,14 @@ static u16 b43_phy_lcn_op_radio_read(str
+       /* LCN-PHY needs 0x200 for read access */
+       reg |= 0x200;
+-      b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+ }
+ static void b43_phy_lcn_op_radio_write(struct b43_wldev *dev, u16 reg,
+                                      u16 value)
+ {
+-      b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
++      b43_wflush16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+ }
 --- a/drivers/net/wireless/b43/phy_n.c
 +++ b/drivers/net/wireless/b43/phy_n.c
-@@ -5417,14 +5417,14 @@ static inline void check_phyreg(struct b
+@@ -5418,14 +5418,14 @@ static inline void check_phyreg(struct b
  static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
  {
        check_phyreg(dev, reg);
@@ -105,7 +214,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
        b43_write16(dev, B43_MMIO_PHY_DATA, value);
  }
  
-@@ -5432,7 +5432,7 @@ static void b43_nphy_op_maskset(struct b
+@@ -5433,7 +5433,7 @@ static void b43_nphy_op_maskset(struct b
                                 u16 set)
  {
        check_phyreg(dev, reg);
@@ -114,7 +223,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
        b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
  }
  
-@@ -5443,7 +5443,7 @@ static u16 b43_nphy_op_radio_read(struct
+@@ -5444,7 +5444,7 @@ static u16 b43_nphy_op_radio_read(struct
        /* N-PHY needs 0x100 for read access */
        reg |= 0x100;
  
@@ -123,7 +232,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
        return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
  }
  
-@@ -5452,7 +5452,7 @@ static void b43_nphy_op_radio_write(stru
+@@ -5453,7 +5453,7 @@ static void b43_nphy_op_radio_write(stru
        /* Register 1 is a 32-bit register. */
        B43_WARN_ON(reg == 1);
  
index a1eafa487b91e6364654aa16170128faed502d79..50347cdc3c3a4fce8c8a38f2c0bae826090c0f81 100644 (file)
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
-@@ -2759,6 +2759,14 @@ static int b43_gpio_init(struct b43_wlde
+@@ -2764,6 +2764,14 @@ static int b43_gpio_init(struct b43_wlde
        } else if (dev->dev->chip_id == 0x5354) {
                /* Don't allow overtaking buttons GPIOs */
                set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */
diff --git a/package/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch b/package/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch
new file mode 100644 (file)
index 0000000..185c427
--- /dev/null
@@ -0,0 +1,27 @@
+--- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
++++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
+@@ -58,19 +58,12 @@
+                                (((c) < 149) ? 3 : 4))))
+ #define BRCM_2GHZ_2412_2462   REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
+-#define BRCM_2GHZ_2467_2472   REG_RULE(2467-10, 2472+10, 20, 0, 19, \
+-                                       NL80211_RRF_NO_IR)
++#define BRCM_2GHZ_2467_2472   REG_RULE(2467-10, 2472+10, 20, 0, 19, 0)
+-#define BRCM_5GHZ_5180_5240   REG_RULE(5180-10, 5240+10, 40, 0, 21, \
+-                                       NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5260_5320   REG_RULE(5260-10, 5320+10, 40, 0, 21, \
+-                                       NL80211_RRF_DFS | \
+-                                       NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5500_5700   REG_RULE(5500-10, 5700+10, 40, 0, 21, \
+-                                       NL80211_RRF_DFS | \
+-                                       NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5745_5825   REG_RULE(5745-10, 5825+10, 40, 0, 21, \
+-                                       NL80211_RRF_NO_IR)
++#define BRCM_5GHZ_5180_5240   REG_RULE(5180-10, 5240+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5260_5320   REG_RULE(5260-10, 5320+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5500_5700   REG_RULE(5500-10, 5700+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5745_5825   REG_RULE(5745-10, 5825+10, 40, 0, 21, 0)
+ static const struct ieee80211_regdomain brcms_regdom_x2 = {
+       .n_reg_rules = 6,
diff --git a/package/mac80211/patches/851-brcmsmac-remove-extra-regulation-restriction.patch b/package/mac80211/patches/851-brcmsmac-remove-extra-regulation-restriction.patch
deleted file mode 100644 (file)
index dd1393a..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
---- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c
-+++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c
-@@ -59,23 +59,16 @@
- #define BRCM_2GHZ_2412_2462   REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
- #define BRCM_2GHZ_2467_2472   REG_RULE(2467-10, 2472+10, 20, 0, 19, \
--                                       NL80211_RRF_PASSIVE_SCAN | \
--                                       NL80211_RRF_NO_IBSS)
-+                                       0)
- #define BRCM_5GHZ_5180_5240   REG_RULE(5180-10, 5240+10, 40, 0, 21, \
--                                       NL80211_RRF_PASSIVE_SCAN | \
--                                       NL80211_RRF_NO_IBSS)
-+                                       0)
- #define BRCM_5GHZ_5260_5320   REG_RULE(5260-10, 5320+10, 40, 0, 21, \
--                                       NL80211_RRF_PASSIVE_SCAN | \
--                                       NL80211_RRF_DFS | \
--                                       NL80211_RRF_NO_IBSS)
-+                                       0)
- #define BRCM_5GHZ_5500_5700   REG_RULE(5500-10, 5700+10, 40, 0, 21, \
--                                       NL80211_RRF_PASSIVE_SCAN | \
--                                       NL80211_RRF_DFS | \
--                                       NL80211_RRF_NO_IBSS)
-+                                       0)
- #define BRCM_5GHZ_5745_5825   REG_RULE(5745-10, 5825+10, 40, 0, 21, \
--                                       NL80211_RRF_PASSIVE_SCAN | \
--                                       NL80211_RRF_NO_IBSS)
-+                                       0)
- static const struct ieee80211_regdomain brcms_regdom_x2 = {
-       .n_reg_rules = 6,
diff --git a/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch b/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch
new file mode 100644 (file)
index 0000000..a8af257
--- /dev/null
@@ -0,0 +1,109 @@
+Move the wl1251 part of the wl12xx platform data structure into a new
+structure specifically for wl1251.  Change the platform data built-in
+block and board files accordingly.
+
+Cc: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Luciano Coelho <coelho@ti.com>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Reviewed-by: Felipe Balbi <balbi@ti.com>
+
+--- a/drivers/net/wireless/ti/wilink_platform_data.c
++++ b/drivers/net/wireless/ti/wilink_platform_data.c
+@@ -23,17 +23,17 @@
+ #include <linux/err.h>
+ #include <linux/wl12xx.h>
+-static struct wl12xx_platform_data *platform_data;
++static struct wl12xx_platform_data *wl12xx_platform_data;
+ int __init wl12xx_set_platform_data(const struct wl12xx_platform_data *data)
+ {
+-      if (platform_data)
++      if (wl12xx_platform_data)
+               return -EBUSY;
+       if (!data)
+               return -EINVAL;
+-      platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
+-      if (!platform_data)
++      wl12xx_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
++      if (!wl12xx_platform_data)
+               return -ENOMEM;
+       return 0;
+@@ -41,9 +41,34 @@ int __init wl12xx_set_platform_data(cons
+ struct wl12xx_platform_data *wl12xx_get_platform_data(void)
+ {
+-      if (!platform_data)
++      if (!wl12xx_platform_data)
+               return ERR_PTR(-ENODEV);
+-      return platform_data;
++      return wl12xx_platform_data;
+ }
+ EXPORT_SYMBOL(wl12xx_get_platform_data);
++
++static struct wl1251_platform_data *wl1251_platform_data;
++
++int __init wl1251_set_platform_data(const struct wl1251_platform_data *data)
++{
++      if (wl1251_platform_data)
++              return -EBUSY;
++      if (!data)
++              return -EINVAL;
++
++      wl1251_platform_data = kmemdup(data, sizeof(*data), GFP_KERNEL);
++      if (!wl1251_platform_data)
++              return -ENOMEM;
++
++      return 0;
++}
++
++struct wl1251_platform_data *wl1251_get_platform_data(void)
++{
++      if (!wl1251_platform_data)
++              return ERR_PTR(-ENODEV);
++
++      return wl1251_platform_data;
++}
++EXPORT_SYMBOL(wl1251_get_platform_data);
+--- a/drivers/net/wireless/ti/wl1251/sdio.c
++++ b/drivers/net/wireless/ti/wl1251/sdio.c
+@@ -227,7 +227,7 @@ static int wl1251_sdio_probe(struct sdio
+       struct wl1251 *wl;
+       struct ieee80211_hw *hw;
+       struct wl1251_sdio *wl_sdio;
+-      const struct wl12xx_platform_data *wl12xx_board_data;
++      const struct wl1251_platform_data *wl1251_board_data;
+       hw = wl1251_alloc_hw();
+       if (IS_ERR(hw))
+@@ -254,11 +254,11 @@ static int wl1251_sdio_probe(struct sdio
+       wl->if_priv = wl_sdio;
+       wl->if_ops = &wl1251_sdio_ops;
+-      wl12xx_board_data = wl12xx_get_platform_data();
+-      if (!IS_ERR(wl12xx_board_data)) {
+-              wl->set_power = wl12xx_board_data->set_power;
+-              wl->irq = wl12xx_board_data->irq;
+-              wl->use_eeprom = wl12xx_board_data->use_eeprom;
++      wl1251_board_data = wl1251_get_platform_data();
++      if (!IS_ERR(wl1251_board_data)) {
++              wl->set_power = wl1251_board_data->set_power;
++              wl->irq = wl1251_board_data->irq;
++              wl->use_eeprom = wl1251_board_data->use_eeprom;
+       }
+       if (wl->irq) {
+--- a/drivers/net/wireless/ti/wl1251/spi.c
++++ b/drivers/net/wireless/ti/wl1251/spi.c
+@@ -241,7 +241,7 @@ static const struct wl1251_if_operations
+ static int wl1251_spi_probe(struct spi_device *spi)
+ {
+-      struct wl12xx_platform_data *pdata;
++      struct wl1251_platform_data *pdata;
+       struct ieee80211_hw *hw;
+       struct wl1251 *wl;
+       int ret;
diff --git a/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch b/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch
new file mode 100644 (file)
index 0000000..f2789a9
--- /dev/null
@@ -0,0 +1,118 @@
+The platform_quirk element in the platform data was used to change the
+way the IRQ is triggered.  When set, the EDGE_IRQ quirk would change
+the irqflags used and treat edge trigger differently from the rest.
+
+Instead of hiding this irq flag setting behind the quirk, have the
+board files set the flags during initialization.  This will be more
+meaningful than driver-specific quirks when we switch to DT.
+
+Additionally, fix missing gpio_request() calls in the boarding files
+(so that setting the flags actually works).
+
+Cc: Tony Lindgren <tony@atomide.com>
+Cc: Sekhar Nori <nsekhar@ti.com>
+Signed-off-by: Luciano Coelho <coelho@ti.com>
+Reviewed-by: Felipe Balbi <balbi@ti.com>
+Acked-by: Sekhar Nori <nsekhar@ti.com>
+
+--- a/drivers/net/wireless/ti/wlcore/debugfs.c
++++ b/drivers/net/wireless/ti/wlcore/debugfs.c
+@@ -502,7 +502,7 @@ static ssize_t driver_state_read(struct 
+       DRIVER_STATE_PRINT_HEX(irq);
+       /* TODO: ref_clock and tcxo_clock were moved to wl12xx priv */
+       DRIVER_STATE_PRINT_HEX(hw_pg_ver);
+-      DRIVER_STATE_PRINT_HEX(platform_quirks);
++      DRIVER_STATE_PRINT_HEX(irq_flags);
+       DRIVER_STATE_PRINT_HEX(chip.id);
+       DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
+       DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -27,6 +27,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/wl12xx.h>
+ #include <linux/interrupt.h>
++#include <linux/irq.h>
+ #include "wlcore.h"
+ #include "debug.h"
+@@ -528,7 +529,7 @@ static int wlcore_irq_locked(struct wl12
+        * In case edge triggered interrupt must be used, we cannot iterate
+        * more than once without introducing race conditions with the hardirq.
+        */
+-      if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
++      if (wl->irq_flags & IRQF_TRIGGER_RISING)
+               loopcount = 1;
+       wl1271_debug(DEBUG_IRQ, "IRQ work");
+@@ -5934,7 +5935,6 @@ struct ieee80211_hw *wlcore_alloc_hw(siz
+       wl->ap_ps_map = 0;
+       wl->ap_fw_ps_map = 0;
+       wl->quirks = 0;
+-      wl->platform_quirks = 0;
+       wl->system_hlid = WL12XX_SYSTEM_HLID;
+       wl->active_sta_count = 0;
+       wl->active_link_count = 0;
+@@ -6075,7 +6075,7 @@ static void wlcore_nvs_cb(const struct f
+       struct platform_device *pdev = wl->pdev;
+       struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
+       struct wl12xx_platform_data *pdata = pdev_data->pdata;
+-      unsigned long irqflags;
++
+       int ret;
+       irq_handler_t hardirq_fn = NULL;
+@@ -6103,29 +6103,19 @@ static void wlcore_nvs_cb(const struct f
+       wlcore_adjust_conf(wl);
+       wl->irq = platform_get_irq(pdev, 0);
+-      wl->platform_quirks = pdata->platform_quirks;
+       wl->if_ops = pdev_data->if_ops;
+-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+-      irqflags = IRQF_TRIGGER_RISING;
++      wl->irq_flags = irq_get_trigger_type(wl->irq) | IRQF_ONESHOT;
+       hardirq_fn = wlcore_hardirq;
+-#else
+-      if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) {
+-              irqflags = IRQF_TRIGGER_RISING;
+-              hardirq_fn = wlcore_hardirq;
+-      } else {
+-              irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
+-      }
+-#endif
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+       ret = compat_request_threaded_irq(&wl->irq_compat, wl->irq,
+                                         hardirq_fn, wlcore_irq,
+-                                        irqflags,
++                                        wl->irqflags,
+                                         pdev->name, wl);
+ #else
+       ret = request_threaded_irq(wl->irq, hardirq_fn, wlcore_irq,
+-                                 irqflags, pdev->name, wl);
++                                 wl->irq_flags, pdev->name, wl);
+ #endif
+       if (ret < 0) {
+               wl1271_error("request_irq() failed: %d", ret);
+--- a/drivers/net/wireless/ti/wlcore/wlcore.h
++++ b/drivers/net/wireless/ti/wlcore/wlcore.h
+@@ -188,6 +188,8 @@ struct wl1271 {
+       int irq;
++      int irq_flags;
++
+       spinlock_t wl_lock;
+       enum wlcore_state state;
+@@ -395,9 +397,6 @@ struct wl1271 {
+       /* Quirks of specific hardware revisions */
+       unsigned int quirks;
+-      /* Platform limitations */
+-      unsigned int platform_quirks;
+-
+       /* number of currently active RX BA sessions */
+       int ba_rx_session_count;
diff --git a/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch b/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch
new file mode 100644 (file)
index 0000000..6394377
--- /dev/null
@@ -0,0 +1,48 @@
+The pwr_in_suspend flag depends on the MMC settings which can be
+retrieved from the SDIO subsystem, so it doesn't need to be part of
+the platform data structure.  Move it to the platform device data that
+is passed from SDIO to wlcore.
+
+Signed-off-by: Luciano Coelho <coelho@ti.com>
+Reviewed-by: Felipe Balbi <balbi@ti.com>
+
+--- a/drivers/net/wireless/ti/wlcore/main.c
++++ b/drivers/net/wireless/ti/wlcore/main.c
+@@ -6074,7 +6074,6 @@ static void wlcore_nvs_cb(const struct f
+       struct wl1271 *wl = context;
+       struct platform_device *pdev = wl->pdev;
+       struct wlcore_platdev_data *pdev_data = dev_get_platdata(&pdev->dev);
+-      struct wl12xx_platform_data *pdata = pdev_data->pdata;
+       int ret;
+       irq_handler_t hardirq_fn = NULL;
+@@ -6127,7 +6126,7 @@ static void wlcore_nvs_cb(const struct f
+       if (!ret) {
+               wl->irq_wake_enabled = true;
+               device_init_wakeup(wl->dev, 1);
+-              if (pdata->pwr_in_suspend)
++              if (pdev_data->pwr_in_suspend)
+                       wl->hw->wiphy->wowlan = &wlcore_wowlan_support;
+       }
+ #endif
+--- a/drivers/net/wireless/ti/wlcore/sdio.c
++++ b/drivers/net/wireless/ti/wlcore/sdio.c
+@@ -260,7 +260,7 @@ static int wl1271_probe(struct sdio_func
+       dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags);
+       if (mmcflags & MMC_PM_KEEP_POWER)
+-              pdev_data->pdata->pwr_in_suspend = true;
++              pdev_data->pwr_in_suspend = true;
+       sdio_set_drvdata(func, glue);
+--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
++++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
+@@ -209,6 +209,7 @@ struct wl1271_if_operations {
+ struct wlcore_platdev_data {
+       struct wl12xx_platform_data *pdata;
+       struct wl1271_if_operations *if_ops;
++      bool pwr_in_suspend;
+ };
+ #define MAX_NUM_KEYS 14
diff --git a/package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch b/package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch
new file mode 100644 (file)
index 0000000..4b20932
--- /dev/null
@@ -0,0 +1,131 @@
+Instead of defining an enumeration with the FW specific values for the
+different clock rates, use the actual frequency instead.  Also add a
+boolean to specify whether the clock is XTAL or not.
+
+Change all board files to reflect this.
+
+Additionally, this reverts commit 26f45c (ARM: OMAP2+: Legacy support
+for wl12xx when booted with devicetree), since this is not be needed
+anymore, now that DT support for WiLink is implemented.
+
+Cc: Tony Lindgren <tony@atomide.com>
+Cc: Sekhar Nori <nsekhar@ti.com>
+Signed-off-by: Luciano Coelho <coelho@ti.com>
+Reviewed-by: Felipe Balbi <balbi@ti.com>
+
+--- a/drivers/net/wireless/ti/wl12xx/main.c
++++ b/drivers/net/wireless/ti/wl12xx/main.c
+@@ -1711,6 +1711,43 @@ static struct ieee80211_sta_ht_cap wl12x
+               },
+ };
++static const struct wl12xx_clock wl12xx_refclock_table[] = {
++      { 19200000,     false,  WL12XX_REFCLOCK_19      },
++      { 26000000,     false,  WL12XX_REFCLOCK_26      },
++      { 26000000,     true,   WL12XX_REFCLOCK_26_XTAL },
++      { 38400000,     false,  WL12XX_REFCLOCK_38      },
++      { 38400000,     true,   WL12XX_REFCLOCK_38_XTAL },
++      { 52000000,     false,  WL12XX_REFCLOCK_52      },
++      { 0,            false,  0 }
++};
++
++static const struct wl12xx_clock wl12xx_tcxoclock_table[] = {
++      { 16368000,     true,   WL12XX_TCXOCLOCK_16_368 },
++      { 16800000,     true,   WL12XX_TCXOCLOCK_16_8   },
++      { 19200000,     true,   WL12XX_TCXOCLOCK_19_2   },
++      { 26000000,     true,   WL12XX_TCXOCLOCK_26     },
++      { 32736000,     true,   WL12XX_TCXOCLOCK_32_736 },
++      { 33600000,     true,   WL12XX_TCXOCLOCK_33_6   },
++      { 38400000,     true,   WL12XX_TCXOCLOCK_38_4   },
++      { 52000000,     true,   WL12XX_TCXOCLOCK_52     },
++      { 0,            false,  0 }
++};
++
++static int wl12xx_get_clock_idx(const struct wl12xx_clock *table,
++                              u32 freq, bool xtal)
++{
++      int i = 0;
++
++      while(table[i].freq != 0) {
++              if ((table[i].freq == freq) &&
++                  (table[i].xtal == xtal))
++                      return table[i].hw_idx;
++              i++;
++      };
++
++      return -EINVAL;
++}
++
+ static int wl12xx_setup(struct wl1271 *wl)
+ {
+       struct wl12xx_priv *priv = wl->priv;
+@@ -1732,7 +1769,16 @@ static int wl12xx_setup(struct wl1271 *w
+       wl12xx_conf_init(wl);
+       if (!fref_param) {
+-              priv->ref_clock = pdata->board_ref_clock;
++              priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
++                                                     pdata->ref_clock_freq,
++                                                     pdata->ref_clock_xtal);
++              if (priv->ref_clock < 0) {
++                      wl1271_error("Invalid ref_clock frequency (%d Hz, %s)",
++                              pdata->ref_clock_freq,
++                              pdata->ref_clock_xtal ? "XTAL" : "not XTAL");
++
++                      return priv->ref_clock;
++              }
+       } else {
+               if (!strcmp(fref_param, "19.2"))
+                       priv->ref_clock = WL12XX_REFCLOCK_19;
+@@ -1751,7 +1797,15 @@ static int wl12xx_setup(struct wl1271 *w
+       }
+       if (!tcxo_param) {
+-              priv->tcxo_clock = pdata->board_tcxo_clock;
++              priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
++                                                      pdata->tcxo_clock_freq,
++                                                      true);
++              if (priv->tcxo_clock < 0) {
++                      wl1271_error("Invalid tcxo_clock frequency (%d Hz)",
++                              pdata->tcxo_clock_freq);
++
++                      return priv->tcxo_clock;
++              }
+       } else {
+               if (!strcmp(tcxo_param, "19.2"))
+                       priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
+--- a/drivers/net/wireless/ti/wl12xx/wl12xx.h
++++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h
+@@ -79,4 +79,32 @@ struct wl12xx_priv {
+       struct wl127x_rx_mem_pool_addr *rx_mem_addr;
+ };
++/* Reference clock values */
++enum {
++      WL12XX_REFCLOCK_19      = 0, /* 19.2 MHz */
++      WL12XX_REFCLOCK_26      = 1, /* 26 MHz */
++      WL12XX_REFCLOCK_38      = 2, /* 38.4 MHz */
++      WL12XX_REFCLOCK_52      = 3, /* 52 MHz */
++      WL12XX_REFCLOCK_38_XTAL = 4, /* 38.4 MHz, XTAL */
++      WL12XX_REFCLOCK_26_XTAL = 5, /* 26 MHz, XTAL */
++};
++
++/* TCXO clock values */
++enum {
++      WL12XX_TCXOCLOCK_19_2   = 0, /* 19.2MHz */
++      WL12XX_TCXOCLOCK_26     = 1, /* 26 MHz */
++      WL12XX_TCXOCLOCK_38_4   = 2, /* 38.4MHz */
++      WL12XX_TCXOCLOCK_52     = 3, /* 52 MHz */
++      WL12XX_TCXOCLOCK_16_368 = 4, /* 16.368 MHz */
++      WL12XX_TCXOCLOCK_32_736 = 5, /* 32.736 MHz */
++      WL12XX_TCXOCLOCK_16_8   = 6, /* 16.8 MHz */
++      WL12XX_TCXOCLOCK_33_6   = 7, /* 33.6 MHz */
++};
++
++struct wl12xx_clock {
++      u32     freq;
++      bool    xtal;
++      u8      hw_idx;
++};
++
+ #endif /* __WL12XX_PRIV_H__ */
diff --git a/package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch b/package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch
new file mode 100644 (file)
index 0000000..9e1d190
--- /dev/null
@@ -0,0 +1,118 @@
+If platform data is not available, try to get the required information
+from the device tree.  Register an OF match table and parse the
+appropriate device tree nodes.
+
+Parse interrupt property only, for now.
+
+Signed-off-by: Luciano Coelho <coelho@ti.com>
+Reviewed-by: Felipe Balbi <balbi@ti.com>
+
+--- a/drivers/net/wireless/ti/wlcore/sdio.c
++++ b/drivers/net/wireless/ti/wlcore/sdio.c
+@@ -30,7 +30,7 @@
+ #include <linux/mmc/sdio_ids.h>
+ #include <linux/mmc/card.h>
+ #include <linux/mmc/host.h>
+-#include <linux/gpio.h>
++#include <linux/of_irq.h>
+ #include <linux/wl12xx.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/printk.h>
+@@ -214,6 +214,43 @@ static struct wl1271_if_operations sdio_
+       .set_block_size = wl1271_sdio_set_block_size,
+ };
++static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
++{
++      struct wl12xx_platform_data *pdata;
++      struct device_node *np = dev->of_node;
++
++      if (!np) {
++              np = of_find_matching_node(NULL, dev->driver->of_match_table);
++              if (!np) {
++                      dev_notice(dev, "device tree node not available\n");
++                      pdata = ERR_PTR(-ENODEV);
++                      goto out;
++              }
++      }
++
++      pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
++      if (!pdata) {
++              dev_err(dev, "can't allocate platform data\n");
++              pdata = ERR_PTR(-ENODEV);
++              goto out;
++      }
++
++      pdata->irq = irq_of_parse_and_map(np, 0);
++      if (pdata->irq < 0) {
++              dev_err(dev, "can't get interrupt gpio from the device tree\n");
++              goto out_free;
++      }
++
++      goto out;
++
++out_free:
++      kfree(pdata);
++      pdata = ERR_PTR(-ENODEV);
++
++out:
++      return pdata;
++}
++
+ static int wl1271_probe(struct sdio_func *func,
+                                 const struct sdio_device_id *id)
+ {
+@@ -248,11 +285,22 @@ static int wl1271_probe(struct sdio_func
+       /* Use block mode for transferring over one block size of data */
+       func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
++      /* The pdata allocated here is freed when the device is freed,
++       * so we don't need an additional out label to free it in case
++       * of error further on.
++       */
++
++      /* Try to get legacy platform data from the board file */
+       pdev_data->pdata = wl12xx_get_platform_data();
+       if (IS_ERR(pdev_data->pdata)) {
+-              ret = PTR_ERR(pdev_data->pdata);
+-              dev_err(glue->dev, "missing wlan platform data: %d\n", ret);
+-              goto out_free_glue;
++              dev_info(&func->dev,
++                       "legacy platform data not found, trying device tree\n");
++
++              pdev_data->pdata = wlcore_get_pdata_from_of(&func->dev);
++              if (IS_ERR(pdev_data->pdata)) {
++                      dev_err(&func->dev, "can't get platform data\n");
++                      goto out_free_glue;
++              }
+       }
+       /* if sdio can keep power while host is suspended, enable wow */
+@@ -386,16 +434,25 @@ static const struct dev_pm_ops wl1271_sd
+ };
+ #endif
++static const struct of_device_id wlcore_sdio_of_match_table[] = {
++      { .compatible = "ti,wilink6" },
++      { .compatible = "ti,wilink7" },
++      { .compatible = "ti,wilink8" },
++      { }
++};
++MODULE_DEVICE_TABLE(of, wlcore_sdio_of_match_table);
++
+ static struct sdio_driver wl1271_sdio_driver = {
+       .name           = "wl1271_sdio",
+       .id_table       = wl1271_devices,
+       .probe          = wl1271_probe,
+       .remove         = wl1271_remove,
+-#ifdef CONFIG_PM
+       .drv = {
++#ifdef CONFIG_PM
+               .pm = &wl1271_sdio_pm_ops,
+-      },
+ #endif
++              .of_match_table = of_match_ptr(wlcore_sdio_of_match_table),
++      },
+ };
+ static int __init wl1271_init(void)
diff --git a/package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch b/package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch
new file mode 100644 (file)
index 0000000..be1f9ad
--- /dev/null
@@ -0,0 +1,50 @@
+Add refclock and tcxoclock as clock providers in WiLink.  These clocks
+are not accesible outside the WiLink module, but they are registered
+in the clock framework anyway.  Only the WiLink chip consumes these
+clocks.
+
+In theory, the WiLink chip could be connected to external clocks
+instead of using these internal clocks, so make the clock consumer
+code generic enough.  If external clocks are used, then the internal
+clock device tree nodes are not necessary, but the external ones must
+be specified.
+
+Signed-off-by: Luciano Coelho <coelho@ti.com>
+Reviewed-by: Felipe Balbi <balbi@ti.com>
+
+--- a/drivers/net/wireless/ti/wlcore/sdio.c
++++ b/drivers/net/wireless/ti/wlcore/sdio.c
+@@ -34,6 +34,7 @@
+ #include <linux/wl12xx.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/printk.h>
++#include <linux/clk-provider.h>
+ #include "wlcore.h"
+ #include "wl12xx_80211.h"
+@@ -214,10 +215,15 @@ static struct wl1271_if_operations sdio_
+       .set_block_size = wl1271_sdio_set_block_size,
+ };
++static const struct of_device_id wlcore_sdio_of_clk_match_table[] = {
++      { .compatible = "ti,wilink-clock" },
++};
++
+ static struct wl12xx_platform_data *wlcore_get_pdata_from_of(struct device *dev)
+ {
+       struct wl12xx_platform_data *pdata;
+       struct device_node *np = dev->of_node;
++      struct device_node *clock_node;
+       if (!np) {
+               np = of_find_matching_node(NULL, dev->driver->of_match_table);
+@@ -241,6 +247,9 @@ static struct wl12xx_platform_data *wlco
+               goto out_free;
+       }
++      for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
++              of_fixed_clk_setup(clock_node);
++
+       goto out;
+ out_free:
diff --git a/package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch b/package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch
new file mode 100644 (file)
index 0000000..09ff4af
--- /dev/null
@@ -0,0 +1,90 @@
+Read the clock nodes from the device tree and use them to set the
+frequency for the refclock and the tcxo clock.
+
+Also, call sdio_set_drvdata() earlier, so the glue is already set in
+the driver data when we call wlcore_get_pdata_from_of() and we don't
+need to pass it as a parameter.
+
+Signed-off-by: Luciano Coelho <coelho@ti.com>
+Reviewed-by: Felipe Balbi <balbi@ti.com>
+
+--- a/drivers/net/wireless/ti/wlcore/sdio.c
++++ b/drivers/net/wireless/ti/wlcore/sdio.c
+@@ -53,6 +53,7 @@ static bool dump = false;
+ struct wl12xx_sdio_glue {
+       struct device *dev;
+       struct platform_device *core;
++      struct clk *refclock, *tcxoclock;
+ };
+ static const struct sdio_device_id wl1271_devices[] = {
+@@ -224,6 +225,7 @@ static struct wl12xx_platform_data *wlco
+       struct wl12xx_platform_data *pdata;
+       struct device_node *np = dev->of_node;
+       struct device_node *clock_node;
++      struct wl12xx_sdio_glue *glue = sdio_get_drvdata(dev_to_sdio_func(dev));
+       if (!np) {
+               np = of_find_matching_node(NULL, dev->driver->of_match_table);
+@@ -250,6 +252,26 @@ static struct wl12xx_platform_data *wlco
+       for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
+               of_fixed_clk_setup(clock_node);
++      /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */
++      glue->refclock = of_clk_get_by_name(np, "refclock");
++      if (IS_ERR(glue->refclock)) {
++              dev_err(dev, "couldn't find refclock on the device tree\n");
++              glue->refclock = NULL;
++      } else {
++              clk_prepare_enable(glue->refclock);
++              pdata->ref_clock_freq = clk_get_rate(glue->refclock);
++      }
++
++      /* TODO: make sure we have this when needed (ie. for WL7) */
++      glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock");
++      if (IS_ERR(glue->tcxoclock)) {
++              dev_err(dev, "couldn't find tcxoclock on the device tree\n");
++              glue->tcxoclock = NULL;
++      } else {
++              clk_prepare_enable(glue->tcxoclock);
++              pdata->ref_clock_freq = clk_get_rate(glue->tcxoclock);
++      }
++
+       goto out;
+ out_free:
+@@ -294,6 +316,8 @@ static int wl1271_probe(struct sdio_func
+       /* Use block mode for transferring over one block size of data */
+       func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
++      sdio_set_drvdata(func, glue);
++
+       /* The pdata allocated here is freed when the device is freed,
+        * so we don't need an additional out label to free it in case
+        * of error further on.
+@@ -319,8 +343,6 @@ static int wl1271_probe(struct sdio_func
+       if (mmcflags & MMC_PM_KEEP_POWER)
+               pdev_data->pwr_in_suspend = true;
+-      sdio_set_drvdata(func, glue);
+-
+       /* Tell PM core that we don't need the card to be powered now */
+       pm_runtime_put_noidle(&func->dev);
+@@ -387,6 +409,16 @@ static void wl1271_remove(struct sdio_fu
+ {
+       struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func);
++      if (glue->refclock) {
++              clk_disable_unprepare(glue->refclock);
++              clk_put(glue->refclock);
++      }
++
++      if (glue->tcxoclock) {
++              clk_disable_unprepare(glue->tcxoclock);
++              clk_put(glue->tcxoclock);
++      }
++
+       /* Undo decrement done above in wl1271_probe */
+       pm_runtime_get_noresume(&func->dev);
diff --git a/package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch b/package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch
new file mode 100644 (file)
index 0000000..6b09177
--- /dev/null
@@ -0,0 +1,96 @@
+The fref and the tcxo clocks settings are optional in some platforms.
+WiLink8 doesn't need either, so we don't check the values.  WiLink 6
+only needs the fref clock, so we check that it is valid or return with
+an error.  WiLink7 needs both clocks, if either is not available we
+return with an error.
+
+Signed-off-by: Luciano Coelho <coelho@ti.com>
+Reviewed-by: Felipe Balbi <balbi@ti.com>
+
+--- a/drivers/net/wireless/ti/wl12xx/main.c
++++ b/drivers/net/wireless/ti/wl12xx/main.c
+@@ -930,6 +930,11 @@ static int wl128x_boot_clk(struct wl1271
+       u16 sys_clk_cfg;
+       int ret;
++      if ((priv->ref_clock < 0) || (priv->tcxo_clock < 0)) {
++              wl1271_error("Missing fref and/or tcxo clock settings\n");
++              return -EINVAL;
++      }
++
+       /* For XTAL-only modes, FREF will be used after switching from TCXO */
+       if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
+           priv->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
+@@ -979,6 +984,11 @@ static int wl127x_boot_clk(struct wl1271
+       u32 clk;
+       int ret;
++      if (priv->ref_clock < 0) {
++              wl1271_error("Missing fref clock settings\n");
++              return -EINVAL;
++      }
++
+       if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
+               wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
+@@ -1768,7 +1778,7 @@ static int wl12xx_setup(struct wl1271 *w
+       wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap);
+       wl12xx_conf_init(wl);
+-      if (!fref_param) {
++      if (!fref_param && (pdata->ref_clock_freq > 0)) {
+               priv->ref_clock = wl12xx_get_clock_idx(wl12xx_refclock_table,
+                                                      pdata->ref_clock_freq,
+                                                      pdata->ref_clock_xtal);
+@@ -1779,6 +1789,8 @@ static int wl12xx_setup(struct wl1271 *w
+                       return priv->ref_clock;
+               }
++      } else if (!fref_param) {
++              priv->ref_clock = -EINVAL;
+       } else {
+               if (!strcmp(fref_param, "19.2"))
+                       priv->ref_clock = WL12XX_REFCLOCK_19;
+@@ -1796,7 +1808,7 @@ static int wl12xx_setup(struct wl1271 *w
+                       wl1271_error("Invalid fref parameter %s", fref_param);
+       }
+-      if (!tcxo_param) {
++      if (!fref_param && (pdata->tcxo_clock_freq > 0)) {
+               priv->tcxo_clock = wl12xx_get_clock_idx(wl12xx_tcxoclock_table,
+                                                       pdata->tcxo_clock_freq,
+                                                       true);
+@@ -1806,7 +1818,9 @@ static int wl12xx_setup(struct wl1271 *w
+                       return priv->tcxo_clock;
+               }
+-      } else {
++      } else if (!fref_param) {
++              priv->tcxo_clock = -EINVAL;
++      }else {
+               if (!strcmp(tcxo_param, "19.2"))
+                       priv->tcxo_clock = WL12XX_TCXOCLOCK_19_2;
+               else if (!strcmp(tcxo_param, "26"))
+--- a/drivers/net/wireless/ti/wlcore/sdio.c
++++ b/drivers/net/wireless/ti/wlcore/sdio.c
+@@ -252,20 +252,16 @@ static struct wl12xx_platform_data *wlco
+       for_each_matching_node(clock_node, wlcore_sdio_of_clk_match_table)
+               of_fixed_clk_setup(clock_node);
+-      /* TODO: make sure we have this when needed (ie. for WL6 and WL7) */
+       glue->refclock = of_clk_get_by_name(np, "refclock");
+       if (IS_ERR(glue->refclock)) {
+-              dev_err(dev, "couldn't find refclock on the device tree\n");
+               glue->refclock = NULL;
+       } else {
+               clk_prepare_enable(glue->refclock);
+               pdata->ref_clock_freq = clk_get_rate(glue->refclock);
+       }
+-      /* TODO: make sure we have this when needed (ie. for WL7) */
+       glue->tcxoclock = of_clk_get_by_name(np, "tcxoclock");
+       if (IS_ERR(glue->tcxoclock)) {
+-              dev_err(dev, "couldn't find tcxoclock on the device tree\n");
+               glue->tcxoclock = NULL;
+       } else {
+               clk_prepare_enable(glue->tcxoclock);
diff --git a/package/mac80211/patches/a00-ath9k_platform_h_backup.patch b/package/mac80211/patches/a00-ath9k_platform_h_backup.patch
new file mode 100644 (file)
index 0000000..5a74fbf
--- /dev/null
@@ -0,0 +1,22 @@
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -676,8 +676,7 @@ static int ath9k_init_soc_platform(struc
+                       return ret;
+       }
+-      if (pdata->tx_gain_buffalo)
+-              ah->config.tx_gain_buffalo = true;
++      ah->config.tx_gain_buffalo = true;
+       return ret;
+ }
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -33,7 +33,6 @@ struct ath9k_platform_data {
+       bool endian_check;
+       bool is_clk_25mhz;
+-      bool tx_gain_buffalo;
+       bool disable_2ghz;
+       bool disable_5ghz;