diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-03-14 10:53:42 +0000 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2014-03-14 10:53:42 +0000 |
commit | 705d7a8aa438a21daa646e1dc8c5d0a45295de0c (patch) | |
tree | fc4abc713ed39e07d94d500e5f7d44cbc985f43e /package | |
parent | 9b1e65073a8b1a571c390a1041bfe7fcd07d97ba (diff) | |
download | upstream-705d7a8aa438a21daa646e1dc8c5d0a45295de0c.tar.gz upstream-705d7a8aa438a21daa646e1dc8c5d0a45295de0c.tar.bz2 upstream-705d7a8aa438a21daa646e1dc8c5d0a45295de0c.zip |
AA: mac80211: backport package from trunk r39886
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
git-svn-id: svn://svn.openwrt.org/openwrt/branches/attitude_adjustment@39928 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package')
84 files changed, 7214 insertions, 2932 deletions
diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index e4fa9252f1..d9149d9cc5 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -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)) diff --git a/package/mac80211/files/lib/wifi/mac80211.sh b/package/mac80211/files/lib/wifi/mac80211.sh index 20f6bfa93c..1994ca38d4 100644 --- a/package/mac80211/files/lib/wifi/mac80211.sh +++ b/package/mac80211/files/lib/wifi/mac80211.sh @@ -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" ] && { diff --git a/package/mac80211/files/regdb.txt b/package/mac80211/files/regdb.txt index b250e6926e..2badb21c45 100644 --- a/package/mac80211/files/regdb.txt +++ b/package/mac80211/files/regdb.txt @@ -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) diff --git a/package/mac80211/patches/001-fix_build.patch b/package/mac80211/patches/001-fix_build.patch index c541985cf3..26b327ac8e 100644 --- a/package/mac80211/patches/001-fix_build.patch +++ b/package/mac80211/patches/001-fix_build.patch @@ -128,7 +128,7 @@ + @$(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 index 0000000000..584fb05ff5 --- /dev/null +++ b/package/mac80211/patches/004-backports-add-led_trigger_blink-_oneshot.patch @@ -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 */ diff --git a/package/mac80211/patches/020-disable_tty_set_termios.patch b/package/mac80211/patches/020-disable_tty_set_termios.patch index 89c6a60e13..e6d4ff6e9d 100644 --- a/package/mac80211/patches/020-disable_tty_set_termios.patch +++ b/package/mac80211/patches/020-disable_tty_set_termios.patch @@ -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 diff --git a/package/mac80211/patches/030-rt2x00_options.patch b/package/mac80211/patches/030-rt2x00_options.patch index 789a77ab12..5ee52a240d 100644 --- a/package/mac80211/patches/030-rt2x00_options.patch +++ b/package/mac80211/patches/030-rt2x00_options.patch @@ -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 @@ -30,7 +36,12 @@ 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 + diff --git a/package/mac80211/patches/060-no_local_ssb_bcma.patch b/package/mac80211/patches/060-no_local_ssb_bcma.patch index 5e8d421aa5..f4b9470627 100644 --- a/package/mac80211/patches/060-no_local_ssb_bcma.patch +++ b/package/mac80211/patches/060-no_local_ssb_bcma.patch @@ -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 @@ -52,12 +52,12 @@ -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/ @@ -65,10 +65,10 @@ -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 index 0000000000..4654bc8ea4 --- /dev/null +++ b/package/mac80211/patches/100-revert_aes_ccm_port.patch @@ -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; + } + diff --git a/package/mac80211/patches/150-disable_addr_notifier.patch b/package/mac80211/patches/150-disable_addr_notifier.patch index 92c1909981..7b50154e86 100644 --- a/package/mac80211/patches/150-disable_addr_notifier.patch +++ b/package/mac80211/patches/150-disable_addr_notifier.patch @@ -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); diff --git a/package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch b/package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch index d9672d473f..21516ffde9 100644 --- a/package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch +++ b/package/mac80211/patches/201-ath5k-WAR-for-AR71xx-PCI-bug.patch @@ -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) { diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index 73f440bd3b..1da7941d21 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -1,1234 +1,4142 @@ ---- 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); ---- 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; +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 + } ---- 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; -- } -- -- 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); -- -- res = sta_info_insert(sta); -- if (res) { -- /* STA has been freed */ -- goto err_del_interface; + 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); - -- 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); -- } + if (AR_SREV_9100(ah)) +- udelay(10000); ++ mdelay(10); + else + udelay(50); - /* - * 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; +--- 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 } -+static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, -+ struct sk_buff *skb) + /** ++ * 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) +{ -+ 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; -+ -+ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; -+ if (baselen > skb->len) -+ return; -+ -+ ieee802_11_parse_elems(mgmt->u.probe_resp.variable, -+ skb->len - baselen, false, &elems); -+ -+ rates = ieee80211_sta_get_rates(local, &elems, band, NULL); -+ -+ rcu_read_lock(); -+ -+ sta = sta_info_get(sdata, sdata->u.wds.remote_addr); ++ /* 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)); ++} + -+ if (!sta) { -+ rcu_read_unlock(); -+ sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, -+ GFP_KERNEL); -+ if (!sta) -+ return; ++/** + * 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); ++} + -+ new = true; ++/** + * 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 +@@ -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, ¶ms->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, ¶ms->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); + -+ sta->last_rx = jiffies; -+ sta->sta.supp_rates[band] = rates; -+ -+ if (elems.ht_cap_elem) -+ ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, -+ elems.ht_cap_elem, sta); -+ -+ if (elems.wmm_param) -+ set_sta_flag(sta, WLAN_STA_WME); + 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 (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); + 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; + } + -+ rcu_read_unlock(); -+} + /* 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); + - static void ieee80211_iface_work(struct work_struct *work) - { - struct ieee80211_sub_if_data *sdata = -@@ -1220,6 +1265,9 @@ static void ieee80211_iface_work(struct - break; - ieee80211_mesh_rx_queued_mgmt(sdata, skb); - break; -+ case NL80211_IFTYPE_WDS: -+ ieee80211_wds_rx_queued_mgmt(sdata, skb); -+ break; - default: - WARN(1, "frame for unexpected interface type"); - 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; -+ } + 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; + - 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; + 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); } - static void + 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/iface.c ++++ b/net/mac80211/iface.c +@@ -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); +- +- if (sdata->vif.type == NL80211_IFTYPE_ADHOC) ++ break; ++ case NL80211_IFTYPE_ADHOC: + ieee80211_ibss_stop(sdata); +- ++ 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 -@@ -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); +@@ -599,10 +599,10 @@ static int ieee80211_is_unicast_robust_m + { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; -- /* 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) - break; +- if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) ++ if (is_multicast_ether_addr(hdr->addr1)) + return 0; -@@ -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 - } - 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; -+ - 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)); +- return ieee80211_is_robust_mgmt_frame(hdr); ++ return ieee80211_is_robust_mgmt_frame(skb); } -+static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, -+ struct sk_buff *skb) -+{ -+ 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; -+ -+ if (WARN_ON(--txq->pending_frames < 0)) -+ txq->pending_frames = 0; + +@@ -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); + -+ if (txq->stopped && -+ txq->pending_frames < sc->tx.txq_max_pending[q]) { -+ ieee80211_wake_queue(sc->hw, q); -+ txq->stopped = false; -+ } -+} ++ /* 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; ++ } + - static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) - { - 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 (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 (!bf) { - __skb_unlink(skb, &tid->buf_q); -+ ath_txq_skb_done(sc, txq, skb); - ieee80211_free_txskb(sc->hw, skb); - continue; + 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); } -@@ -1824,6 +1848,7 @@ static void ath_tx_send_ampdu(struct ath - 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; +- 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); } -@@ -2090,6 +2115,7 @@ int ath_tx_start(struct ieee80211_hw *hw - 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; + return err; +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg - 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); + rdev->opencount--; - __skb_queue_tail(&txq->complete_q, skb); -- -- q = skb_get_queue_mapping(skb); -- if (txq == sc->tx.uapsdq) -- txq = sc->tx.txq_map[q]; +- 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; - -- if (txq == sc->tx.txq_map[q]) { -- if (WARN_ON(--txq->pending_frames < 0)) -- txq->pending_frames = 0; + /* + * 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; + } - -- 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); +- wdev->beacon_interval = 0; } - 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; + 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 (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); + 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; + -+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { -+ if (!ATH_TXQ_SETUP(sc, i)) ++ 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; -+ -+ 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); ++ } ++ 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 ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx != 3) -@@ -543,21 +553,10 @@ chip_reset: + 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; - static int ath_reset(struct ath_softc *sc) - { -- int i, r; -+ int r; +- 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; + } - 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)) -- 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); + 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); + } - return r; -@@ -2094,7 +2093,7 @@ static void ath9k_wow_add_pattern(struct +-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 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; + struct sk_buff *msg; ---- 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 + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) +- return; ++ return NULL; - #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 + 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; + } - /* 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; +- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, +- NL80211_MCGRP_SCAN, GFP_KERNEL); ++ return msg; + } - p = &wow->patterns[i]; ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1698,7 +1698,7 @@ struct cfg80211_pmksa { - }; +-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; +- +- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return; - /** -- * 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 { - }; +- 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; - /** -- * 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, - }; +- 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); - /** -- * 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 ++void nl80211_send_ap_stopped(struct wireless_dev *wdev) ++{ ++ struct wiphy *wiphy = wdev->wiphy; ++ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); ++ struct sk_buff *msg; ++ void *hdr; + - /** - * 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) ++ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); ++ if (!msg) + return; + - /* - * 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 ++ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP); ++ if (!hdr) ++ goto out; ++ ++ 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; ++ ++ genlmsg_end(msg, hdr); ++ ++ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0, ++ NL80211_MCGRP_MLME, GFP_KERNEL); ++ return; ++ out: ++ nlmsg_free(msg); ++} ++ + /* initialisation/exit functions */ - 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); + 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); ++ + 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++; } - EXPORT_SYMBOL(cfg80211_testmode_event); + +-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 -@@ -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); + ASSERT_RTNL(); -- genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); -+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, -+ nl80211_mlme_mcgrp.id, gfp); - return; +- request = rdev->scan_req; ++ if (rdev->scan_msg) { ++ nl80211_send_scan_result(rdev, rdev->scan_msg); ++ rdev->scan_msg = NULL; ++ 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 ++ request = rdev->scan_req; + if (!request) + return; - void wiphy_regulatory_register(struct wiphy *wiphy) - { -+ struct regulatory_request *lr; +@@ -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); + - if (!reg_dev_ignore_cell_hint(wiphy)) - reg_num_devs_support_basehint++; + #ifdef CPTCFG_CFG80211_WEXT + if (wdev->netdev && !request->aborted) { + memset(&wrqu, 0, sizeof(wrqu)); +@@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg802 -- wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); -+ lr = get_last_request(); -+ wiphy_update_regulatory(wiphy, lr->initiator); + rdev->scan_req = NULL; + kfree(request); ++ ++ if (!send_message) ++ rdev->scan_msg = msg; ++ else ++ nl80211_send_scan_result(rdev, msg); } - 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(); + 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(); } - int __init regulatory_init(void) +@@ -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 -@@ -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; +@@ -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 } -- 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 + 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; - void cfg80211_sme_auth_timeout(struct wireless_dev *wdev) + 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( { -- cfg80211_sme_free(wdev); -+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); -+ -+ if (!wdev->conn) -+ return; + struct ieee80211_sub_if_data *sdata; + ++ lockdep_assert_held(&local->mtx); + -+ wdev->conn->state = CFG80211_CONN_AUTH_FAILED; -+ schedule_work(&rdev->conn_work); + 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); } - void cfg80211_sme_disassoc(struct wireless_dev *wdev) -@@ -399,7 +416,13 @@ void cfg80211_sme_disassoc(struct wirele + 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; - void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev) - { -- cfg80211_sme_disassoc(wdev); -+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); ++ sdata_assert_lock(sdata); + -+ if (!wdev->conn) -+ return; + 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; + -+ wdev->conn->state = CFG80211_CONN_ASSOC_FAILED; -+ schedule_work(&rdev->conn_work); ++ /* avoid excessive retries for probe request to wildcard SSIDs */ ++ if (pos[1] == 0) ++ IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK; ++ + ieee80211_tx_skb(sdata, skb); } - 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)) +--- 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); ++ + 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; ---- 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); + +- 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 rt2x00queue_pause_queue(struct data_queue *queue) -+void rt2x00queue_pause_queue_nocheck(struct data_queue *queue) +-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) { -- 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 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) +-); - - switch (queue->qid) { - case QID_AC_VO: - case QID_AC_VI: -@@ -958,6 +953,15 @@ void rt2x00queue_pause_queue(struct data + 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 EVENT_IBSS_JOINED: +- __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid); ++ __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, ++ ev->ij.channel); + break; + } + 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; ++ ++ /* 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; - } - } -+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; +@@ -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; + -+ rt2x00queue_pause_queue_nocheck(queue); -+} - EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue); ++ 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; + } + + 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; + + 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; - void rt2x00queue_unpause_queue(struct data_queue *queue) -@@ -1019,7 +1023,7 @@ void rt2x00queue_stop_queue(struct data_ +- 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; + } -- rt2x00queue_pause_queue(queue); -+ rt2x00queue_pause_queue_nocheck(queue); +--- 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 - queue->rt2x00dev->ops->lib->stop_queue(queue); + 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]; + }; ---- 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) +@@ -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) { -+ 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. - */ -- 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; + 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; + } } -@@ -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 + + /* 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]; - 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 + /* 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; } + } - 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; +-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; -+ /* -+ * 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. -+ */ - 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; +@@ -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); ++ ++ /* Detect phase outlier */ ++ ar9003_hw_detect_outlier(coeff->phs_coeff[i], ++ nmeasurement, ++ MAX_PHS_DELTA); ++ } } - ret |= chandef_downgrade(chandef); - } + 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 (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"); + 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; -@@ -384,7 +395,7 @@ static int ieee80211_config_bw(struct ie + 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; + } - /* 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); +- 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; - /* - * 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); +- 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 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); + return; + +@@ -1409,7 +1484,7 @@ skip_tx_iqcal: } - 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; + 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); -+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev))) -+ return -EIO; +@@ -1455,14 +1530,38 @@ skip_tx_iqcal: + return true; + } + ++static bool do_ar9003_agc_cal(struct ath_hw *ah) ++{ ++ struct ath_common *common = ath9k_hw_common(ah); ++ bool status; + - /* - * Send signal to firmware during boot time. ++ REG_WRITE(ah, AR_PHY_AGC_CONTROL, ++ REG_READ(ah, AR_PHY_AGC_CONTROL) | ++ AR_PHY_AGC_CONTROL_CAL); ++ ++ 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 bool ar9003_hw_init_cal_soc(struct ath_hw *ah, + struct ath9k_channel *chan) + { + 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; + + /* 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. */ - 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); -- } -+ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); - msleep(1); + 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)); -- if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || -- rt2800_wait_bbp_ready(rt2x00dev))) -+ if (unlikely(rt2800_wait_bbp_ready(rt2x00dev))) - return -EIO; +- /* 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; - 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; +- 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); ++ } ++ } ++ } } -- power = chandef.chan->max_power; +- if (txiqcal_done) +- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); - + /* Revert chainmask to runtime parameters */ + ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); + +--- 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 + ++#include <linux/cache.h> ++ + #include "rtl818x.h" + #include "leds.h" + +@@ -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; + } + ++ 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(); - 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); +--- 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++) { + +- if (!tid->sched) +- continue; +- + ac = tid->ac; + txq = ac->txq; + + ath_txq_lock(sc, txq); + ++ if (!tid->sched) { ++ ath_txq_unlock(sc, txq); ++ continue; ++ } ++ + buffered = ath_tid_has_buffered(tid); + + tid->sched = false; +@@ -1696,7 +1698,7 @@ int ath_cabq_update(struct ath_softc *sc + + ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); + +- 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); + +@@ -2061,7 +2063,7 @@ static struct ath_buf *ath_tx_setup_buff + + ATH_TXBUF_RESET(bf); + +- 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; } - rcu_read_unlock(); -+ power = min(power, chandef.chan->max_power); ++ if (txctl->an && ieee80211_is_data_present(hdr->frame_control)) ++ tid = ath_get_skb_tid(sc, txctl->an, skb); + - 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; + 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); + + 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; + } + +-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; + +- 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; + + clear_sta_flag(sta, WLAN_STA_PS_STA); ++ clear_sta_flag(sta, WLAN_STA_PS_DRIVER); + + 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); } - 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; ++} -+ if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) -+ sta->last_rx = jiffies; ++static void cleanup_single_sta(struct sta_info *sta) ++{ ++ struct ieee80211_sub_if_data *sdata = sta->sdata; ++ struct ieee80211_local *local = sdata->local; + - 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); ++ __cleanup_single_sta(sta); + sta_info_free(local, sta); + } + +@@ -330,6 +339,7 @@ struct sta_info *sta_info_alloc(struct i + rcu_read_unlock(); + + 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; } ---- 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); +- /* notify driver */ +- err = sta_info_insert_drv_state(local, sdata, sta); +- if (err) +- goto out_err; +- + local->num_sta++; + local->sta_generation++; + smp_mb(); + ++ /* simplify things and don't accept BA sessions yet */ ++ set_sta_flag(sta, WLAN_STA_BLOCK_BA); + - tries[0] = info->status.rates[0].count; - tries[1] = info->status.rates[1].count; - tries[2] = info->status.rates[2].count; + /* make the station visible */ + sta_info_hash_add(local, sta); + + list_add_rcu(&sta->list, &local->sta_list); + ++ /* notify driver */ ++ err = sta_info_insert_drv_state(local, sdata, sta); ++ if (err) ++ goto out_remove; ++ + set_sta_flag(sta, WLAN_STA_INSERTED); ++ /* accept BA sessions now */ ++ clear_sta_flag(sta, WLAN_STA_BLOCK_BA); + + 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); - ieee80211_tx_info_clear_status(info); +-static void clear_sta_ps_flags(void *_sta) ++/* powersave support code */ ++void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) + { +- 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; -- size = min_t(int, sizeof(info->status.rates), sizeof(bf->rates)); -- memcpy(info->status.rates, bf->rates, size); + 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); +-} - - 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; +-/* 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; + } + +- 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); ++ ++ atomic_dec(&ps->num_sta_ps); + + /* 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); } -@@ -202,8 +202,8 @@ static void rt2800usb_async_read_tx_stat - if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) + +- 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(®_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 }, ++ }; + + 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; + + /* +- * 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. + */ +- 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; ++ } + } + + 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; + + /* + * 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. +- */ ++ /* ++ * 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. ++ */ + if (rx_stats->rs_datalen > (common->rx_bufsize - ah->caps.rx_status_len)) { + RX_STAT_INC(rx_len_err); +- return -EINVAL; ++ goto corrupt; + } + + /* 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; + + hdr = (struct ieee80211_hdr *) (skb->data + ah->caps.rx_status_len); + +@@ -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); + +- ret = -EINVAL; +- goto exit; ++ return -EINVAL; + } + + /* + * 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 (ath_is_mybeacon(common, hdr)) { + RX_STAT_INC(rx_beacons); +@@ -1064,15 +1066,11 @@ static int ath9k_rx_skb_preprocess(struc + /* + * This shouldn't happen, but have a safety check anyway. + */ +- if (WARN_ON(!ah->curchan)) { +- ret = -EINVAL; +- goto exit; +- } ++ if (WARN_ON(!ah->curchan)) ++ return -EINVAL; -- /* 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); +- 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; + + ath9k_process_rssi(common, hw, rx_stats, rx_status); + +@@ -1087,9 +1085,11 @@ static int ath9k_rx_skb_preprocess(struc + sc->rx.num_pkts++; + #endif + +-exit: +- sc->rx.discard_next = false; +- return ret; ++ return 0; ++ ++corrupt: ++ sc->rx.discard_next = rx_stats->rs_more; ++ return -EINVAL; } + 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; ++ ++ /* 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; ++ ++ 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; + + 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++; + +- /* 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; +- } +- + 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 + + 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++; diff --git a/package/mac80211/patches/310-ap_scan.patch b/package/mac80211/patches/310-ap_scan.patch index d7479f2965..389a00370d 100644 --- a/package/mac80211/patches/310-ap_scan.patch +++ b/package/mac80211/patches/310-ap_scan.patch @@ -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) */ diff --git a/package/mac80211/patches/400-ath_move_debug_code.patch b/package/mac80211/patches/400-ath_move_debug_code.patch index aa5ce94d1e..0dba7ac125 100644 --- a/package/mac80211/patches/400-ath_move_debug_code.patch +++ b/package/mac80211/patches/400-ath_move_debug_code.patch @@ -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. */ diff --git a/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch b/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch index b2a7073307..63ab0dba6e 100644 --- a/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch +++ b/package/mac80211/patches/402-ath9k-fix-invalid-mac-address-handling.patch @@ -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; } diff --git a/package/mac80211/patches/403-ath_regd_optional.patch b/package/mac80211/patches/403-ath_regd_optional.patch index 303c4d7792..07c54ccf81 100644 --- a/package/mac80211/patches/403-ath_regd_optional.patch +++ b/package/mac80211/patches/403-ath_regd_optional.patch @@ -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 @@ -58,11 +58,11 @@ ---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= diff --git a/package/mac80211/patches/404-world_regd_fixup.patch b/package/mac80211/patches/404-world_regd_fixup.patch index 7a5840eb18..2b04309ce5 100644 --- a/package/mac80211/patches/404-world_regd_fixup.patch +++ b/package/mac80211/patches/404-world_regd_fixup.patch @@ -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) diff --git a/package/mac80211/patches/405-regd_no_assoc_hints.patch b/package/mac80211/patches/405-regd_no_assoc_hints.patch index 5380853df6..6ad4fda272 100644 --- a/package/mac80211/patches/405-regd_no_assoc_hints.patch +++ b/package/mac80211/patches/405-regd_no_assoc_hints.patch @@ -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) { diff --git a/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch index f6182dd31b..1f71e0b8aa 100644 --- a/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch +++ b/package/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch @@ -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[] = { diff --git a/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch b/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch index 12e03e1bb1..3487ab26f2 100644 --- a/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch +++ b/package/mac80211/patches/411-ath5k_allow_adhoc_and_ap.patch @@ -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) }, diff --git a/package/mac80211/patches/440-ath5k_channel_bw_debugfs.patch b/package/mac80211/patches/440-ath5k_channel_bw_debugfs.patch index 01c28bcca2..a8ebdf5126 100644 --- a/package/mac80211/patches/440-ath5k_channel_bw_debugfs.patch +++ b/package/mac80211/patches/440-ath5k_channel_bw_debugfs.patch @@ -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 diff --git a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch index 7f4e68d5ea..664cf45175 100644 --- a/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch +++ b/package/mac80211/patches/500-ath9k_eeprom_debugfs.patch @@ -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); diff --git a/package/mac80211/patches/501-ath9k-eeprom_endianess.patch b/package/mac80211/patches/501-ath9k-eeprom_endianess.patch index b98e8f50f0..96e7c6d8cc 100644 --- a/package/mac80211/patches/501-ath9k-eeprom_endianess.patch +++ b/package/mac80211/patches/501-ath9k-eeprom_endianess.patch @@ -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; + diff --git a/package/mac80211/patches/502-ath9k_ahb_init.patch b/package/mac80211/patches/502-ath9k_ahb_init.patch index 03199d8f37..4edc63bede 100644 --- a/package/mac80211/patches/502-ath9k_ahb_init.patch +++ b/package/mac80211/patches/502-ath9k_ahb_init.patch @@ -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; } diff --git a/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch index 647bde2ca0..d7478ff590 100644 --- a/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch +++ b/package/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch @@ -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) diff --git a/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch index 8d8c5fd7fe..ef0b9a1e2a 100644 --- a/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch +++ b/package/mac80211/patches/511-ath9k_reduce_rxbuf.patch @@ -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 diff --git a/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch index a42daf5c3e..8f3cc03043 100644 --- a/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch +++ b/package/mac80211/patches/512-ath9k_channelbw_debugfs.patch @@ -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 }; @@ -27,10 +9,11 @@ + 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); @@ -78,51 +62,64 @@ 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 index 0000000000..db4e6a1238 --- /dev/null +++ b/package/mac80211/patches/513-ath9k_add_pci_ids.patch @@ -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 } + }; + diff --git a/package/mac80211/patches/520-mac80211_cur_txpower.patch b/package/mac80211/patches/520-mac80211_cur_txpower.patch index 837d9f633f..6df95bceae 100644 --- a/package/mac80211/patches/520-mac80211_cur_txpower.patch +++ b/package/mac80211/patches/520-mac80211_cur_txpower.patch @@ -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; diff --git a/package/mac80211/patches/521-ath9k_cur_txpower.patch b/package/mac80211/patches/521-ath9k_cur_txpower.patch index a14d0315f8..0d6c360d38 100644 --- a/package/mac80211/patches/521-ath9k_cur_txpower.patch +++ b/package/mac80211/patches/521-ath9k_cur_txpower.patch @@ -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 index 50dbcd9902..0000000000 --- a/package/mac80211/patches/522-ath9k_per_chain_signal_strength.patch +++ /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/523-mac80211_configure_antenna_gain.patch b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch index d247c561db..308ee6eb77 100644 --- a/package/mac80211/patches/523-mac80211_configure_antenna_gain.patch +++ b/package/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -1,6 +1,24 @@ +--- 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 -@@ -999,6 +999,7 @@ enum ieee80211_smps_mode { +@@ -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 @@ -8,7 +26,7 @@ * * @chandef: the channel definition to tune to * @radar_enabled: whether radar detection is enabled -@@ -1020,6 +1021,7 @@ struct ieee80211_conf { +@@ -1054,6 +1055,7 @@ struct ieee80211_conf { u32 flags; int power_level, dynamic_ps_timeout; int max_sleep_period; @@ -16,63 +34,30 @@ 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 { +@@ -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_PEER_AID, + NL80211_ATTR_QOS_MAP, + 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 +@@ -2339,6 +2339,19 @@ static int ieee80211_get_tx_power(struct return 0; } @@ -92,7 +77,7 @@ 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 +@@ -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, @@ -100,37 +85,30 @@ .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); +--- 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; - 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 +@@ -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 = 0; -+ int ant_gain, max_power; +- int power; ++ int power, 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); +@@ -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; @@ -145,13 +123,13 @@ + } + + if (local->hw.conf.power_level != power || -+ local->hw.conf.max_antenna_gain != ant_gain) { ++ 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( +@@ -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; @@ -159,3 +137,36 @@ 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/524-ath9k_use_configured_antenna_gain.patch b/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch index 9d627ac1e1..30aa9ee187 100644 --- a/package/mac80211/patches/524-ath9k_use_configured_antenna_gain.patch +++ b/package/mac80211/patches/523-ath9k_use_configured_antenna_gain.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h -@@ -73,6 +73,7 @@ struct ath_regulatory { +@@ -74,6 +74,7 @@ struct ath_regulatory { u16 max_power_level; u16 current_rd; int16_t power_limit; @@ -10,7 +10,7 @@ --- 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 +@@ -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); @@ -21,7 +21,7 @@ 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 +@@ -1371,7 +1371,10 @@ static int ath9k_config(struct ieee80211 } if (changed & IEEE80211_CONF_CHANGE_POWER) { diff --git a/package/mac80211/patches/530-ath9k_extra_leds.patch b/package/mac80211/patches/530-ath9k_extra_leds.patch index b931d5f4cf..59f78d9dfa 100644 --- a/package/mac80211/patches/530-ath9k_extra_leds.patch +++ b/package/mac80211/patches/530-ath9k_extra_leds.patch @@ -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 @@ -162,7 +162,7 @@ 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 */ @@ -173,7 +173,7 @@ #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, }; @@ -235,7 +235,7 @@ 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); diff --git a/package/mac80211/patches/531-ath9k_extra_platform_leds.patch b/package/mac80211/patches/531-ath9k_extra_platform_leds.patch index 764242cd1c..6c9832c4a0 100644 --- a/package/mac80211/patches/531-ath9k_extra_platform_leds.patch +++ b/package/mac80211/patches/531-ath9k_extra_platform_leds.patch @@ -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/550-ath9k_reduce_ani_interval.patch b/package/mac80211/patches/540-ath9k_reduce_ani_interval.patch index 7c24f46f67..e899903478 100644 --- a/package/mac80211/patches/550-ath9k_reduce_ani_interval.patch +++ b/package/mac80211/patches/540-ath9k_reduce_ani_interval.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h -@@ -38,7 +38,7 @@ +@@ -42,7 +42,7 @@ #define ATH9K_ANI_PERIOD 300 /* in ms */ 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 index 95ceb3575d..0000000000 --- a/package/mac80211/patches/541-ath9k_optimize_interrupt_mitigation.patch +++ /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/552-ath9k_rx_dma_stop_check.patch b/package/mac80211/patches/541-ath9k_rx_dma_stop_check.patch index 5d063c7d65..a521525a1b 100644 --- a/package/mac80211/patches/552-ath9k_rx_dma_stop_check.patch +++ b/package/mac80211/patches/541-ath9k_rx_dma_stop_check.patch @@ -1,6 +1,6 @@ --- 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 +@@ -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); @@ -9,7 +9,7 @@ int i; /* Enable access to the DMA observation bus */ -@@ -735,6 +735,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw +@@ -730,6 +730,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw } if (i == 0) { diff --git a/package/mac80211/patches/553-ath9k_debugfs_diag.patch b/package/mac80211/patches/542-ath9k_debugfs_diag.patch index 7230d32963..e1b6ff17e8 100644 --- a/package/mac80211/patches/553-ath9k_debugfs_diag.patch +++ b/package/mac80211/patches/542-ath9k_debugfs_diag.patch @@ -1,6 +1,6 @@ --- 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 +@@ -1629,6 +1629,50 @@ static const struct file_operations fops #endif @@ -51,7 +51,7 @@ 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) +@@ -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 @@ -62,7 +62,7 @@ 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 { +@@ -482,6 +482,12 @@ enum { ATH9K_RESET_COLD, }; @@ -75,7 +75,7 @@ struct ath9k_hw_version { u32 magic; u16 devid; -@@ -777,6 +783,8 @@ struct ath_hw { +@@ -762,6 +768,8 @@ struct ath_hw { u32 rfkill_polarity; u32 ah_flags; @@ -84,17 +84,17 @@ bool reset_power_on; bool htc_reset_init; -@@ -1027,6 +1035,7 @@ void ath9k_hw_set_sta_beacon_timers(stru +@@ -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); - #ifdef CPTCFG_ATH9K_DEBUGFS - void ath9k_debug_sync_cause(struct ath_common *common, u32 sync_cause); + /* 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 -@@ -1853,6 +1853,20 @@ fail: +@@ -1735,6 +1735,20 @@ fail: return -EINVAL; } @@ -115,18 +115,18 @@ 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 - } +@@ -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) && ah->shared_chain_lnadiv) + 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 -@@ -472,6 +472,11 @@ irqreturn_t ath_isr(int irq, void *dev) - ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ +@@ -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)) { diff --git a/package/mac80211/patches/555-ath9k-allow-to-disable-bands-via-platform-data.patch b/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch index 584a7d70ce..d26a5af865 100644 --- a/package/mac80211/patches/555-ath9k-allow-to-disable-bands-via-platform-data.patch +++ b/package/mac80211/patches/543-ath9k-allow-to-disable-bands-via-platform-data.patch @@ -1,18 +1,17 @@ --- a/include/linux/ath9k_platform.h +++ b/include/linux/ath9k_platform.h -@@ -33,6 +33,9 @@ struct ath9k_platform_data { - +@@ -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 -@@ -2448,17 +2448,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw +@@ -2328,17 +2328,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw } eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); @@ -48,7 +47,7 @@ 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 { +@@ -932,6 +932,8 @@ struct ath_hw { bool is_clk_25mhz; int (*get_mac_revision)(void); int (*external_reset)(void); @@ -59,7 +58,7 @@ }; --- 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; 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 index 0000000000..d126fd4e94 --- /dev/null +++ b/package/mac80211/patches/550-ath9k_entropy_from_adc.patch @@ -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/551-ath9k_p2p_ifcomb.patch b/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch new file mode 100644 index 0000000000..ffffe0cbe8 --- /dev/null +++ b/package/mac80211/patches/551-ath9k_p2p_ifcomb.patch @@ -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 index 0000000000..4a61db3f9a --- /dev/null +++ b/package/mac80211/patches/552-ath9k_p2p_ps_support.patch @@ -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/554-ath9k_ani_mrc_fix.patch b/package/mac80211/patches/554-ath9k_ani_mrc_fix.patch deleted file mode 100644 index 47df721322..0000000000 --- a/package/mac80211/patches/554-ath9k_ani_mrc_fix.patch +++ /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/556-ath9k_fix_rx_race.patch b/package/mac80211/patches/556-ath9k_fix_rx_race.patch deleted file mode 100644 index 69030d27a3..0000000000 --- a/package/mac80211/patches/556-ath9k_fix_rx_race.patch +++ /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 index 47ecd747ba..0000000000 --- a/package/mac80211/patches/560-ath9k_tx_queueing_rework.patch +++ /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/566-ath9k-ar933x-usb-hang-workaround.patch index 40b6fef794..af94c9e312 100644 --- a/package/mac80211/patches/561-ath9k-ar933x-usb-hang-workaround.patch +++ b/package/mac80211/patches/566-ath9k-ar933x-usb-hang-workaround.patch @@ -1,6 +1,6 @@ --- 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 +@@ -217,6 +217,19 @@ void ath9k_hw_get_channel_centers(struct centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); } @@ -20,7 +20,7 @@ /******************/ /* Chip Revisions */ /******************/ -@@ -1397,6 +1410,9 @@ static bool ath9k_hw_set_reset(struct at +@@ -1337,6 +1350,9 @@ static bool ath9k_hw_set_reset(struct at if (AR_SREV_9100(ah)) udelay(50); @@ -30,9 +30,9 @@ return true; } -@@ -1498,6 +1514,9 @@ static bool ath9k_hw_chip_reset(struct a +@@ -1436,6 +1452,9 @@ static bool ath9k_hw_chip_reset(struct a + ar9003_hw_internal_regulator_apply(ah); 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); @@ -40,7 +40,7 @@ return true; } -@@ -1848,8 +1867,14 @@ static int ath9k_hw_do_fastcc(struct ath +@@ -1730,8 +1749,14 @@ static int ath9k_hw_do_fastcc(struct ath if (AR_SREV_9271(ah)) ar9002_hw_load_ani_reg(ah, chan); @@ -55,8 +55,8 @@ return -EINVAL; } -@@ -2074,6 +2099,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st - if (AR_SREV_9565(ah) && ah->shared_chain_lnadiv) +@@ -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)) @@ -67,11 +67,13 @@ 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 @@ +@@ -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 + - #endif + enum ath9k_ant_div_comb_lna_conf { + ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, + ATH_ANT_DIV_COMB_LNA2, diff --git a/package/mac80211/patches/601-rt2x00-set_pci_mwi.patch b/package/mac80211/patches/601-rt2x00-set_pci_mwi.patch index d9a20bc107..08c8fa651c 100644 --- a/package/mac80211/patches/601-rt2x00-set_pci_mwi.patch +++ b/package/mac80211/patches/601-rt2x00-set_pci_mwi.patch @@ -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); diff --git a/package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch b/package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch index 6c80c3dfa8..8c71075b5c 100644 --- a/package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch +++ b/package/mac80211/patches/602-rt2x00-introduce-rt2x00_platform_h.patch @@ -22,10 +22,10 @@ +#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> diff --git a/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch index f47c1a5321..2bbc6f162a 100644 --- a/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch +++ b/package/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch @@ -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> @@ -33,13 +185,24 @@ +#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" @@ -82,9 +245,11 @@ +{ + 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) @@ -99,39 +264,9 @@ + 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 */ /* @@ -154,122 +289,9 @@ * 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; @@ -277,13 +299,3 @@ 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 index 0000000000..4bc6f37adb --- /dev/null +++ b/package/mac80211/patches/604-rt2x00-of_load_eeprom_filename.patch @@ -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/617-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 index d5af4c9ae2..75f0415b73 100644 --- a/package/mac80211/patches/617-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 @@ -12,32 +12,35 @@ Signed-off-by: John Crispin <blogic@openwrt.org> --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig -@@ -71,6 +71,7 @@ config RT2800PCI - select RT2X00_LIB_FIRMWARE +@@ -219,6 +219,7 @@ config RT2800SOC select RT2X00_LIB_EEPROM - select RT2X00_LIB_CRYPTO + select RT2800_LIB + select RT2800_LIB_MMIO + select MTD if SOC_RT288X || SOC_RT305X - depends on CRC_CCITT - depends on EEPROM_93CX6 ---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 -@@ -30,12 +30,77 @@ - #include "rt2x00.h" - #include "rt2x00lib.h" +@@ -26,11 +26,66 @@ -+#ifdef CONFIG_OF -+#include <linux/of.h> + #include <linux/kernel.h> + #include <linux/module.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) + #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 ret, size, offset = 0; ++ int size, offset = 0; + struct mtd_info *mtd; + const char *part; + const __be32 *list; @@ -78,25 +81,21 @@ Signed-off-by: John Crispin <blogic@openwrt.org> + mtd_fw.size = len; + mtd_fw.data = rt2x00dev->eeprom; + } ++#endif + + 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) + static const char * + rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev) { - const struct firmware *ee; - char *ee_name; +@@ -58,6 +113,9 @@ static int rt2x00lib_request_eeprom_file + const char *ee_name; int retval; -+ if (!rt2800pci_read_eeprom_mtd(rt2x00dev)) ++ if (!rt2800lib_read_eeprom_mtd(rt2x00dev)) + return 0; + - ee_name = rt2x00dev->ops->lib->get_eeprom_file_name(rt2x00dev); + 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 index bcbb435c1d..0000000000 --- a/package/mac80211/patches/605-rt2x00-pci-eeprom.patch +++ /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 diff --git a/package/mac80211/patches/606-rt2x00_no_realign.patch b/package/mac80211/patches/606-rt2x00_no_realign.patch index 9608df2e20..7e321922f1 100644 --- a/package/mac80211/patches/606-rt2x00_no_realign.patch +++ b/package/mac80211/patches/606-rt2x00_no_realign.patch @@ -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; diff --git a/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch b/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch index 5e6e27de98..4116735982 100644 --- a/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch +++ b/package/mac80211/patches/607-rt2x00-allow_disabling_bands_through_platform_data.patch @@ -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 diff --git a/package/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/mac80211/patches/608-add_platform_data_mac_addr.patch index 0695b893b5..a910cc36c0 100644 --- a/package/mac80211/patches/608-add_platform_data_mac_addr.patch +++ b/package/mac80211/patches/608-add_platform_data_mac_addr.patch @@ -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, ®); -@@ -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. */ diff --git a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch index 8369a78ad9..83fbcd0fcc 100644 --- a/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch +++ b/package/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch @@ -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 */ @@ -15,6 +15,17 @@ 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); @@ -99,15 +110,15 @@ 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. */ @@ -117,14 +128,14 @@ __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, @@ -142,8 +153,8 @@ --- 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: @@ -155,7 +166,7 @@ * 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) /* @@ -174,26 +185,26 @@ * 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) @@ -203,7 +214,7 @@ * 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, diff --git a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch index e16d97026a..478a0f277e 100644 --- a/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch +++ b/package/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch @@ -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}, }; @@ -28,28 +28,19 @@ 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; diff --git a/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch b/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch index 81125a96c2..f6b4808e42 100644 --- a/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch +++ b/package/mac80211/patches/612-rt2x00-make-wmac-loadable-via-OF-on-rt288x-305x-SoC.patch @@ -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 index 293b71a183..0000000000 --- a/package/mac80211/patches/614-rt2x00-of_load_eeprom_filename.patch +++ /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 index 0000000000..d843b7ab53 --- /dev/null +++ b/package/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch @@ -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; + } diff --git a/package/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/mac80211/patches/616-rt2x00-support-rt5350.patch index 9dc5835605..8d3fcd245a 100644 --- a/package/mac80211/patches/616-rt2x00-support-rt5350.patch +++ b/package/mac80211/patches/616-rt2x00-support-rt5350.patch @@ -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 @@ -10,39 +10,37 @@ #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 */ @@ -52,25 +50,24 @@ 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); @@ -104,7 +101,7 @@ 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); @@ -118,7 +115,7 @@ } 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: @@ -126,8 +123,8 @@ 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) @@ -203,9 +200,9 @@ 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); @@ -213,9 +210,9 @@ 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); @@ -226,16 +223,16 @@ } 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: @@ -243,35 +240,33 @@ 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/618-rt2x00-msi-fix.patch b/package/mac80211/patches/618-rt2x00-msi-fix.patch deleted file mode 100644 index ceddbe439d..0000000000 --- a/package/mac80211/patches/618-rt2x00-msi-fix.patch +++ /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 index 0000000000..f820b96f6e --- /dev/null +++ b/package/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch @@ -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 index 0000000000..419cb60f21 --- /dev/null +++ b/package/mac80211/patches/620-rt2x00-add-AP+STA-support.patch @@ -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 diff --git a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch index ef6b1af62b..51c223d12c 100644 --- a/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch +++ b/package/mac80211/patches/620-rt2x00-rt3352-rf-id.patch @@ -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)) diff --git a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch index 3381ba56ad..484c075893 100644 --- a/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch +++ b/package/mac80211/patches/700-mwl8k-missing-pci-id-for-WNR854T.patch @@ -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 index 050defaef0..0000000000 --- a/package/mac80211/patches/750-rtlwifi-Align-private-space-in-rtl_priv-struct.patch +++ /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)) diff --git a/package/mac80211/patches/800-b43-gpio-mask-module-option.patch b/package/mac80211/patches/800-b43-gpio-mask-module-option.patch index 46de746db1..fc874ad049 100644 --- a/package/mac80211/patches/800-b43-gpio-mask-module-option.patch +++ b/package/mac80211/patches/800-b43-gpio-mask-module-option.patch @@ -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); diff --git a/package/mac80211/patches/810-b43_no_pio.patch b/package/mac80211/patches/810-b43_no_pio.patch index 1206923e0d..5cd1b8bccd 100644 --- a/package/mac80211/patches/810-b43_no_pio.patch +++ b/package/mac80211/patches/810-b43_no_pio.patch @@ -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 diff --git a/package/mac80211/patches/820-b43-add-antenna-control.patch b/package/mac80211/patches/820-b43-add-antenna-control.patch index 56aef894bc..dea98303cd 100644 --- a/package/mac80211/patches/820-b43-add-antenna-control.patch +++ b/package/mac80211/patches/820-b43-add-antenna-control.patch @@ -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; @@ -108,7 +108,7 @@ 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; diff --git a/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch index e55d4fe4aa..e76758ca63 100644 --- a/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch +++ b/package/mac80211/patches/830-b43-workaround-pcie-bcm4716.patch @@ -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); diff --git a/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch b/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch index a1eafa487b..50347cdc3c 100644 --- a/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch +++ b/package/mac80211/patches/845-b43-only-use-gpio-0-1-for-led.patch @@ -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 index 0000000000..185c4279e9 --- /dev/null +++ b/package/mac80211/patches/850-brcmsmac-remove-extra-regulation-restriction.patch @@ -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 index dd1393ae5d..0000000000 --- a/package/mac80211/patches/851-brcmsmac-remove-extra-regulation-restriction.patch +++ /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 index 0000000000..a8af257c34 --- /dev/null +++ b/package/mac80211/patches/900-wl1251-split-wl251-platform-data-to-a-separate-structure.patch @@ -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 index 0000000000..f2789a9c55 --- /dev/null +++ b/package/mac80211/patches/901-wlcore-set-irq_flags-in-the-board-files.patch @@ -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 index 0000000000..639437754b --- /dev/null +++ b/package/mac80211/patches/902-wlcore-remove-pwr_in_suspend-from-platform-data.patch @@ -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 index 0000000000..4b20932f53 --- /dev/null +++ b/package/mac80211/patches/903-wl12xx-use-frequency-instead-of-enumerations-for-pdata-clocks.patch @@ -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 index 0000000000..9e1d19070f --- /dev/null +++ b/package/mac80211/patches/904-wlcore-add-initial-device-tree-support-to-the-sdio-module.patch @@ -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 index 0000000000..be1f9ada43 --- /dev/null +++ b/package/mac80211/patches/905-wlcore-sdio-add-wilink-clock-providers.patch @@ -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 index 0000000000..09ff4aff96 --- /dev/null +++ b/package/mac80211/patches/906-wlcore-sdio-get-clocks-from-device-tree.patch @@ -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 index 0000000000..6b09177ded --- /dev/null +++ b/package/mac80211/patches/907-wlcore-wl12xx-check-if-we-got-correct-clock-data-from-DT.patch @@ -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 index 0000000000..5a74fbf3db --- /dev/null +++ b/package/mac80211/patches/a00-ath9k_platform_h_backup.patch @@ -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; + |