diff --git a/patches/openwrt/0006-ar71xx-define-wmac-reset-function-for-QCA955x.patch b/patches/openwrt/0006-ar71xx-define-wmac-reset-function-for-QCA955x.patch new file mode 100644 index 00000000..81d95a9a --- /dev/null +++ b/patches/openwrt/0006-ar71xx-define-wmac-reset-function-for-QCA955x.patch @@ -0,0 +1,85 @@ +From: Matthias Schiffer +Date: Tue, 19 Jul 2016 17:48:53 +0200 +Subject: ar71xx: define wmac reset function for QCA955x + +Signed-off-by: Felix Fietkau + +Backport of LEDE a176168a85477caa44eef7e979567d1d52868fde + +diff --git a/target/linux/ar71xx/patches-3.18/640-MIPS-ath79-add-QCA955x-wmac-reset.patch b/target/linux/ar71xx/patches-3.18/640-MIPS-ath79-add-QCA955x-wmac-reset.patch +new file mode 100644 +index 0000000..4ac5acd +--- /dev/null ++++ b/target/linux/ar71xx/patches-3.18/640-MIPS-ath79-add-QCA955x-wmac-reset.patch +@@ -0,0 +1,71 @@ ++--- a/arch/mips/ath79/common.h +++++ b/arch/mips/ath79/common.h ++@@ -19,6 +19,8 @@ ++ #define ATH79_MEM_SIZE_MIN (2 * 1024 * 1024) ++ #define ATH79_MEM_SIZE_MAX (128 * 1024 * 1024) ++ +++extern void __iomem *ath79_ddr_base; +++ ++ void ath79_clocks_init(void); ++ unsigned long ath79_get_sys_clk_rate(const char *id); ++ ++--- a/arch/mips/ath79/dev-wmac.c +++++ b/arch/mips/ath79/dev-wmac.c ++@@ -149,6 +149,27 @@ static void ar934x_wmac_setup(void) ++ ath79_wmac_data.is_clk_25mhz = true; ++ } ++ +++static int ar955x_wmac_reset(void) +++{ +++ int i; +++ +++ /* Try to wait for WMAC DDR activity to stop */ +++ for (i = 0; i < 10; i++) { +++ if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) & +++ QCA955X_DDR_CTL_CONFIG_ACT_WMAC)) +++ break; +++ +++ udelay(10); +++ } +++ +++ ath79_device_reset_set(QCA955X_RESET_RTC); +++ udelay(10); +++ ath79_device_reset_clear(QCA955X_RESET_RTC); +++ udelay(10); +++ +++ return 0; +++} +++ ++ static void qca955x_wmac_setup(void) ++ { ++ u32 t; ++@@ -165,6 +186,8 @@ static void qca955x_wmac_setup(void) ++ ath79_wmac_data.is_clk_25mhz = false; ++ else ++ ath79_wmac_data.is_clk_25mhz = true; +++ +++ ath79_wmac_data.external_reset = ar955x_wmac_reset; ++ } ++ ++ static bool __init ++--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h +++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h ++@@ -32,7 +32,7 @@ ++ #define AR71XX_SPI_SIZE 0x01000000 ++ ++ #define AR71XX_DDR_CTRL_BASE (AR71XX_APB_BASE + 0x00000000) ++-#define AR71XX_DDR_CTRL_SIZE 0x100 +++#define AR71XX_DDR_CTRL_SIZE 0x200 ++ #define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000) ++ #define AR71XX_UART_SIZE 0x100 ++ #define AR71XX_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000) ++@@ -173,6 +173,9 @@ ++ #define AR934X_DDR_REG_FLUSH_PCIE 0xa8 ++ #define AR934X_DDR_REG_FLUSH_WMAC 0xac ++ +++#define QCA955X_DDR_CTL_CONFIG 0x108 +++#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23) +++ ++ /* ++ * PLL block ++ */ diff --git a/patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch b/patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch deleted file mode 100644 index 4d5e1b86..00000000 --- a/patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: Matthias Schiffer -Date: Wed, 20 May 2015 23:10:36 +0200 -Subject: mac80211: ath10k: allow simultaneous AP+IBSS - -diff --git a/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch -new file mode 100644 -index 0000000..956c3fd ---- /dev/null -+++ b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch -@@ -0,0 +1,32 @@ -+--- a/drivers/net/wireless/ath/ath10k/mac.c -++++ b/drivers/net/wireless/ath/ath10k/mac.c -+@@ -7521,6 +7521,10 @@ static const struct ieee80211_iface_limi -+ | BIT(NL80211_IFTYPE_MESH_POINT) -+ #endif -+ }, -++ { -++ .max = 1, -++ .types = BIT(NL80211_IFTYPE_ADHOC) -++ }, -+ }; -+ -+ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = { -+@@ -7535,6 +7539,10 @@ static const struct ieee80211_iface_limi -+ .max = 1, -+ .types = BIT(NL80211_IFTYPE_STATION) -+ }, -++ { -++ .max = 1, -++ .types = BIT(NL80211_IFTYPE_ADHOC) -++ }, -+ }; -+ -+ static const struct ieee80211_iface_combination ath10k_if_comb[] = { -+@@ -7920,6 +7928,7 @@ int ath10k_mac_register(struct ath10k *a -+ ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb; -+ ar->hw->wiphy->n_iface_combinations = -+ ARRAY_SIZE(ath10k_10x_if_comb); -++ ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); -+ break; -+ case ATH10K_FW_WMI_OP_VERSION_10_4: -+ ar->hw->wiphy->iface_combinations = ath10k_10_4_if_comb; diff --git a/patches/openwrt/0006-mac80211-update-to-LEDE-0a0caa2656c8db73518a1783743ede772e3ac40f.patch b/patches/openwrt/0007-mac80211-update-to-LEDE-6c2651566cce8f5b3a3d3b976439dee2bac5e07e.patch similarity index 65% rename from patches/openwrt/0006-mac80211-update-to-LEDE-0a0caa2656c8db73518a1783743ede772e3ac40f.patch rename to patches/openwrt/0007-mac80211-update-to-LEDE-6c2651566cce8f5b3a3d3b976439dee2bac5e07e.patch index 26bd0609..85b2157a 100644 --- a/patches/openwrt/0006-mac80211-update-to-LEDE-0a0caa2656c8db73518a1783743ede772e3ac40f.patch +++ b/patches/openwrt/0007-mac80211-update-to-LEDE-6c2651566cce8f5b3a3d3b976439dee2bac5e07e.patch @@ -1,9 +1,9 @@ From: Matthias Schiffer Date: Tue, 7 Jun 2016 14:06:23 +0200 -Subject: mac80211: update to LEDE 0a0caa2656c8db73518a1783743ede772e3ac40f +Subject: mac80211: update to LEDE 6c2651566cce8f5b3a3d3b976439dee2bac5e07e diff --git a/package/firmware/ath10k-firmware/Makefile b/package/firmware/ath10k-firmware/Makefile -index b03d644..4f63cdd 100644 +index b03d644..170a6c9 100644 --- a/package/firmware/ath10k-firmware/Makefile +++ b/package/firmware/ath10k-firmware/Makefile @@ -8,7 +8,7 @@ @@ -28,7 +28,7 @@ index b03d644..4f63cdd 100644 CATEGORY:=Kernel modules SUBMENU:=$(WMENU) URL:=$(PKG_SOURCE_URL) -+ DEPENDS:=kmod-ath10k ++ DEPENDS:= endef define Package/ath10k-firmware-qca988x @@ -135,7 +135,7 @@ index b03d644..4f63cdd 100644 define Package/ath10k-firmware-qca6174/install $(INSTALL_DIR) $(1)/lib/firmware/ath10k $(CP) $(PKG_BUILD_DIR)/QCA6174 $(1)/lib/firmware/ath10k/ -@@ -97,6 +163,33 @@ define Package/ath10k-firmware-qca99x0/install +@@ -97,6 +163,36 @@ define Package/ath10k-firmware-qca99x0/install $(1)/lib/firmware/ath10k/QCA99X0/hw2.0/firmware-5.bin endef @@ -154,6 +154,9 @@ index b03d644..4f63cdd 100644 + +define Package/ath10k-firmware-qca9984/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9984/hw1.0 ++ ln -s \ ++ ../../cal-pci-0000:01:00.0.bin \ ++ $(1)/lib/firmware/ath10k/QCA9984/hw1.0/board.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9984/hw1.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA9984/hw1.0/board-2.bin @@ -526,8 +529,94 @@ index 0000000..94d6135 + + adev->channel = channel; + +diff --git a/package/kernel/ath10k-ct/Makefile b/package/kernel/ath10k-ct/Makefile +new file mode 100644 +index 0000000..adda03c +--- /dev/null ++++ b/package/kernel/ath10k-ct/Makefile +@@ -0,0 +1,80 @@ ++include $(TOPDIR)/rules.mk ++ ++PKG_NAME:=ath10k-ct ++PKG_VERSION:=2016-07-09 ++PKG_RELEASE=1 ++ ++PKG_LICENSE:=GPLv2 ++PKG_LICENSE_FILES:= ++ ++PKG_SOURCE_URL:=https://github.com/greearb/ath10k-ct.git ++PKG_SOURCE_PROTO:=git ++PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) ++PKG_SOURCE_VERSION:=0241aa1d2797ef564bf36fa67888e62289d71e8f ++PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz ++ ++PKG_MAINTAINER:=Ben Greear ++PKG_BUILD_PARALLEL:=1 ++ ++STAMP_CONFIGURED_DEPENDS := $(STAGING_DIR)/usr/include/mac80211-backport/backport/autoconf.h ++ ++include $(INCLUDE_DIR)/kernel.mk ++include $(INCLUDE_DIR)/package.mk ++ ++define KernelPackage/ath10k-ct ++ SUBMENU:=Wireless Drivers ++ TITLE:=ath10k-ct driver optimized for CT ath10k firmware ++ DEPENDS:=+kmod-mac80211 +kmod-ath +@DRIVER_11N_SUPPORT @PCI_SUPPORT ++ FILES:=\ ++ $(PKG_BUILD_DIR)/ath10k/ath10k_pci.ko \ ++ $(PKG_BUILD_DIR)/ath10k/ath10k_core.ko ++ AUTOLOAD:=$(call AutoLoad,50,mac80211 ath ath10k_core ath10k_pci) ++endef ++ ++NOSTDINC_FLAGS = \ ++ -I$(PKG_BUILD_DIR) \ ++ -I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \ ++ -I$(STAGING_DIR)/usr/include/mac80211-backport \ ++ -I$(STAGING_DIR)/usr/include/mac80211/uapi \ ++ -I$(STAGING_DIR)/usr/include/mac80211 \ ++ -include backport/autoconf.h \ ++ -include backport/backport.h ++ ++ifdef CONFIG_PACKAGE_MAC80211_MESH ++ NOSTDINC_FLAGS += -DCONFIG_MAC80211_MESH ++endif ++ ++CT_MAKEDEFS += CONFIG_ATH10K=m CONFIG_ATH10K_PCI=m ++# No AHB support enabled yet. Could conditionally enable it later. ++#CT_MAKEDEFS += CONFIG_ATH10K_AHB=y ++#NOSTDINC_FLAGS += -DCONFIG_ATH10K_AHB ++NOSTDINC_FLAGS += -DSTANDALONE_CT ++ ++ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS ++ CT_MAKEDEFS += CONFIG_ATH10K_DEBUGFS=y CONFIG_MAC80211_DEBUGFS=y ++ NOSTDINC_FLAGS += -DCONFIG_MAC80211_DEBUGFS ++ NOSTDINC_FLAGS += -DCONFIG_ATH10K_DEBUGFS ++endif ++ ++ifdef CONFIG_PACKAGE_ATH_DEBUG ++ NOSTDINC_FLAGS += -DCONFIG_ATH10K_DEBUG ++endif ++ ++define Build/Configure ++ cp $(STAGING_DIR)/usr/include/mac80211/ath/*.h $(PKG_BUILD_DIR) ++endef ++ ++ifneq ($(findstring c,$(OPENWRT_VERBOSE)),) ++ CT_MAKEDEFS += V=1 ++endif ++ ++define Build/Compile ++ +$(MAKE) $(CT_MAKEDEFS) $(PKG_JOBS) -C "$(LINUX_DIR)" \ ++ ARCH="$(LINUX_KARCH)" \ ++ CROSS_COMPILE="$(TARGET_CROSS)" \ ++ SUBDIRS="$(PKG_BUILD_DIR)/ath10k" \ ++ NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ ++ modules ++endef ++ ++$(eval $(call KernelPackage,ath10k-ct)) diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile -index 30da1cf..bee0723 100644 +index 30da1cf..f2839cd 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -10,20 +10,21 @@ include $(INCLUDE_DIR)/kernel.mk @@ -535,12 +624,12 @@ index 30da1cf..bee0723 100644 PKG_NAME:=mac80211 -PKG_VERSION:=2016-01-10 -+PKG_VERSION:=2016-05-12 ++PKG_VERSION:=2016-06-20 PKG_RELEASE:=1 PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources PKG_BACKPORT_VERSION:= -PKG_MD5SUM:=be5fae2e8d6f7490f9b073374fb895ba -+PKG_MD5SUM:=2142cf38509896dca108624e7c193611 ++PKG_MD5SUM:=29c79bdc3928ef5113b17042ebda9237 PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION) @@ -618,7 +707,15 @@ index 30da1cf..bee0723 100644 help Atheros' idea of regulatory handling is that the EEPROM of the card defines the regulatory limits and the user is only allowed to restrict the settings -@@ -226,6 +246,10 @@ define KernelPackage/ath9k/config +@@ -199,6 +219,7 @@ define KernelPackage/ath9k-common + $(call KernelPackage/mac80211/Default) + TITLE:=Atheros 802.11n wireless devices (common code for ath9k and ath9k_htc) + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath9k ++ HIDDEN:=1 + DEPENDS+= @PCI_SUPPORT||USB_SUPPORT||TARGET_ar71xx +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT +@KERNEL_RELAY + FILES:= \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath9k/ath9k_common.ko \ +@@ -226,6 +247,10 @@ define KernelPackage/ath9k/config bool "Support chips used in PC OEM cards" depends on PACKAGE_kmod-ath9k @@ -629,7 +726,7 @@ index 30da1cf..bee0723 100644 endef define KernelPackage/ath9k-htc -@@ -247,7 +271,7 @@ define KernelPackage/ath10k +@@ -247,7 +272,7 @@ define KernelPackage/ath10k $(call KernelPackage/mac80211/Default) TITLE:=Atheros 802.11ac wireless cards support URL:=https://wireless.wiki.kernel.org/en/users/Drivers/ath10k @@ -638,7 +735,7 @@ index 30da1cf..bee0723 100644 FILES:= \ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \ $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko -@@ -673,6 +697,7 @@ define KernelPackage/brcmfmac/config +@@ -673,6 +698,7 @@ define KernelPackage/brcmfmac/config config BRCMFMAC_SDIO bool "Enable SDIO bus interface support" @@ -646,7 +743,7 @@ index 30da1cf..bee0723 100644 default n help Enable support for cards attached to an SDIO bus. -@@ -761,7 +786,7 @@ endef +@@ -761,7 +787,7 @@ endef define KernelPackage/iwlwifi $(call KernelPackage/mac80211/Default) @@ -655,7 +752,7 @@ index 30da1cf..bee0723 100644 TITLE:=Intel AGN Wireless support FILES:= \ $(PKG_BUILD_DIR)/drivers/net/wireless/intel/iwlwifi/iwlwifi.ko \ -@@ -870,7 +895,7 @@ endef +@@ -870,7 +896,7 @@ endef define KernelPackage/lib80211 $(call KernelPackage/mac80211/Default) TITLE:=802.11 Networking stack @@ -664,7 +761,7 @@ index 30da1cf..bee0723 100644 FILES:= \ $(PKG_BUILD_DIR)/net/wireless/lib80211.ko \ $(PKG_BUILD_DIR)/net/wireless/lib80211_crypt_wep.ko \ -@@ -897,7 +922,7 @@ endef +@@ -897,7 +923,7 @@ endef define KernelPackage/libipw $(call KernelPackage/mac80211/Default) TITLE:=libipw for ipw2100 and ipw2200 @@ -673,7 +770,7 @@ index 30da1cf..bee0723 100644 FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intel/ipw2x00/libipw.ko AUTOLOAD:=$(call AutoProbe,libipw) endef -@@ -978,7 +1003,7 @@ endef +@@ -978,7 +1004,7 @@ endef define KernelPackage/libertas-spi $(call KernelPackage/mac80211/Default) SUBMENU:=Wireless Drivers @@ -682,7 +779,68 @@ index 30da1cf..bee0723 100644 KCONFIG := \ CONFIG_SPI=y \ CONFIG_SPI_MASTER=y -@@ -1453,6 +1478,7 @@ config-y:= \ +@@ -1036,33 +1062,6 @@ define KernelPackage/mwifiex-pcie/description + Kernel modules for Marvell 802.11n/802.11ac PCIe Wireless cards + endef + +- +-# Prism54 drivers +-P54PCIFW:=2.13.12.0.arm +-P54USBFW:=2.13.24.0.lm87.arm +-P54SPIFW:=2.13.0.0.a.13.14.arm +- +-define Download/p54usb +- FILE:=$(P54USBFW) +- URL:=http://daemonizer.de/prism54/prism54-fw/fw-usb +- MD5SUM:=8e8ab005a4f8f0123bcdc51bc25b47f6 +-endef +-$(eval $(call Download,p54usb)) +- +-define Download/p54pci +- FILE:=$(P54PCIFW) +- URL:=http://daemonizer.de/prism54/prism54-fw/fw-softmac +- MD5SUM:=ff7536af2092b1c4b21315bd103ef4c4 +-endef +-$(eval $(call Download,p54pci)) +- +-define Download/p54spi +- FILE:=$(P54SPIFW) +- URL:=http://daemonizer.de/prism54/prism54-fw/stlc4560 +- MD5SUM:=42661f8ecbadd88012807493f596081d +-endef +-$(eval $(call Download,p54spi)) +- + define KernelPackage/p54/Default + $(call KernelPackage/mac80211/Default) + TITLE:=Prism54 Drivers +@@ -1082,7 +1081,7 @@ endef + define KernelPackage/p54-pci + $(call KernelPackage/p54/Default) + TITLE+= (PCI) +- DEPENDS+= @PCI_SUPPORT +kmod-p54-common ++ DEPENDS+= @PCI_SUPPORT +kmod-p54-common +p54-pci-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54pci.ko + AUTOLOAD:=$(call AutoProbe,p54pci) + endef +@@ -1090,7 +1089,7 @@ endef + define KernelPackage/p54-usb + $(call KernelPackage/p54/Default) + TITLE+= (USB) +- DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-p54-common ++ DEPENDS+= @USB_SUPPORT +kmod-usb-core +kmod-p54-common +p54-usb-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54usb.ko + AUTOLOAD:=$(call AutoProbe,p54usb) + endef +@@ -1098,7 +1097,7 @@ endef + define KernelPackage/p54-spi + $(call KernelPackage/p54/Default) + TITLE+= (SPI) +- DEPENDS+= @TARGET_omap24xx +kmod-p54-common ++ DEPENDS+= @TARGET_omap24xx +kmod-p54-common +p54-spi-firmware + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/intersil/p54/p54spi.ko + AUTOLOAD:=$(call AutoProbe,p54spi) + endef +@@ -1453,6 +1452,7 @@ config-y:= \ WLAN_VENDOR_ATH \ WLAN_VENDOR_ATMEL \ WLAN_VENDOR_BROADCOM \ @@ -690,7 +848,7 @@ index 30da1cf..bee0723 100644 WLAN_VENDOR_INTEL \ WLAN_VENDOR_INTERSIL \ WLAN_VENDOR_MARVELL \ -@@ -1491,6 +1517,8 @@ endif +@@ -1491,6 +1491,8 @@ endif config-$(call config_package,lib80211) += LIB80211 LIB80211_CRYPT_WEP LIB80211_CRYPT_CCMP LIB80211_CRYPT_TKIP @@ -699,7 +857,7 @@ index 30da1cf..bee0723 100644 config-$(call config_package,ath) += ATH_CARDS ATH_COMMON config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG ATH10K_DEBUG config-$(CONFIG_PACKAGE_ATH_DFS) += ATH9K_DFS_CERTIFIED ATH10K_DFS_CERTIFIED -@@ -1501,6 +1529,7 @@ config-$(CONFIG_TARGET_ar71xx) += ATH9K_AHB +@@ -1501,6 +1503,7 @@ config-$(CONFIG_TARGET_ar71xx) += ATH9K_AHB config-$(CONFIG_PCI) += ATH9K_PCI config-$(CONFIG_ATH_USER_REGD) += ATH_USER_REGD config-$(CONFIG_ATH9K_SUPPORT_PCOEM) += ATH9K_PCOEM @@ -707,7 +865,29 @@ index 30da1cf..bee0723 100644 config-$(call config_package,ath9k-htc) += ATH9K_HTC config-$(call config_package,ath10k) += ATH10K ATH10K_PCI -@@ -1764,6 +1793,7 @@ endef +@@ -1742,21 +1745,6 @@ define KernelPackage/ipw2200/install + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(IPW2200_NAME)-$(IPW2200_VERSION)/ipw2200*.fw $(1)/lib/firmware + endef + +-define KernelPackage/p54-pci/install +- $(INSTALL_DIR) $(1)/lib/firmware +- $(INSTALL_DATA) $(DL_DIR)/$(P54PCIFW) $(1)/lib/firmware/isl3886pci +-endef +- +-define KernelPackage/p54-usb/install +- $(INSTALL_DIR) $(1)/lib/firmware +- $(INSTALL_DATA) $(DL_DIR)/$(P54USBFW) $(1)/lib/firmware/isl3887usb +-endef +- +-define KernelPackage/p54-spi/install +- $(INSTALL_DIR) $(1)/lib/firmware +- $(INSTALL_DATA) $(DL_DIR)/$(P54SPIFW) $(1)/lib/firmware/3826.arm +-endef +- + define KernelPackage/zd1211rw/install + $(INSTALL_DIR) $(1)/lib/firmware/zd1211 + $(INSTALL_DATA) $(PKG_BUILD_DIR)/$(ZD1211FW_NAME)/zd1211* $(1)/lib/firmware/zd1211 +@@ -1764,6 +1752,7 @@ endef $(eval $(call KernelPackage,adm8211)) @@ -901,33 +1081,51 @@ index 9adfd8f..0000000 -+#endif -+ - #endif /* __BACKPORT_SKBUFF_H */ -diff --git a/package/kernel/mac80211/patches/004-header-backport-GENL_UNS_ADMIN_PERM.patch b/package/kernel/mac80211/patches/004-header-backport-GENL_UNS_ADMIN_PERM.patch +diff --git a/package/kernel/mac80211/patches/004-fix_duplicate_skcipher_backport.patch b/package/kernel/mac80211/patches/004-fix_duplicate_skcipher_backport.patch new file mode 100644 -index 0000000..38d655f +index 0000000..38b3179 --- /dev/null -+++ b/package/kernel/mac80211/patches/004-header-backport-GENL_UNS_ADMIN_PERM.patch -@@ -0,0 +1,21 @@ -+From: Felix Fietkau -+Date: Sat, 14 May 2016 16:39:35 +0200 -+Subject: [PATCH] header: backport GENL_UNS_ADMIN_PERM -+ -+Signed-off-by: Felix Fietkau -+--- -+ create mode 100644 backport-include/uapi/linux/genetlink.h -+ -+--- /dev/null -++++ b/backport-include/uapi/linux/genetlink.h -+@@ -0,0 +1,10 @@ -++#ifndef __COMPAT_UAPI_LINUX_GENETLINK_H -++#define __COMPAT_UAPI_LINUX_GENETLINK_H ++++ b/package/kernel/mac80211/patches/004-fix_duplicate_skcipher_backport.patch +@@ -0,0 +1,11 @@ ++--- a/compat/Makefile +++++ b/compat/Makefile ++@@ -35,8 +35,6 @@ compat-$(CPTCFG_KERNEL_4_6) += backport- ++ ++ compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o ++ compat-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += crypto-skcipher.o ++-skcipher-objs += crypto-skcipher.o ++-obj-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += skcipher.o ++ compat-$(CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP) += drivers-base-devcoredump.o ++ compat-$(CPTCFG_BPAUTO_RHASHTABLE) += lib-rhashtable.o ++ cordic-objs += lib-cordic.o +diff --git a/package/kernel/mac80211/patches/005-backport_skb_get_hash_perturb.patch b/package/kernel/mac80211/patches/005-backport_skb_get_hash_perturb.patch +new file mode 100644 +index 0000000..29bccc1 +--- /dev/null ++++ b/package/kernel/mac80211/patches/005-backport_skb_get_hash_perturb.patch +@@ -0,0 +1,22 @@ ++--- a/backport-include/linux/skbuff.h +++++ b/backport-include/linux/skbuff.h ++@@ -305,6 +305,19 @@ static inline void skb_free_frag(void *d ++ { ++ put_page(virt_to_head_page(data)); ++ } ++ -++#include_next +++#include +++#include ++ -++#ifndef GENL_UNS_ADMIN_PERM -++#define GENL_UNS_ADMIN_PERM GENL_ADMIN_PERM -++#endif +++static inline u32 skb_get_hash_perturb(struct sk_buff *skb, u32 key) +++{ +++ struct flow_keys keys; ++ -++#endif +++ skb_flow_dissect(skb, &keys); +++ return jhash_3words((__force u32)keys.dst, +++ (__force u32)keys.src ^ keys.ip_proto, +++ (__force u32)keys.ports, key); +++} ++ #endif ++ ++ #endif /* __BACKPORT_SKBUFF_H */ diff --git a/package/kernel/mac80211/patches/005-backports-add-napi_alloc_frag.patch b/package/kernel/mac80211/patches/005-backports-add-napi_alloc_frag.patch deleted file mode 100644 index 9b672a8..0000000 @@ -954,213 +1152,8 @@ index 9b672a8..0000000 - /* - * Complicated way of saying: We only backport netdev_rss_key stuff on kernels - * that either already have net_get_random_once() (>= 3.13) or where we've been -diff --git a/package/kernel/mac80211/patches/005-header-backport-nla_put_u64_64bit-and-nla_put_64bit.patch b/package/kernel/mac80211/patches/005-header-backport-nla_put_u64_64bit-and-nla_put_64bit.patch -new file mode 100644 -index 0000000..e20d87a ---- /dev/null -+++ b/package/kernel/mac80211/patches/005-header-backport-nla_put_u64_64bit-and-nla_put_64bit.patch -@@ -0,0 +1,158 @@ -+From: Felix Fietkau -+Date: Sat, 14 May 2016 16:40:16 +0200 -+Subject: [PATCH] header: backport nla_put_u64_64bit and nla_put_64bit -+ -+Signed-off-by: Felix Fietkau -+--- -+ -+--- a/backport-include/net/netlink.h -++++ b/backport-include/net/netlink.h -+@@ -189,4 +189,148 @@ static inline __le64 nla_get_le64(const -+ } -+ #endif /* < 4.4 */ -+ -++ -++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) -++ -++/** -++ * nla_need_padding_for_64bit - test 64-bit alignment of the next attribute -++ * @skb: socket buffer the message is stored in -++ * -++ * Return true if padding is needed to align the next attribute (nla_data()) to -++ * a 64-bit aligned area. -++ */ -++static inline bool nla_need_padding_for_64bit(struct sk_buff *skb) -++{ -++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -++ /* The nlattr header is 4 bytes in size, that's why we test -++ * if the skb->data _is_ aligned. A NOP attribute, plus -++ * nlattr header for next attribute, will make nla_data() -++ * 8-byte aligned. -++ */ -++ if (IS_ALIGNED((unsigned long)skb_tail_pointer(skb), 8)) -++ return true; -++#endif -++ return false; -++} -++ -++/** -++ * nla_align_64bit - 64-bit align the nla_data() of next attribute -++ * @skb: socket buffer the message is stored in -++ * @padattr: attribute type for the padding -++ * -++ * Conditionally emit a padding netlink attribute in order to make -++ * the next attribute we emit have a 64-bit aligned nla_data() area. -++ * This will only be done in architectures which do not have -++ * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS defined. -++ * -++ * Returns zero on success or a negative error code. -++ */ -++static inline int nla_align_64bit(struct sk_buff *skb, int padattr) -++{ -++ if (nla_need_padding_for_64bit(skb) && -++ !nla_reserve(skb, padattr, 0)) -++ return -EMSGSIZE; -++ -++ return 0; -++} -++ -++/** -++ * __nla_reserve_64bit - reserve room for attribute on the skb and align it -++ * @skb: socket buffer to reserve room on -++ * @attrtype: attribute type -++ * @attrlen: length of attribute payload -++ * @padattr: attribute type for the padding -++ * -++ * Adds a netlink attribute header to a socket buffer and reserves -++ * room for the payload but does not copy it. It also ensure that this -++ * attribute will have a 64-bit aligned nla_data() area. -++ * -++ * The caller is responsible to ensure that the skb provides enough -++ * tailroom for the attribute header and payload. -++ */ -++static inline struct nlattr *__nla_reserve_64bit(struct sk_buff *skb, int attrtype, -++ int attrlen, int padattr) -++{ -++ if (nla_need_padding_for_64bit(skb)) -++ nla_align_64bit(skb, padattr); -++ -++ return __nla_reserve(skb, attrtype, attrlen); -++} -++ -++/** -++ * __nla_put_64bit - Add a netlink attribute to a socket buffer and align it -++ * @skb: socket buffer to add attribute to -++ * @attrtype: attribute type -++ * @attrlen: length of attribute payload -++ * @data: head of attribute payload -++ * @padattr: attribute type for the padding -++ * -++ * The caller is responsible to ensure that the skb provides enough -++ * tailroom for the attribute header and payload. -++ */ -++static inline void __nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen, -++ const void *data, int padattr) -++{ -++ struct nlattr *nla; -++ -++ nla = __nla_reserve_64bit(skb, attrtype, attrlen, padattr); -++ memcpy(nla_data(nla), data, attrlen); -++} -++ -++/** -++ * nla_total_size_64bit - total length of attribute including padding -++ * @payload: length of payload -++ */ -++static inline int nla_total_size_64bit(int payload) -++{ -++ return NLA_ALIGN(nla_attr_size(payload)) -++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -++ + NLA_ALIGN(nla_attr_size(0)) -++#endif -++ ; -++} -++ -++/** -++ * nla_put_64bit - Add a netlink attribute to a socket buffer and align it -++ * @skb: socket buffer to add attribute to -++ * @attrtype: attribute type -++ * @attrlen: length of attribute payload -++ * @data: head of attribute payload -++ * @padattr: attribute type for the padding -++ * -++ * Returns -EMSGSIZE if the tailroom of the skb is insufficient to store -++ * the attribute header and payload. -++ */ -++static inline int nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen, -++ const void *data, int padattr) -++{ -++ size_t len; -++ -++ if (nla_need_padding_for_64bit(skb)) -++ len = nla_total_size_64bit(attrlen); -++ else -++ len = nla_total_size(attrlen); -++ if (unlikely(skb_tailroom(skb) < len)) -++ return -EMSGSIZE; -++ -++ __nla_put_64bit(skb, attrtype, attrlen, data, padattr); -++ return 0; -++} -++ -++/** -++ * nla_put_u64_64bit - Add a u64 netlink attribute to a skb and align it -++ * @skb: socket buffer to add attribute to -++ * @attrtype: attribute type -++ * @value: numeric value -++ * @padattr: attribute type for the padding -++ */ -++static inline int nla_put_u64_64bit(struct sk_buff *skb, int attrtype, -++ u64 value, int padattr) -++{ -++ return nla_put_64bit(skb, attrtype, sizeof(u64), &value, padattr); -++} -++ -++ -++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) */ -++ -+ #endif /* __BACKPORT_NET_NETLINK_H */ -diff --git a/package/kernel/mac80211/patches/006-compat-bump-rhashtable-backport-version-due-to-API-c.patch b/package/kernel/mac80211/patches/006-compat-bump-rhashtable-backport-version-due-to-API-c.patch -new file mode 100644 -index 0000000..1fdad3c ---- /dev/null -+++ b/package/kernel/mac80211/patches/006-compat-bump-rhashtable-backport-version-due-to-API-c.patch -@@ -0,0 +1,18 @@ -+From: Felix Fietkau -+Date: Sat, 14 May 2016 16:44:57 +0200 -+Subject: [PATCH] compat: bump rhashtable backport version due to API changes -+ -+Signed-off-by: Felix Fietkau -+--- -+ -+--- a/compat/Kconfig -++++ b/compat/Kconfig -+@@ -139,7 +139,7 @@ config BPAUTO_BUILD_WANT_DEV_COREDUMP -+ config BPAUTO_RHASHTABLE -+ bool -+ # current API of rhashtable was introduced in version 4.1 -+- depends on KERNEL_4_1 -++ depends on KERNEL_4_7 -+ # not very nice - but better than always having it -+ default y if MAC80211 -+ #h-file linux/rhashtable.h -diff --git a/package/kernel/mac80211/patches/007-fix_duplicate_skcipher_backport.patch b/package/kernel/mac80211/patches/007-fix_duplicate_skcipher_backport.patch -new file mode 100644 -index 0000000..38b3179 ---- /dev/null -+++ b/package/kernel/mac80211/patches/007-fix_duplicate_skcipher_backport.patch -@@ -0,0 +1,11 @@ -+--- a/compat/Makefile -++++ b/compat/Makefile -+@@ -35,8 +35,6 @@ compat-$(CPTCFG_KERNEL_4_6) += backport- -+ -+ compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o -+ compat-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += crypto-skcipher.o -+-skcipher-objs += crypto-skcipher.o -+-obj-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += skcipher.o -+ compat-$(CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP) += drivers-base-devcoredump.o -+ compat-$(CPTCFG_BPAUTO_RHASHTABLE) += lib-rhashtable.o -+ cordic-objs += lib-cordic.o diff --git a/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch -index fd1e1cf..e9a140c 100644 +index fd1e1cf..8be5fa1 100644 --- a/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch +++ b/package/kernel/mac80211/patches/060-no_local_ssb_bcma.patch @@ -1,6 +1,6 @@ @@ -1184,7 +1177,7 @@ index fd1e1cf..e9a140c 100644 #else return bus->chipco.dev; -@@ -4903,7 +4903,7 @@ static int b43_wireless_core_init(struct -+@@ -4901,7 +4901,7 @@ static int b43_wireless_core_init(struct ++@@ -4883,7 +4883,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. */ @@ -1215,180 +1208,10 @@ index 3765591..0000000 --EXPORT_SYMBOL_GPL(clk_disable); --#endif diff --git a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch -index 02f46c7..b65b0bd 100644 +index 02f46c7..fbe22e5 100644 --- a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch +++ b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch -@@ -34,12 +34,9 @@ - #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, --- size_t mic_len) - +static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0, - + u8 *a, u8 *b) -- { --- struct scatterlist sg[3]; -++{ - + int i; - + - + crypto_cipher_encrypt_one(tfm, b, b_0); -@@ -54,55 +51,56 @@ - + for (i = 0; i < AES_BLOCK_SIZE; i++) - + aad[i] ^= b[i]; - + crypto_cipher_encrypt_one(tfm, a, aad); -- --- char aead_req_data[sizeof(struct aead_request) + --- crypto_aead_reqsize(tfm)] --- __aligned(__alignof__(struct aead_request)); --- struct aead_request *aead_req = (void *) aead_req_data; -++ - + /* Mask out bits from auth-only-b_0 */ - + b_0[0] &= 0x07; -- --- memset(aead_req, 0, sizeof(aead_req_data)); -++ - + /* 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); - +} -- --- sg_init_table(sg, 3); --- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); --- sg_set_buf(&sg[1], data, data_len); --- sg_set_buf(&sg[2], mic, mic_len); -- --- aead_request_set_tfm(aead_req, tfm); --- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0); --- aead_request_set_ad(aead_req, sg[0].length); -++ -++ - +void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, --+ u8 *data, size_t data_len, u8 *mic, --+ size_t mic_len) --+{ -+ u8 *data, size_t data_len, u8 *mic, -+ size_t mic_len) -+ { -+- struct scatterlist sg[3]; - + int i, j, last_len, num_blocks; - + u8 b[AES_BLOCK_SIZE]; - + u8 s_0[AES_BLOCK_SIZE]; - + u8 e[AES_BLOCK_SIZE]; - + u8 *pos, *cpos; --+ -+ -+- char aead_req_data[sizeof(struct aead_request) + -+- crypto_aead_reqsize(tfm)] -+- __aligned(__alignof__(struct aead_request)); -+- struct aead_request *aead_req = (void *) aead_req_data; - + num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); - + last_len = data_len % AES_BLOCK_SIZE; - + aes_ccm_prepare(tfm, b_0, aad, s_0, b, b); --+ -+ -+- memset(aead_req, 0, sizeof(aead_req_data)); - + /* Process payload blocks */ - + pos = data; - + cpos = data; - + for (j = 1; j <= num_blocks; j++) { - + int blen = (j == num_blocks && last_len) ? - + last_len : AES_BLOCK_SIZE; --+ -+ -+- sg_init_table(sg, 3); -+- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); -+- sg_set_buf(&sg[1], data, data_len); -+- sg_set_buf(&sg[2], mic, mic_len); - + /* Authentication followed by encryption */ - + for (i = 0; i < blen; i++) - + b[i] ^= pos[i]; - + crypto_cipher_encrypt_one(tfm, b, b); --+ -+ -+- aead_request_set_tfm(aead_req, tfm); -+- aead_request_set_crypt(aead_req, sg, sg, data_len, b_0); -+- aead_request_set_ad(aead_req, sg[0].length); - + b_0[14] = (j >> 8) & 0xff; - + b_0[15] = j & 0xff; - + crypto_cipher_encrypt_one(tfm, e, b_0); -@@ -125,37 +123,30 @@ - - crypto_aead_reqsize(tfm)] - - __aligned(__alignof__(struct aead_request)); - - struct aead_request *aead_req = (void *) aead_req_data; --- --- if (data_len == 0) --- return -EINVAL; --- --- memset(aead_req, 0, sizeof(aead_req_data)); --- --- sg_init_table(sg, 3); --- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); --- sg_set_buf(&sg[1], data, data_len); --- sg_set_buf(&sg[2], mic, mic_len); --- --- aead_request_set_tfm(aead_req, tfm); --- aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); --- aead_request_set_ad(aead_req, sg[0].length); - + int i, j, last_len, num_blocks; - + u8 *pos, *cpos; - + u8 a[AES_BLOCK_SIZE]; - + u8 b[AES_BLOCK_SIZE]; - + u8 s_0[AES_BLOCK_SIZE]; --+ -+ -+- if (data_len == 0) -+- return -EINVAL; - + num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); - + last_len = data_len % AES_BLOCK_SIZE; - + aes_ccm_prepare(tfm, b_0, aad, s_0, a, b); --+ -+ -+- memset(aead_req, 0, sizeof(aead_req_data)); - + /* Process payload blocks */ - + cpos = data; - + pos = data; - + for (j = 1; j <= num_blocks; j++) { - + int blen = (j == num_blocks && last_len) ? - + last_len : AES_BLOCK_SIZE; --+ -+ -+- sg_init_table(sg, 3); -+- sg_set_buf(&sg[0], &aad[2], be16_to_cpup((__be16 *)aad)); -+- sg_set_buf(&sg[1], data, data_len); -+- sg_set_buf(&sg[2], mic, mic_len); - + /* Decryption followed by authentication */ - + b_0[14] = (j >> 8) & 0xff; - + b_0[15] = j & 0xff; -@@ -166,7 +157,10 @@ - + } - + crypto_cipher_encrypt_one(tfm, a, a); - + } --+ -+ -+- aead_request_set_tfm(aead_req, tfm); -+- aead_request_set_crypt(aead_req, sg, sg, data_len + mic_len, b_0); -+- aead_request_set_ad(aead_req, sg[0].length); - + for (i = 0; i < mic_len; i++) { - + if ((mic[i] ^ s_0[i]) != a[i]) - + return -1; -@@ -185,12 +179,12 @@ - { - - struct crypto_aead *tfm; - - int err; --+ struct crypto_cipher *tfm; -- -+- - - tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC); - - if (IS_ERR(tfm)) - - return tfm; --- -++ struct crypto_cipher *tfm; -+ - - err = crypto_aead_setkey(tfm, key, key_len); - - if (err) - - goto free_aead; -@@ -309,7 +303,7 @@ +@@ -309,7 +309,7 @@ #endif /* AES_GMAC_H */ --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -1397,7 +1220,7 @@ index 02f46c7..b65b0bd 100644 * Management frames. */ u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; -@@ -320,7 +314,7 @@ +@@ -320,7 +320,7 @@ struct { --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -1406,7 +1229,7 @@ index 02f46c7..b65b0bd 100644 } -@@ -330,7 +324,7 @@ +@@ -330,7 +330,7 @@ { __le16 mask_fc; int a4_included, mgmt; @@ -1415,7 +1238,7 @@ index 02f46c7..b65b0bd 100644 else qos_tid = 0; -@@ -347,7 +341,7 @@ +@@ -347,7 +347,7 @@ /* Nonce: Nonce Flags | A2 | PN * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) @@ -1424,7 +1247,7 @@ index 02f46c7..b65b0bd 100644 b_0[1] = qos_tid | (mgmt << 4); memcpy(&b_0[2], hdr->addr2, ETH_ALEN); memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); -@@ -356,7 +350,7 @@ +@@ -356,7 +356,7 @@ /* AAD (extra authenticate-only data) / masked 802.11 header * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ @@ -1433,7 +1256,7 @@ index 02f46c7..b65b0bd 100644 return 0; pos += IEEE80211_CCMP_HDR_LEN; -@@ -365,7 +359,7 @@ +@@ -365,7 +365,7 @@ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, skb_put(skb, mic_len), mic_len); @@ -1456,33 +1279,39 @@ index d1d9fbd..3ca166f 100644 __sta_info_flush(sdata, true); diff --git a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch -index 2855a88..3029598 100644 +index 2855a88..16fab84 100644 --- a/package/kernel/mac80211/patches/150-disable_addr_notifier.patch +++ b/package/kernel/mac80211/patches/150-disable_addr_notifier.patch -@@ -18,7 +18,7 @@ +@@ -18,9 +18,9 @@ static int ieee80211_ifa6_changed(struct notifier_block *nb, unsigned long data, void *arg) { -@@ -1087,14 +1087,14 @@ int ieee80211_register_hw(struct ieee802 -+@@ -1089,14 +1089,14 @@ int ieee80211_register_hw(struct ieee802 - - rtnl_unlock(); +- +- rtnl_unlock(); ++@@ -1090,14 +1090,14 @@ int ieee80211_register_hw(struct ieee802 ++ if (result) ++ goto fail_flows; + -#ifdef CONFIG_INET + +#ifdef __disabled__CONFIG_INET @@ -35,7 +35,7 @@ local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; result = register_inet6addr_notifier(&local->ifa6_notifier); if (result) -@@ -1103,13 +1103,13 @@ int ieee80211_register_hw(struct ieee802 -+@@ -1105,13 +1105,13 @@ int ieee80211_register_hw(struct ieee802 ++@@ -1106,13 +1106,13 @@ int ieee80211_register_hw(struct ieee802 return 0; -@@ -52,7 +52,7 @@ +@@ -51,8 +51,8 @@ + +#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6) fail_ifa: #endif - rtnl_lock(); +- rtnl_lock(); -@@ -1137,10 +1137,10 @@ void ieee80211_unregister_hw(struct ieee -+@@ -1139,10 +1139,10 @@ void ieee80211_unregister_hw(struct ieee ++ ieee80211_txq_teardown_flows(local); ++@@ -1142,10 +1142,10 @@ void ieee80211_unregister_hw(struct ieee tasklet_kill(&local->tx_pending_tasklet); tasklet_kill(&local->tasklet); @@ -1498,14 +1327,32 @@ index a99cbd2..29f05c4 100644 * the frames sent while scanning on other channel will be * lost) */ +diff --git a/package/kernel/mac80211/patches/220-fq_disable_hack.patch b/package/kernel/mac80211/patches/220-fq_disable_hack.patch +new file mode 100644 +index 0000000..7f420be +--- /dev/null ++++ b/package/kernel/mac80211/patches/220-fq_disable_hack.patch +@@ -0,0 +1,15 @@ ++mac80211 fq has been found to cause a regression in multi-stream TCP ++performance. Disable it until the cause has been found and fixed ++ ++--- a/include/net/fq_impl.h +++++ b/include/net/fq_impl.h ++@@ -104,6 +104,9 @@ static struct fq_flow *fq_flow_classify( ++ ++ lockdep_assert_held(&fq->lock); ++ +++ /* HACK: disable fq for now until TCP issues are fixed */ +++ return get_default_func(fq, tin, 0, skb); +++ ++ hash = skb_get_hash_perturb(skb, fq->perturbation); ++ idx = reciprocal_scale(hash, fq->flows_cnt); ++ flow = &fq->flows[idx]; diff --git a/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch -index bddb15a..8f7e893 100644 +index bddb15a..098bda7 100644 --- a/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch +++ b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch -@@ -1,17 +1,18 @@ --From: Felix Fietkau -+From: Felix Fietkau - Date: Sun, 7 Jun 2015 13:53:35 +0200 +@@ -3,15 +3,16 @@ Date: Sun, 7 Jun 2015 13:53:35 +0200 Subject: [PATCH] ath9k: force rx_clear when disabling rx This makes stopping Rx more reliable and should reduce the frequency of @@ -1539,25 +1386,6 @@ index bddb15a..8f7e893 100644 ath9k_hw_disable_mib_counters(ah); } -diff --git a/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch -index a160dc4..358d028 100644 ---- a/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch -+++ b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch -@@ -1,4 +1,4 @@ --From: Felix Fietkau -+From: Felix Fietkau - Date: Thu, 2 Jul 2015 15:20:56 +0200 - Subject: [PATCH] ath9k: limit retries for powersave response frames - -@@ -8,7 +8,7 @@ gone to sleep. To avoid wasting too much airtime on this, limit the - number of retries on such frames and ensure that no sample rate gets - used. - --Signed-off-by: Felix Fietkau -+Signed-off-by: Felix Fietkau - --- - - --- a/drivers/net/wireless/ath/ath9k/xmit.c diff --git a/package/kernel/mac80211/patches/302-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch b/package/kernel/mac80211/patches/302-Revert-ath9k-interpret-requested-txpower-in-EIRP-dom.patch new file mode 100644 index 0000000..7caa9be @@ -1702,158 +1530,33 @@ index 22b987a..0000000 - static const u32 qca953x_2p0_baseband_core[][2] = { - /* Addr allmodes */ - {0x00009800, 0xafe68e30}, -diff --git a/package/kernel/mac80211/patches/303-mac80211-mesh-flush-mesh-paths-unconditionally.patch b/package/kernel/mac80211/patches/303-mac80211-mesh-flush-mesh-paths-unconditionally.patch +diff --git a/package/kernel/mac80211/patches/303-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch b/package/kernel/mac80211/patches/303-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch new file mode 100644 -index 0000000..518d0a3 +index 0000000..73accd8 --- /dev/null -+++ b/package/kernel/mac80211/patches/303-mac80211-mesh-flush-mesh-paths-unconditionally.patch -@@ -0,0 +1,146 @@ -+From: Bob Copeland -+Date: Sun, 15 May 2016 13:19:16 -0400 -+Subject: [PATCH] mac80211: mesh: flush mesh paths unconditionally ++++ b/package/kernel/mac80211/patches/303-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch +@@ -0,0 +1,21 @@ ++From: Ben Greear ++Date: Fri, 1 Apr 2016 14:12:08 -0700 ++Subject: [PATCH] ath10k: Ensure txrx-compl-task is stopped when cleaning ++ htt-tx. + -+Currently, the mesh paths associated with a nexthop station are cleaned -+up in the following code path: ++Otherwise, the txrx-compl-task may access some bad memory? + -+ __sta_info_destroy_part1 -+ synchronize_net() -+ __sta_info_destroy_part2 -+ -> cleanup_single_sta -+ -> mesh_sta_cleanup -+ -> mesh_plink_deactivate -+ -> mesh_path_flush_by_nexthop -+ -+However, there are a couple of problems here: -+ -+1) the paths aren't flushed at all if the MPM is running in userspace -+ (e.g. when using wpa_supplicant or authsae) -+ -+2) there is no synchronize_rcu between removing the path and readers -+ accessing the nexthop, which means the following race is possible: -+ -+CPU0 CPU1 -+~~~~ ~~~~ -+ sta_info_destroy_part1() -+ synchronize_net() -+rcu_read_lock() -+mesh_nexthop_resolve() -+ mpath = mesh_path_lookup() -+ [...] -> mesh_path_flush_by_nexthop() -+ sta = rcu_dereference( -+ mpath->next_hop) -+ kfree(sta) -+ access sta <-- CRASH -+ -+Fix both of these by unconditionally flushing paths before destroying -+the sta, and by adding a synchronize_net() after path flush to ensure -+no active readers can still dereference the sta. -+ -+Fixes this crash: -+ -+[ 348.529295] BUG: unable to handle kernel paging request at 00020040 -+[ 348.530014] IP: [] ieee80211_mps_set_frame_flags+0x40/0xaa [mac80211] -+[ 348.530014] *pde = 00000000 -+[ 348.530014] Oops: 0000 [#1] PREEMPT -+[ 348.530014] Modules linked in: drbg ansi_cprng ctr ccm ppp_generic slhc ipt_MASQUERADE nf_nat_masquerade_ipv4 8021q ] -+[ 348.530014] CPU: 0 PID: 20597 Comm: wget Tainted: G O 4.6.0-rc5-wt=V1 #1 -+[ 348.530014] Hardware name: To Be Filled By O.E.M./To be filled by O.E.M., BIOS 080016 11/07/2014 -+[ 348.530014] task: f64fa280 ti: f4f9c000 task.ti: f4f9c000 -+[ 348.530014] EIP: 0060:[] EFLAGS: 00010246 CPU: 0 -+[ 348.530014] EIP is at ieee80211_mps_set_frame_flags+0x40/0xaa [mac80211] -+[ 348.530014] EAX: f4ce63e0 EBX: 00000088 ECX: f3788416 EDX: 00020008 -+[ 348.530014] ESI: 00000000 EDI: 00000088 EBP: f6409a4c ESP: f6409a40 -+[ 348.530014] DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068 -+[ 348.530014] CR0: 80050033 CR2: 00020040 CR3: 33190000 CR4: 00000690 -+[ 348.530014] Stack: -+[ 348.530014] 00000000 f4ce63e0 f5f9bd80 f6409a64 f9291d80 0000ce67 f5d51e00 f4ce63e0 -+[ 348.530014] f3788416 f6409a80 f9291dc1 f4ce8320 f4ce63e0 f5d51e00 f4ce63e0 f4ce8320 -+[ 348.530014] f6409a98 f9277f6f 00000000 00000000 0000007c 00000000 f6409b2c f9278dd1 -+[ 348.530014] Call Trace: -+[ 348.530014] [] mesh_nexthop_lookup+0xbb/0xc8 [mac80211] -+[ 348.530014] [] mesh_nexthop_resolve+0x34/0xd8 [mac80211] -+[ 348.530014] [] ieee80211_xmit+0x92/0xc1 [mac80211] -+[ 348.530014] [] __ieee80211_subif_start_xmit+0x807/0x83c [mac80211] -+[ 348.530014] [] ? sch_direct_xmit+0xd7/0x1b3 -+[ 348.530014] [] ? __local_bh_enable_ip+0x5d/0x7b -+[ 348.530014] [] ? nf_nat_ipv4_out+0x4c/0xd0 [nf_nat_ipv4] -+[ 348.530014] [] ? iptable_nat_ipv4_fn+0xf/0xf [iptable_nat] -+[ 348.530014] [] ? netif_skb_features+0x14d/0x30a -+[ 348.530014] [] ieee80211_subif_start_xmit+0xa/0xe [mac80211] -+[ 348.530014] [] dev_hard_start_xmit+0x1f8/0x267 -+[ 348.530014] [] ? validate_xmit_skb.isra.120.part.121+0x10/0x253 -+[ 348.530014] [] sch_direct_xmit+0x8b/0x1b3 -+[ 348.530014] [] __dev_queue_xmit+0x2c8/0x513 -+[ 348.530014] [] dev_queue_xmit+0xa/0xc -+[ 348.530014] [] batadv_send_skb_packet+0xd6/0xec [batman_adv] -+[ 348.530014] [] batadv_send_unicast_skb+0x15/0x4a [batman_adv] -+[ 348.530014] [] batadv_dat_send_data+0x27e/0x310 [batman_adv] -+[ 348.530014] [] ? batadv_tt_global_hash_find.isra.11+0x8/0xa [batman_adv] -+[ 348.530014] [] batadv_dat_snoop_outgoing_arp_request+0x208/0x23d [batman_adv] -+[ 348.530014] [] batadv_interface_tx+0x206/0x385 [batman_adv] -+[ 348.530014] [] dev_hard_start_xmit+0x1f8/0x267 -+[ 348.530014] [] ? validate_xmit_skb.isra.120.part.121+0x10/0x253 -+[ 348.530014] [] sch_direct_xmit+0x8b/0x1b3 -+[ 348.530014] [] __dev_queue_xmit+0x2c8/0x513 -+[ 348.530014] [] ? igb_xmit_frame+0x57/0x72 [igb] -+[ 348.530014] [] dev_queue_xmit+0xa/0xc -+[ 348.530014] [] br_dev_queue_push_xmit+0xeb/0xfb [bridge] -+[ 348.530014] [] br_forward_finish+0x29/0x74 [bridge] -+[ 348.530014] [] ? deliver_clone+0x3b/0x3b [bridge] -+[ 348.530014] [] __br_forward+0x89/0xe7 [bridge] -+[ 348.530014] [] ? br_dev_queue_push_xmit+0xfb/0xfb [bridge] -+[ 348.530014] [] deliver_clone+0x34/0x3b [bridge] -+[ 348.530014] [] ? br_flood+0x95/0x95 [bridge] -+[ 348.530014] [] br_flood+0x77/0x95 [bridge] -+[ 348.530014] [] br_flood_forward+0x13/0x1a [bridge] -+[ 348.530014] [] ? br_flood+0x95/0x95 [bridge] -+[ 348.530014] [] br_handle_frame_finish+0x392/0x3db [bridge] -+[ 348.530014] [] ? nf_iterate+0x2b/0x6b -+[ 348.530014] [] br_handle_frame+0x1e6/0x240 [bridge] -+[ 348.530014] [] ? br_handle_local_finish+0x6a/0x6a [bridge] -+[ 348.530014] [] __netif_receive_skb_core+0x43a/0x66b -+[ 348.530014] [] ? br_handle_frame_finish+0x3db/0x3db [bridge] -+[ 348.530014] [] ? resched_curr+0x19/0x37 -+[ 348.530014] [] ? check_preempt_wakeup+0xbf/0xfe -+[ 348.530014] [] ? ktime_get_with_offset+0x5c/0xfc -+[ 348.530014] [] __netif_receive_skb+0x47/0x55 -+[ 348.530014] [] netif_receive_skb_internal+0x40/0x5a -+[ 348.530014] [] napi_gro_receive+0x3a/0x94 -+[ 348.530014] [] igb_poll+0x6fd/0x9ad [igb] -+[ 348.530014] [] ? swake_up_locked+0x14/0x26 -+[ 348.530014] [] net_rx_action+0xde/0x250 -+[ 348.530014] [] __do_softirq+0x8a/0x163 -+[ 348.530014] [] ? __hrtimer_tasklet_trampoline+0x19/0x19 -+[ 348.530014] [] do_softirq_own_stack+0x26/0x2c -+[ 348.530014] -+[ 348.530014] [] irq_exit+0x31/0x6f -+[ 348.530014] [] do_IRQ+0x8d/0xa0 -+[ 348.530014] [] common_interrupt+0x2c/0x40 -+[ 348.530014] Code: e7 8c 00 66 81 ff 88 00 75 12 85 d2 75 0e b2 c3 b8 83 e9 29 f9 e8 a7 5f f9 c6 eb 74 66 81 e3 8c 005 -+[ 348.530014] EIP: [] ieee80211_mps_set_frame_flags+0x40/0xaa [mac80211] SS:ESP 0068:f6409a40 -+[ 348.530014] CR2: 0000000000020040 -+[ 348.530014] ---[ end trace 48556ac26779732e ]--- -+[ 348.530014] Kernel panic - not syncing: Fatal exception in interrupt -+[ 348.530014] Kernel Offset: disabled -+ -+Cc: stable@vger.kernel.org -+Reported-by: Fred Veldini -+Tested-by: Fred Veldini -+Signed-off-by: Bob Copeland ++Signed-off-by: Ben Greear +--- + -+--- a/net/mac80211/mesh.c -++++ b/net/mac80211/mesh.c -+@@ -161,6 +161,10 @@ void mesh_sta_cleanup(struct sta_info *s -+ del_timer_sync(&sta->mesh->plink_timer); -+ } ++--- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++++ b/drivers/net/wireless/ath/ath10k/htt_tx.c ++@@ -388,6 +388,8 @@ void ath10k_htt_tx_free(struct ath10k_ht ++ { ++ int size; + -++ /* make sure no readers can access nexthop sta from here on */ -++ mesh_path_flush_by_nexthop(sta); -++ synchronize_net(); +++ tasklet_kill(&htt->txrx_compl_task); ++ -+ if (changed) -+ ieee80211_mbss_info_change_notify(sdata, changed); -+ } ++ idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); ++ idr_destroy(&htt->pending_tx); ++ diff --git a/package/kernel/mac80211/patches/303-rt2x00-fix-monitor-mode-regression.patch b/package/kernel/mac80211/patches/303-rt2x00-fix-monitor-mode-regression.patch deleted file mode 100644 index 7bb7435..0000000 @@ -2016,6 +1719,72 @@ index 7bb7435..0000000 - !rt2x00dev->intf_ap_count); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, +diff --git a/package/kernel/mac80211/patches/304-ath10k-Ensure-peer_map-references-are-cleaned-up.patch b/package/kernel/mac80211/patches/304-ath10k-Ensure-peer_map-references-are-cleaned-up.patch +new file mode 100644 +index 0000000..7dec1fb +--- /dev/null ++++ b/package/kernel/mac80211/patches/304-ath10k-Ensure-peer_map-references-are-cleaned-up.patch +@@ -0,0 +1,60 @@ ++From: Ben Greear ++Date: Fri, 1 Apr 2016 14:12:09 -0700 ++Subject: [PATCH] ath10k: Ensure peer_map references are cleaned up. ++ ++While debugging OS crashes due to firmware crashes, I enabled ++kasan, and it noticed that peer objects were being used-after-freed. ++ ++Looks like there are two places we could be leaving stale references ++in the peer-map, so clean that up. ++ ++Signed-off-by: Ben Greear ++--- ++ ++--- a/drivers/net/wireless/ath/ath10k/mac.c +++++ b/drivers/net/wireless/ath/ath10k/mac.c ++@@ -802,6 +802,7 @@ static void ath10k_peer_cleanup(struct a ++ { ++ struct ath10k_peer *peer, *tmp; ++ int peer_id; +++ int i; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++@@ -818,6 +819,17 @@ static void ath10k_peer_cleanup(struct a ++ ar->peer_map[peer_id] = NULL; ++ } ++ +++ /* Double check that peer is properly un-referenced from +++ * the peer_map +++ */ +++ for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { +++ if (ar->peer_map[i] == peer) { +++ ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n", +++ peer->addr, peer, i); +++ ar->peer_map[i] = NULL; +++ } +++ } +++ ++ list_del(&peer->list); ++ kfree(peer); ++ ar->num_peers--; ++@@ -828,6 +840,7 @@ static void ath10k_peer_cleanup(struct a ++ static void ath10k_peer_cleanup_all(struct ath10k *ar) ++ { ++ struct ath10k_peer *peer, *tmp; +++ int i; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++@@ -836,6 +849,10 @@ static void ath10k_peer_cleanup_all(stru ++ list_del(&peer->list); ++ kfree(peer); ++ } +++ +++ for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) +++ ar->peer_map[i] = NULL; +++ ++ spin_unlock_bh(&ar->data_lock); ++ ++ ar->num_peers = 0; diff --git a/package/kernel/mac80211/patches/304-ath9k-avoid-ANI-restart-if-no-trigger.patch b/package/kernel/mac80211/patches/304-ath9k-avoid-ANI-restart-if-no-trigger.patch deleted file mode 100644 index 049059a..0000000 @@ -2054,64 +1823,44 @@ index 049059a..0000000 - } - } - EXPORT_SYMBOL(ath9k_hw_ani_monitor); -diff --git a/package/kernel/mac80211/patches/304-mac80211-fix-fast_tx-header-alignment.patch b/package/kernel/mac80211/patches/304-mac80211-fix-fast_tx-header-alignment.patch +diff --git a/package/kernel/mac80211/patches/305-ath10k-Clean-up-peer-when-sta-goes-away.patch b/package/kernel/mac80211/patches/305-ath10k-Clean-up-peer-when-sta-goes-away.patch new file mode 100644 -index 0000000..6316d81 +index 0000000..7248a8c --- /dev/null -+++ b/package/kernel/mac80211/patches/304-mac80211-fix-fast_tx-header-alignment.patch -@@ -0,0 +1,25 @@ -+From: Felix Fietkau -+Date: Thu, 19 May 2016 17:32:13 +0200 -+Subject: [PATCH] mac80211: fix fast_tx header alignment -+ -+The header field is defined as u8[] but also accessed as struct -+ieee80211_hdr. Enforce an alignment of 2 to prevent unnecessary -+unaligned accesses, which can be very harmful for performance on many -+platforms. -+ -+Fixes: e495c24731a2 ("mac80211: extend fast-xmit for more ciphers") -+Cc: stable@vger.kernel.org -+Signed-off-by: Felix Fietkau -+--- -+ -+--- a/net/mac80211/sta_info.h -++++ b/net/mac80211/sta_info.h -+@@ -280,7 +280,7 @@ struct ieee80211_fast_tx { -+ u8 sa_offs, da_offs, pn_offs; -+ u8 band; -+ u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV + -+- sizeof(rfc1042_header)]; -++ sizeof(rfc1042_header)] __aligned(2); -+ -+ struct rcu_head rcu_head; -+ }; -diff --git a/package/kernel/mac80211/patches/305-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch b/package/kernel/mac80211/patches/305-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch -new file mode 100644 -index 0000000..73accd8 ---- /dev/null -+++ b/package/kernel/mac80211/patches/305-ath10k-Ensure-txrx-compl-task-is-stopped-when-cleani.patch -@@ -0,0 +1,21 @@ ++++ b/package/kernel/mac80211/patches/305-ath10k-Clean-up-peer-when-sta-goes-away.patch +@@ -0,0 +1,32 @@ +From: Ben Greear -+Date: Fri, 1 Apr 2016 14:12:08 -0700 -+Subject: [PATCH] ath10k: Ensure txrx-compl-task is stopped when cleaning -+ htt-tx. ++Date: Fri, 1 Apr 2016 14:12:11 -0700 ++Subject: [PATCH] ath10k: Clean up peer when sta goes away. + -+Otherwise, the txrx-compl-task may access some bad memory? ++If WMI and/or firmware has issues removing the peer object, ++then we still need to clean up the peer object in the driver. + +Signed-off-by: Ben Greear +--- + -+--- a/drivers/net/wireless/ath/ath10k/htt_tx.c -++++ b/drivers/net/wireless/ath/ath10k/htt_tx.c -+@@ -388,6 +388,8 @@ void ath10k_htt_tx_free(struct ath10k_ht -+ { -+ int size; ++--- a/drivers/net/wireless/ath/ath10k/mac.c +++++ b/drivers/net/wireless/ath/ath10k/mac.c ++@@ -5992,9 +5992,17 @@ static int ath10k_sta_state(struct ieee8 ++ continue; + -++ tasklet_kill(&htt->txrx_compl_task); ++ if (peer->sta == sta) { ++- ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n", ++- sta->addr, arvif->vdev_id); +++ ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n", +++ sta->addr, peer, i, arvif->vdev_id); ++ peer->sta = NULL; ++ -+ idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); -+ idr_destroy(&htt->pending_tx); -+ +++ /* Clean up the peer object as well since we +++ * must have failed to do this above. +++ */ +++ list_del(&peer->list); +++ ar->peer_map[i] = NULL; +++ kfree(peer); +++ ar->num_peers--; ++ } ++ } ++ spin_unlock_bh(&ar->data_lock); diff --git a/package/kernel/mac80211/patches/305-ath9k-clean-up-ANI-per-channel-pointer-checking.patch b/package/kernel/mac80211/patches/305-ath9k-clean-up-ANI-per-channel-pointer-checking.patch deleted file mode 100644 index a1ac67c..0000000 @@ -2209,72 +1958,6 @@ index a1ac67c..0000000 - if (!ath9k_hw_ani_read_counters(ah)) - return; - -diff --git a/package/kernel/mac80211/patches/306-ath10k-Ensure-peer_map-references-are-cleaned-up.patch b/package/kernel/mac80211/patches/306-ath10k-Ensure-peer_map-references-are-cleaned-up.patch -new file mode 100644 -index 0000000..2979b4b ---- /dev/null -+++ b/package/kernel/mac80211/patches/306-ath10k-Ensure-peer_map-references-are-cleaned-up.patch -@@ -0,0 +1,60 @@ -+From: Ben Greear -+Date: Fri, 1 Apr 2016 14:12:09 -0700 -+Subject: [PATCH] ath10k: Ensure peer_map references are cleaned up. -+ -+While debugging OS crashes due to firmware crashes, I enabled -+kasan, and it noticed that peer objects were being used-after-freed. -+ -+Looks like there are two places we could be leaving stale references -+in the peer-map, so clean that up. -+ -+Signed-off-by: Ben Greear -+--- -+ -+--- a/drivers/net/wireless/ath/ath10k/mac.c -++++ b/drivers/net/wireless/ath/ath10k/mac.c -+@@ -773,6 +773,7 @@ static void ath10k_peer_cleanup(struct a -+ { -+ struct ath10k_peer *peer, *tmp; -+ int peer_id; -++ int i; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+@@ -789,6 +790,17 @@ static void ath10k_peer_cleanup(struct a -+ ar->peer_map[peer_id] = NULL; -+ } -+ -++ /* Double check that peer is properly un-referenced from -++ * the peer_map -++ */ -++ for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { -++ if (ar->peer_map[i] == peer) { -++ ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n", -++ peer->addr, peer, i); -++ ar->peer_map[i] = NULL; -++ } -++ } -++ -+ list_del(&peer->list); -+ kfree(peer); -+ ar->num_peers--; -+@@ -799,6 +811,7 @@ static void ath10k_peer_cleanup(struct a -+ static void ath10k_peer_cleanup_all(struct ath10k *ar) -+ { -+ struct ath10k_peer *peer, *tmp; -++ int i; -+ -+ lockdep_assert_held(&ar->conf_mutex); -+ -+@@ -807,6 +820,10 @@ static void ath10k_peer_cleanup_all(stru -+ list_del(&peer->list); -+ kfree(peer); -+ } -++ -++ for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) -++ ar->peer_map[i] = NULL; -++ -+ spin_unlock_bh(&ar->data_lock); -+ -+ ar->num_peers = 0; diff --git a/package/kernel/mac80211/patches/306-ath9k-do-not-reset-while-BB-panic-0x4000409-on-ar956.patch b/package/kernel/mac80211/patches/306-ath9k-do-not-reset-while-BB-panic-0x4000409-on-ar956.patch deleted file mode 100644 index cf8194a..0000000 @@ -2312,44 +1995,215 @@ index cf8194a..0000000 - return false; - else - return true; -diff --git a/package/kernel/mac80211/patches/307-ath10k-Clean-up-peer-when-sta-goes-away.patch b/package/kernel/mac80211/patches/307-ath10k-Clean-up-peer-when-sta-goes-away.patch +diff --git a/package/kernel/mac80211/patches/306-mac80211-add-hdrlen-to-ieee80211_tx_data.patch b/package/kernel/mac80211/patches/306-mac80211-add-hdrlen-to-ieee80211_tx_data.patch new file mode 100644 -index 0000000..f814ae7 +index 0000000..4a8f143 --- /dev/null -+++ b/package/kernel/mac80211/patches/307-ath10k-Clean-up-peer-when-sta-goes-away.patch -@@ -0,0 +1,32 @@ -+From: Ben Greear -+Date: Fri, 1 Apr 2016 14:12:11 -0700 -+Subject: [PATCH] ath10k: Clean up peer when sta goes away. ++++ b/package/kernel/mac80211/patches/306-mac80211-add-hdrlen-to-ieee80211_tx_data.patch +@@ -0,0 +1,203 @@ ++From: Janusz Dziedzic ++Date: Fri, 19 Feb 2016 11:01:49 +0100 ++Subject: [PATCH] mac80211: add hdrlen to ieee80211_tx_data + -+If WMI and/or firmware has issues removing the peer object, -+then we still need to clean up the peer object in the driver. ++Add hdrlen to ieee80211_tx_data and use this ++when wep/ccmd/tkip. This is preparation for ++aligned4 code. + -+Signed-off-by: Ben Greear ++Signed-off-by: Janusz Dziedzic +--- + -+--- a/drivers/net/wireless/ath/ath10k/mac.c -++++ b/drivers/net/wireless/ath/ath10k/mac.c -+@@ -5949,9 +5949,17 @@ static int ath10k_sta_state(struct ieee8 -+ continue; ++--- a/net/mac80211/ieee80211_i.h +++++ b/net/mac80211/ieee80211_i.h ++@@ -173,6 +173,7 @@ struct ieee80211_tx_data { ++ struct ieee80211_tx_rate rate; + -+ if (peer->sta == sta) { -+- ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n", -+- sta->addr, arvif->vdev_id); -++ ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n", -++ sta->addr, peer, i, arvif->vdev_id); -+ peer->sta = NULL; ++ unsigned int flags; +++ unsigned int hdrlen; ++ }; ++ ++ ++--- a/net/mac80211/tx.c +++++ b/net/mac80211/tx.c ++@@ -922,7 +922,7 @@ ieee80211_tx_h_fragment(struct ieee80211 ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_hdr *hdr = (void *)skb->data; ++ int frag_threshold = tx->local->hw.wiphy->frag_threshold; ++- int hdrlen; +++ int hdrlen = tx->hdrlen; ++ int fragnum; ++ ++ /* no matter what happens, tx->skb moves to tx->skbs */ ++@@ -943,8 +943,6 @@ ieee80211_tx_h_fragment(struct ieee80211 ++ if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU)) ++ return TX_DROP; ++ ++- hdrlen = ieee80211_hdrlen(hdr->frame_control); ++- ++ /* internal error, why isn't DONTFRAG set? */ ++ if (WARN_ON(skb->len + FCS_LEN <= frag_threshold)) ++ return TX_DROP; ++@@ -1176,6 +1174,8 @@ ieee80211_tx_prepare(struct ieee80211_su ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++ +++ tx->hdrlen = ieee80211_hdrlen(hdr->frame_control); ++ -++ /* Clean up the peer object as well since we -++ * must have failed to do this above. -++ */ -++ list_del(&peer->list); -++ ar->peer_map[i] = NULL; -++ kfree(peer); -++ ar->num_peers--; -+ } -+ } -+ spin_unlock_bh(&ar->data_lock); ++ if (likely(sta)) { ++ if (!IS_ERR(sta)) ++ tx->sta = sta; ++--- a/net/mac80211/util.c +++++ b/net/mac80211/util.c ++@@ -1226,6 +1226,7 @@ void ieee80211_send_auth(struct ieee8021 ++ struct ieee80211_local *local = sdata->local; ++ struct sk_buff *skb; ++ struct ieee80211_mgmt *mgmt; +++ unsigned int hdrlen; ++ int err; ++ ++ /* 24 + 6 = header + auth_algo + auth_transaction + status_code */ ++@@ -1250,8 +1251,10 @@ void ieee80211_send_auth(struct ieee8021 ++ memcpy(skb_put(skb, extra_len), extra, extra_len); ++ ++ if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) { +++ hdrlen = ieee80211_hdrlen(mgmt->frame_control); ++ mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); ++- err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx); +++ err = ieee80211_wep_encrypt(local, skb, hdrlen, key, +++ key_len, key_idx); ++ WARN_ON(err); ++ } ++ ++--- a/net/mac80211/wep.c +++++ b/net/mac80211/wep.c ++@@ -89,11 +89,11 @@ static void ieee80211_wep_get_iv(struct ++ ++ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, ++ struct sk_buff *skb, +++ unsigned int hdrlen, ++ int keylen, int keyidx) ++ { ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++- unsigned int hdrlen; ++ u8 *newhdr; ++ ++ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); ++@@ -101,7 +101,6 @@ static u8 *ieee80211_wep_add_iv(struct i ++ if (WARN_ON(skb_headroom(skb) < IEEE80211_WEP_IV_LEN)) ++ return NULL; ++ ++- hdrlen = ieee80211_hdrlen(hdr->frame_control); ++ newhdr = skb_push(skb, IEEE80211_WEP_IV_LEN); ++ memmove(newhdr, newhdr + IEEE80211_WEP_IV_LEN, hdrlen); ++ ++@@ -160,6 +159,7 @@ int ieee80211_wep_encrypt_data(struct cr ++ */ ++ int ieee80211_wep_encrypt(struct ieee80211_local *local, ++ struct sk_buff *skb, +++ unsigned int hdrlen, ++ const u8 *key, int keylen, int keyidx) ++ { ++ u8 *iv; ++@@ -169,7 +169,7 @@ int ieee80211_wep_encrypt(struct ieee802 ++ if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN)) ++ return -1; ++ ++- iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx); +++ iv = ieee80211_wep_add_iv(local, skb, hdrlen, keylen, keyidx); ++ if (!iv) ++ return -1; ++ ++@@ -306,13 +306,14 @@ static int wep_encrypt_skb(struct ieee80 ++ struct ieee80211_key_conf *hw_key = info->control.hw_key; ++ ++ if (!hw_key) { ++- if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key, +++ if (ieee80211_wep_encrypt(tx->local, skb, tx->hdrlen, +++ tx->key->conf.key, ++ tx->key->conf.keylen, ++ tx->key->conf.keyidx)) ++ return -1; ++ } else if ((hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) || ++ (hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) { ++- if (!ieee80211_wep_add_iv(tx->local, skb, +++ if (!ieee80211_wep_add_iv(tx->local, skb, tx->hdrlen, ++ tx->key->conf.keylen, ++ tx->key->conf.keyidx)) ++ return -1; ++--- a/net/mac80211/wep.h +++++ b/net/mac80211/wep.h ++@@ -22,6 +22,7 @@ int ieee80211_wep_encrypt_data(struct cr ++ size_t klen, u8 *data, size_t data_len); ++ int ieee80211_wep_encrypt(struct ieee80211_local *local, ++ struct sk_buff *skb, +++ unsigned int hdrlen, ++ const u8 *key, int keylen, int keyidx); ++ int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, ++ size_t klen, u8 *data, size_t data_len); ++--- a/net/mac80211/wpa.c +++++ b/net/mac80211/wpa.c ++@@ -43,7 +43,7 @@ ieee80211_tx_h_michael_mic_add(struct ie ++ skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control)) ++ return TX_CONTINUE; ++ ++- hdrlen = ieee80211_hdrlen(hdr->frame_control); +++ hdrlen = tx->hdrlen; ++ if (skb->len < hdrlen) ++ return TX_DROP; ++ ++@@ -186,7 +186,6 @@ mic_fail_no_key: ++ ++ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ++ { ++- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; ++ struct ieee80211_key *key = tx->key; ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ unsigned int hdrlen; ++@@ -201,7 +200,7 @@ static int tkip_encrypt_skb(struct ieee8 ++ return 0; ++ } ++ ++- hdrlen = ieee80211_hdrlen(hdr->frame_control); +++ hdrlen = tx->hdrlen; ++ len = skb->len - hdrlen; ++ ++ if (info->control.hw_key) ++@@ -418,7 +417,7 @@ static int ccmp_encrypt_skb(struct ieee8 ++ return 0; ++ } ++ ++- hdrlen = ieee80211_hdrlen(hdr->frame_control); +++ hdrlen = tx->hdrlen; ++ len = skb->len - hdrlen; ++ ++ if (info->control.hw_key) ++@@ -651,7 +650,7 @@ static int gcmp_encrypt_skb(struct ieee8 ++ return 0; ++ } ++ ++- hdrlen = ieee80211_hdrlen(hdr->frame_control); +++ hdrlen = tx->hdrlen; ++ len = skb->len - hdrlen; ++ ++ if (info->control.hw_key) ++@@ -791,7 +790,6 @@ static ieee80211_tx_result ++ ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx, ++ struct sk_buff *skb) ++ { ++- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++ struct ieee80211_key *key = tx->key; ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ int hdrlen; ++@@ -807,8 +805,7 @@ ieee80211_crypto_cs_encrypt(struct ieee8 ++ pskb_expand_head(skb, iv_len, 0, GFP_ATOMIC))) ++ return TX_DROP; ++ ++- hdrlen = ieee80211_hdrlen(hdr->frame_control); ++- +++ hdrlen = tx->hdrlen; ++ pos = skb_push(skb, iv_len); ++ memmove(pos, pos + iv_len, hdrlen); ++ diff --git a/package/kernel/mac80211/patches/307-ath9k-fix-inconsistent-use-of-tab-and-space-in-inden.patch b/package/kernel/mac80211/patches/307-ath9k-fix-inconsistent-use-of-tab-and-space-in-inden.patch deleted file mode 100644 index 80b781c..0000000 @@ -2383,78 +2237,325 @@ index 80b781c..0000000 - else - return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), - AR9300_PAPRD_SCALE_1); -diff --git a/package/kernel/mac80211/patches/308-ath10k-remove-duplicate-and-unused-rx-rate-flags.patch b/package/kernel/mac80211/patches/308-ath10k-remove-duplicate-and-unused-rx-rate-flags.patch +diff --git a/package/kernel/mac80211/patches/307-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch b/package/kernel/mac80211/patches/307-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch new file mode 100644 -index 0000000..7c5c5be +index 0000000..eeb881e --- /dev/null -+++ b/package/kernel/mac80211/patches/308-ath10k-remove-duplicate-and-unused-rx-rate-flags.patch -@@ -0,0 +1,66 @@ ++++ b/package/kernel/mac80211/patches/307-mac80211-add-NEED_ALIGNED4_SKBS-hw-flag.patch +@@ -0,0 +1,235 @@ ++From: Janusz Dziedzic ++Date: Fri, 19 Feb 2016 11:01:50 +0100 ++Subject: [PATCH] mac80211: add NEED_ALIGNED4_SKBS hw flag ++ ++HW/driver should set NEED_ALIGNED4_SKBS flag in case ++require aligned skbs to four-byte boundaries. ++This affect only TX direction. ++ ++Padding is added after ieee80211_hdr, before IV/LLC. ++ ++Before we have to do memmove(hdrlen) twice in the ++dirver. Once before we pass this to HW and next ++in tx completion (to be sure monitor will report ++this tx frame correctly). ++ ++With this patch we can skip this memmove() and save CPU. ++ ++Currently this was tested with ath9k, both hw/sw crypt for ++wep/tkip/ccmp. ++ ++Signed-off-by: Janusz Dziedzic ++--- ++ ++--- a/include/net/mac80211.h +++++ b/include/net/mac80211.h ++@@ -2014,6 +2014,9 @@ struct ieee80211_txq { ++ * @IEEE80211_HW_TX_FRAG_LIST: Hardware (or driver) supports sending frag_list ++ * skbs, needed for zero-copy software A-MSDU. ++ * +++ * @IEEE80211_HW_NEEDS_ALIGNED4_SKBS: Driver need aligned skbs to four-byte. +++ * Padding will be added after ieee80211_hdr, before IV/LLC. +++ * ++ * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays ++ */ ++ enum ieee80211_hw_flags { ++@@ -2054,6 +2057,7 @@ enum ieee80211_hw_flags { ++ IEEE80211_HW_USES_RSS, ++ IEEE80211_HW_TX_AMSDU, ++ IEEE80211_HW_TX_FRAG_LIST, +++ IEEE80211_HW_NEEDS_ALIGNED4_SKBS, ++ ++ /* keep last, obviously */ ++ NUM_IEEE80211_HW_FLAGS ++--- a/net/mac80211/debugfs.c +++++ b/net/mac80211/debugfs.c ++@@ -302,6 +302,7 @@ static const char *hw_flag_names[] = { ++ FLAG(USES_RSS), ++ FLAG(TX_AMSDU), ++ FLAG(TX_FRAG_LIST), +++ FLAG(NEEDS_ALIGNED4_SKBS), ++ #undef FLAG ++ }; ++ ++--- a/net/mac80211/ieee80211_i.h +++++ b/net/mac80211/ieee80211_i.h ++@@ -1497,6 +1497,29 @@ ieee80211_have_rx_timestamp(struct ieee8 ++ return false; ++ } ++ +++static inline unsigned int +++ieee80211_hdr_padsize(struct ieee80211_hw *hw, unsigned int hdrlen) +++{ +++ /* +++ * While hdrlen is already aligned to two-byte boundaries, +++ * simple check with & 2 will return correct padsize. +++ */ +++ if (ieee80211_hw_check(hw, NEEDS_ALIGNED4_SKBS)) +++ return hdrlen & 2; +++ return 0; +++} +++ +++static inline unsigned int +++ieee80211_padded_hdrlen(struct ieee80211_hw *hw, __le16 fc) +++{ +++ unsigned int hdrlen; +++ +++ hdrlen = ieee80211_hdrlen(fc); +++ hdrlen += ieee80211_hdr_padsize(hw, hdrlen); +++ +++ return hdrlen; +++} +++ ++ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, ++ struct ieee80211_rx_status *status, ++ unsigned int mpdu_len, ++--- a/net/mac80211/sta_info.h +++++ b/net/mac80211/sta_info.h ++@@ -279,7 +279,7 @@ struct ieee80211_fast_tx { ++ u8 hdr_len; ++ u8 sa_offs, da_offs, pn_offs; ++ u8 band; ++- u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV + +++ u8 hdr[30 + 2 + 2 + IEEE80211_FAST_XMIT_MAX_IV + ++ sizeof(rfc1042_header)] __aligned(2); ++ ++ struct rcu_head rcu_head; ++--- a/net/mac80211/status.c +++++ b/net/mac80211/status.c ++@@ -683,9 +683,22 @@ void ieee80211_tx_monitor(struct ieee802 ++ struct sk_buff *skb2; ++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ieee80211_sub_if_data *sdata; +++ struct ieee80211_hdr *hdr = (void *)skb->data; ++ struct net_device *prev_dev = NULL; +++ unsigned int hdrlen, padsize; ++ int rtap_len; ++ +++ /* Remove padding if was added */ +++ if (ieee80211_hw_check(&local->hw, NEEDS_ALIGNED4_SKBS)) { +++ hdrlen = ieee80211_hdrlen(hdr->frame_control); +++ padsize = ieee80211_hdr_padsize(&local->hw, hdrlen); +++ +++ if (padsize && skb->len > hdrlen + padsize) { +++ memmove(skb->data + padsize, skb->data, hdrlen); +++ skb_pull(skb, padsize); +++ } +++ } +++ ++ /* send frame to monitor interfaces now */ ++ rtap_len = ieee80211_tx_radiotap_len(info); ++ if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) { ++--- a/net/mac80211/tkip.c +++++ b/net/mac80211/tkip.c ++@@ -201,10 +201,12 @@ void ieee80211_get_tkip_p2k(struct ieee8 ++ { ++ struct ieee80211_key *key = (struct ieee80211_key *) ++ container_of(keyconf, struct ieee80211_key, conf); +++ struct ieee80211_hw *hw = &key->local->hw; ++ const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; ++ struct tkip_ctx *ctx = &key->u.tkip.tx; ++ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; ++- const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control); +++ const u8 *data = (u8 *)hdr + ieee80211_padded_hdrlen(hw, +++ hdr->frame_control); ++ u32 iv32 = get_unaligned_le32(&data[4]); ++ u16 iv16 = data[2] | (data[0] << 8); ++ ++--- a/net/mac80211/tx.c +++++ b/net/mac80211/tx.c ++@@ -1173,8 +1173,7 @@ ieee80211_tx_prepare(struct ieee80211_su ++ info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING; ++ ++ hdr = (struct ieee80211_hdr *) skb->data; ++- ++- tx->hdrlen = ieee80211_hdrlen(hdr->frame_control); +++ tx->hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control); ++ ++ if (likely(sta)) { ++ if (!IS_ERR(sta)) ++@@ -2108,7 +2107,7 @@ netdev_tx_t ieee80211_monitor_start_xmit ++ goto fail; ++ ++ hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); ++- hdrlen = ieee80211_hdrlen(hdr->frame_control); +++ hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control); ++ ++ if (skb->len < len_rthdr + hdrlen) ++ goto fail; ++@@ -2334,7 +2333,7 @@ static struct sk_buff *ieee80211_build_h ++ struct ieee80211_chanctx_conf *chanctx_conf; ++ struct ieee80211_sub_if_data *ap_sdata; ++ enum nl80211_band band; ++- int ret; +++ int padsize, ret; ++ ++ if (IS_ERR(sta)) ++ sta = NULL; ++@@ -2554,6 +2553,9 @@ static struct sk_buff *ieee80211_build_h ++ hdrlen += 2; ++ } ++ +++ /* Check aligned4 skb required */ +++ padsize = ieee80211_hdr_padsize(&sdata->local->hw, hdrlen); +++ ++ /* ++ * Drop unicast frames to unauthorised stations unless they are ++ * EAPOL frames from the local station. ++@@ -2640,6 +2642,7 @@ static struct sk_buff *ieee80211_build_h ++ h_pos -= skip_header_bytes; ++ ++ head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); +++ head_need += padsize; ++ ++ /* ++ * So we need to modify the skb header and hence need a copy of ++@@ -2678,6 +2681,9 @@ static struct sk_buff *ieee80211_build_h ++ } ++ #endif ++ +++ if (padsize) +++ memset(skb_push(skb, padsize), 0, padsize); +++ ++ if (ieee80211_is_data_qos(fc)) { ++ __le16 *qos_control; ++ ++@@ -2691,8 +2697,8 @@ static struct sk_buff *ieee80211_build_h ++ } else ++ memcpy(skb_push(skb, hdrlen), &hdr, hdrlen); ++ ++- nh_pos += hdrlen; ++- h_pos += hdrlen; +++ nh_pos += hdrlen + padsize; +++ h_pos += hdrlen + padsize; ++ ++ /* Update skb pointers to various headers since this modified frame ++ * is going to go through Linux networking code that may potentially ++@@ -2861,6 +2867,9 @@ void ieee80211_check_fast_xmit(struct st ++ fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); ++ } ++ +++ /* Check aligned4 skb required */ +++ build.hdr_len += ieee80211_hdr_padsize(&local->hw, build.hdr_len); +++ ++ /* We store the key here so there's no point in using rcu_dereference() ++ * but that's fine because the code that changes the pointers will call ++ * this function after doing so. For a single CPU that would be enough, ++--- a/net/mac80211/util.c +++++ b/net/mac80211/util.c ++@@ -1224,6 +1224,7 @@ void ieee80211_send_auth(struct ieee8021 ++ u32 tx_flags) ++ { ++ struct ieee80211_local *local = sdata->local; +++ struct ieee80211_hw *hw = &local->hw; ++ struct sk_buff *skb; ++ struct ieee80211_mgmt *mgmt; ++ unsigned int hdrlen; ++@@ -1251,7 +1252,7 @@ void ieee80211_send_auth(struct ieee8021 ++ memcpy(skb_put(skb, extra_len), extra, extra_len); ++ ++ if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) { ++- hdrlen = ieee80211_hdrlen(mgmt->frame_control); +++ hdrlen = ieee80211_padded_hdrlen(hw, mgmt->frame_control); ++ mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); ++ err = ieee80211_wep_encrypt(local, skb, hdrlen, key, ++ key_len, key_idx); +diff --git a/package/kernel/mac80211/patches/308-ath10k-Fix-sending-NULL-Qos-NULL-data-frames-for-QCA.patch b/package/kernel/mac80211/patches/308-ath10k-Fix-sending-NULL-Qos-NULL-data-frames-for-QCA.patch +new file mode 100644 +index 0000000..8590aad +--- /dev/null ++++ b/package/kernel/mac80211/patches/308-ath10k-Fix-sending-NULL-Qos-NULL-data-frames-for-QCA.patch +@@ -0,0 +1,72 @@ +From: Mohammed Shafi Shajakhan -+Date: Thu, 2 Jun 2016 19:54:41 +0530 -+Subject: [PATCH] ath10k: remove duplicate and unused rx rate flags ++Date: Thu, 23 Jun 2016 22:10:01 +0530 ++Subject: [PATCH] ath10k: Fix sending NULL/ Qos NULL data frames for ++ QCA99X0 and later + -+All these flags are not used and their use is completely -+covered by 'ath10k_hw_rate_ofdm', 'ath10k_hw_rate_cck', -+and RX_PPDU_START_RATE_FLAG ++For chipsets like QCA99X0, IPQ4019 and later we are not getting proper ++NULL func status (always acked/successs !!) when hostapd does a ++PROBE_CLIENT via nullfunc frames when the station is powered off ++abruptly (inactive timer probes client via null func after the inactive ++time reaches beyond the threshold). Fix this by disabling the workaround ++(getting the ACK status of NULL func frames by sending via HTT mgmt-tx ++ path) introduced by the change ("ath10k: fix beacon loss handling ") ++for QCA99X0 and later chipsets. The normal tx path provides the proper ++ACK status for NULL data frames. As of now disable this workaround for ++chipsets QCA99X0 and later, once the 10.1 firmware is obselete we can ++completely get rid of this workaround for all the chipsets + ++Signed-off-by: Tamizh chelvam +Signed-off-by: Mohammed Shafi Shajakhan +--- + -+--- a/drivers/net/wireless/ath/ath10k/rx_desc.h -++++ b/drivers/net/wireless/ath/ath10k/rx_desc.h -+@@ -656,26 +656,6 @@ struct rx_msdu_end { -+ * Reserved: HW should fill with zero. FW should ignore. -+ */ ++--- a/drivers/net/wireless/ath/ath10k/core.c +++++ b/drivers/net/wireless/ath/ath10k/core.c ++@@ -181,6 +181,7 @@ static const struct ath10k_hw_params ath ++ .board = QCA99X0_HW_2_0_BOARD_DATA_FILE, ++ .board_size = QCA99X0_BOARD_DATA_SZ, ++ .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, +++ .disable_null_func_workaround = true, ++ }, ++ }, ++ { ++@@ -204,6 +205,7 @@ static const struct ath10k_hw_params ath ++ .board = QCA9984_HW_1_0_BOARD_DATA_FILE, ++ .board_size = QCA99X0_BOARD_DATA_SZ, ++ .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, +++ .disable_null_func_workaround = true, ++ }, ++ }, ++ { ++@@ -262,6 +264,7 @@ static const struct ath10k_hw_params ath ++ .board = QCA4019_HW_1_0_BOARD_DATA_FILE, ++ .board_size = QCA4019_BOARD_DATA_SZ, ++ .board_ext_size = QCA4019_BOARD_EXT_DATA_SZ, +++ .disable_null_func_workaround = true, ++ }, ++ }, ++ }; ++--- a/drivers/net/wireless/ath/ath10k/core.h +++++ b/drivers/net/wireless/ath/ath10k/core.h ++@@ -750,6 +750,12 @@ struct ath10k { ++ const char *board; ++ size_t board_size; ++ size_t board_ext_size; +++ /* Workaround of sending NULL data frames via +++ * HTT mgmt TX and getting the proper ACK status does +++ * not works for chipsets QCA99X0 and later, while +++ * Tx data path reports the ACK status properly. +++ */ +++ bool disable_null_func_workaround; ++ } fw; ++ } hw_params; + -+-#define RX_PPDU_START_SIG_RATE_SELECT_OFDM 0 -+-#define RX_PPDU_START_SIG_RATE_SELECT_CCK 1 -+- -+-#define RX_PPDU_START_SIG_RATE_OFDM_48 0 -+-#define RX_PPDU_START_SIG_RATE_OFDM_24 1 -+-#define RX_PPDU_START_SIG_RATE_OFDM_12 2 -+-#define RX_PPDU_START_SIG_RATE_OFDM_6 3 -+-#define RX_PPDU_START_SIG_RATE_OFDM_54 4 -+-#define RX_PPDU_START_SIG_RATE_OFDM_36 5 -+-#define RX_PPDU_START_SIG_RATE_OFDM_18 6 -+-#define RX_PPDU_START_SIG_RATE_OFDM_9 7 -+- -+-#define RX_PPDU_START_SIG_RATE_CCK_LP_11 0 -+-#define RX_PPDU_START_SIG_RATE_CCK_LP_5_5 1 -+-#define RX_PPDU_START_SIG_RATE_CCK_LP_2 2 -+-#define RX_PPDU_START_SIG_RATE_CCK_LP_1 3 -+-#define RX_PPDU_START_SIG_RATE_CCK_SP_11 4 -+-#define RX_PPDU_START_SIG_RATE_CCK_SP_5_5 5 -+-#define RX_PPDU_START_SIG_RATE_CCK_SP_2 6 -+- -+ #define HTT_RX_PPDU_START_PREAMBLE_LEGACY 0x04 -+ #define HTT_RX_PPDU_START_PREAMBLE_HT 0x08 -+ #define HTT_RX_PPDU_START_PREAMBLE_HT_WITH_TXBF 0x09 -+@@ -711,25 +691,6 @@ struct rx_msdu_end { -+ /* No idea what this flag means. It seems to be always set in rate. */ -+ #define RX_PPDU_START_RATE_FLAG BIT(3) -+ -+-enum rx_ppdu_start_rate { -+- RX_PPDU_START_RATE_OFDM_48M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_48M, -+- RX_PPDU_START_RATE_OFDM_24M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_24M, -+- RX_PPDU_START_RATE_OFDM_12M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_12M, -+- RX_PPDU_START_RATE_OFDM_6M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_6M, -+- RX_PPDU_START_RATE_OFDM_54M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_54M, -+- RX_PPDU_START_RATE_OFDM_36M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_36M, -+- RX_PPDU_START_RATE_OFDM_18M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_18M, -+- RX_PPDU_START_RATE_OFDM_9M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_OFDM_9M, -+- -+- RX_PPDU_START_RATE_CCK_LP_11M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_11M, -+- RX_PPDU_START_RATE_CCK_LP_5_5M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_5_5M, -+- RX_PPDU_START_RATE_CCK_LP_2M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_2M, -+- RX_PPDU_START_RATE_CCK_LP_1M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_LP_1M, -+- RX_PPDU_START_RATE_CCK_SP_11M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_11M, -+- RX_PPDU_START_RATE_CCK_SP_5_5M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_5_5M, -+- RX_PPDU_START_RATE_CCK_SP_2M = RX_PPDU_START_RATE_FLAG | ATH10K_HW_RATE_CCK_SP_2M, -+-}; -+- -+ struct rx_ppdu_start { -+ struct { -+ u8 pri20_mhz; ++--- a/drivers/net/wireless/ath/ath10k/mac.c +++++ b/drivers/net/wireless/ath/ath10k/mac.c ++@@ -3253,6 +3253,7 @@ ath10k_mac_tx_h_get_txmode(struct ath10k ++ * mode though because AP don't sleep. ++ */ ++ if (ar->htt.target_version_major < 3 && +++ !ar->hw_params.fw.disable_null_func_workaround && ++ (ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) && ++ !test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, ++ ar->running_fw->fw_file.fw_features)) diff --git a/package/kernel/mac80211/patches/308-ath9k-fix-data-bus-error-on-ar9300-and-ar9580.patch b/package/kernel/mac80211/patches/308-ath9k-fix-data-bus-error-on-ar9300-and-ar9580.patch deleted file mode 100644 index d408866..0000000 @@ -2675,225 +2776,48 @@ index 711e019..0000000 - void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev, - enum brcmf_sdiod_state state); - #ifdef CONFIG_PM_SLEEP -diff --git a/package/kernel/mac80211/patches/309-ath10k-fix-CCK-h-w-rates-for-QCA99X0-and-newer-chips.patch b/package/kernel/mac80211/patches/309-ath10k-fix-CCK-h-w-rates-for-QCA99X0-and-newer-chips.patch +diff --git a/package/kernel/mac80211/patches/309-cfg80211-fix-proto-in-ieee80211_data_to_8023-for-fra.patch b/package/kernel/mac80211/patches/309-cfg80211-fix-proto-in-ieee80211_data_to_8023-for-fra.patch new file mode 100644 -index 0000000..50ebfce +index 0000000..41c27ca --- /dev/null -+++ b/package/kernel/mac80211/patches/309-ath10k-fix-CCK-h-w-rates-for-QCA99X0-and-newer-chips.patch -@@ -0,0 +1,141 @@ -+From: Mohammed Shafi Shajakhan -+Date: Thu, 2 Jun 2016 19:54:42 +0530 -+Subject: [PATCH] ath10k: fix CCK h/w rates for QCA99X0 and newer chipsets ++++ b/package/kernel/mac80211/patches/309-cfg80211-fix-proto-in-ieee80211_data_to_8023-for-fra.patch +@@ -0,0 +1,37 @@ ++From: Felix Fietkau ++Date: Wed, 29 Jun 2016 10:02:32 +0200 ++Subject: [PATCH] cfg80211: fix proto in ieee80211_data_to_8023 for frames ++ without LLC header + -+CCK hardware table mapping from QCA99X0 onwards got revised. -+The CCK hardware rate values are in a proper order wrt. to -+rate and preamble as below ++The PDU length of incoming LLC frames is set to the total skb payload size ++in __ieee80211_data_to_8023() of net/wireless/util.c which incorrectly ++includes the length of the IEEE 802.11 header. + -+ATH10K_HW_RATE_REV2_CCK_LP_1M = 1, -+ATH10K_HW_RATE_REV2_CCK_LP_2M = 2, -+ATH10K_HW_RATE_REV2_CCK_LP_5_5M = 3, -+ATH10K_HW_RATE_REV2_CCK_LP_11M = 4, -+ATH10K_HW_RATE_REV2_CCK_SP_2M = 5, -+ATH10K_HW_RATE_REV2_CCK_SP_5_5M = 6, -+ATH10K_HW_RATE_REV2_CCK_SP_11M = 7, ++The resulting LLC frame header has a too large PDU length, causing the ++llc_fixup_skb() function of net/llc/llc_input.c to reject the incoming ++skb, effectively breaking STP. + -+This results in reporting of rx frames (with CCK rates) -+totally wrong for QCA99X0, QCA4019. Fix this by having -+separate CCK rate table for these chipsets with rev2 suffix -+and registering the correct rate mapping to mac80211 based on -+the new hw_param (introduced) 'cck_rate_map_rev2' which shall -+be true for any newchipsets from QCA99X0 onwards ++Solve the problem by properly substracting the IEEE 802.11 frame header size ++from the PDU length, allowing the LLC processor to pick up the incoming ++control messages. + -+Signed-off-by: Mohammed Shafi Shajakhan ++Special thanks to Gerry Rozema for tracking down the regression and proposing ++a suitable patch. ++ ++Fixes: 2d1c304cb2d5 ("cfg80211: add function for 802.3 conversion with separate output buffer") ++Cc: stable@vger.kernel.org ++Reported-by: Gerry Rozema ++Signed-off-by: Felix Fietkau +--- + -+--- a/drivers/net/wireless/ath/ath10k/core.c -++++ b/drivers/net/wireless/ath/ath10k/core.c -+@@ -148,6 +148,8 @@ static const struct ath10k_hw_params ath -+ .uart_pin = 7, -+ .otp_exe_param = 0x00000700, -+ .continuous_frag_desc = true, -++ .cck_rate_map_rev2 = true, -++ .cck_rate_map_rev2 = true, -+ .channel_counters_freq_hz = 150000, -+ .max_probe_resp_desc_thres = 24, -+ .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, -+@@ -205,6 +207,7 @@ static const struct ath10k_hw_params ath -+ .has_shifted_cc_wraparound = true, -+ .otp_exe_param = 0x0010000, -+ .continuous_frag_desc = true, -++ .cck_rate_map_rev2 = true, -+ .channel_counters_freq_hz = 125000, -+ .max_probe_resp_desc_thres = 24, -+ .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, -+--- a/drivers/net/wireless/ath/ath10k/core.h -++++ b/drivers/net/wireless/ath/ath10k/core.h -+@@ -716,6 +716,12 @@ struct ath10k { -+ */ -+ bool continuous_frag_desc; ++--- a/net/wireless/util.c +++++ b/net/wireless/util.c ++@@ -509,7 +509,7 @@ static int __ieee80211_data_to_8023(stru ++ * replace EtherType */ ++ hdrlen += ETH_ALEN + 2; ++ else ++- tmp.h_proto = htons(skb->len); +++ tmp.h_proto = htons(skb->len - hdrlen); + -++ /* CCK hardware rate table mapping for the newer chipsets -++ * like QCA99X0, QCA4019 got revised. The CCK h/w rate values -++ * are in a proper order with respect to the rate/preamble -++ */ -++ bool cck_rate_map_rev2; -++ -+ u32 channel_counters_freq_hz; -+ -+ /* Mgmt tx descriptors threshold for limiting probe response -+--- a/drivers/net/wireless/ath/ath10k/hw.h -++++ b/drivers/net/wireless/ath/ath10k/hw.h -+@@ -315,6 +315,16 @@ enum ath10k_hw_rate_cck { -+ ATH10K_HW_RATE_CCK_SP_2M, -+ }; -+ -++enum ath10k_hw_rate_rev2_cck { -++ ATH10K_HW_RATE_REV2_CCK_LP_1M = 1, -++ ATH10K_HW_RATE_REV2_CCK_LP_2M, -++ ATH10K_HW_RATE_REV2_CCK_LP_5_5M, -++ ATH10K_HW_RATE_REV2_CCK_LP_11M, -++ ATH10K_HW_RATE_REV2_CCK_SP_2M, -++ ATH10K_HW_RATE_REV2_CCK_SP_5_5M, -++ ATH10K_HW_RATE_REV2_CCK_SP_11M, -++}; -++ -+ enum ath10k_hw_4addr_pad { -+ ATH10K_HW_4ADDR_PAD_AFTER, -+ ATH10K_HW_4ADDR_PAD_BEFORE, -+--- a/drivers/net/wireless/ath/ath10k/mac.c -++++ b/drivers/net/wireless/ath/ath10k/mac.c -+@@ -62,6 +62,32 @@ static struct ieee80211_rate ath10k_rate -+ { .bitrate = 540, .hw_value = ATH10K_HW_RATE_OFDM_54M }, -+ }; -+ -++static struct ieee80211_rate ath10k_rates_rev2[] = { -++ { .bitrate = 10, -++ .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_1M }, -++ { .bitrate = 20, -++ .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_2M, -++ .hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_2M, -++ .flags = IEEE80211_RATE_SHORT_PREAMBLE }, -++ { .bitrate = 55, -++ .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_5_5M, -++ .hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_5_5M, -++ .flags = IEEE80211_RATE_SHORT_PREAMBLE }, -++ { .bitrate = 110, -++ .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_11M, -++ .hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_11M, -++ .flags = IEEE80211_RATE_SHORT_PREAMBLE }, -++ -++ { .bitrate = 60, .hw_value = ATH10K_HW_RATE_OFDM_6M }, -++ { .bitrate = 90, .hw_value = ATH10K_HW_RATE_OFDM_9M }, -++ { .bitrate = 120, .hw_value = ATH10K_HW_RATE_OFDM_12M }, -++ { .bitrate = 180, .hw_value = ATH10K_HW_RATE_OFDM_18M }, -++ { .bitrate = 240, .hw_value = ATH10K_HW_RATE_OFDM_24M }, -++ { .bitrate = 360, .hw_value = ATH10K_HW_RATE_OFDM_36M }, -++ { .bitrate = 480, .hw_value = ATH10K_HW_RATE_OFDM_48M }, -++ { .bitrate = 540, .hw_value = ATH10K_HW_RATE_OFDM_54M }, -++}; -++ -+ #define ATH10K_MAC_FIRST_OFDM_RATE_IDX 4 -+ -+ #define ath10k_a_rates (ath10k_rates + ATH10K_MAC_FIRST_OFDM_RATE_IDX) -+@@ -70,6 +96,9 @@ static struct ieee80211_rate ath10k_rate -+ #define ath10k_g_rates (ath10k_rates + 0) -+ #define ath10k_g_rates_size (ARRAY_SIZE(ath10k_rates)) -+ -++#define ath10k_g_rates_rev2 (ath10k_rates_rev2 + 0) -++#define ath10k_g_rates_rev2_size (ARRAY_SIZE(ath10k_rates_rev2)) -++ -+ static bool ath10k_mac_bitrate_is_cck(int bitrate) -+ { -+ switch (bitrate) { -+@@ -7720,8 +7749,14 @@ int ath10k_mac_register(struct ath10k *a -+ band = &ar->mac.sbands[NL80211_BAND_2GHZ]; -+ band->n_channels = ARRAY_SIZE(ath10k_2ghz_channels); -+ band->channels = channels; -+- band->n_bitrates = ath10k_g_rates_size; -+- band->bitrates = ath10k_g_rates; -++ -++ if (ar->hw_params.cck_rate_map_rev2) { -++ band->n_bitrates = ath10k_g_rates_rev2_size; -++ band->bitrates = ath10k_g_rates_rev2; -++ } else { -++ band->n_bitrates = ath10k_g_rates_size; -++ band->bitrates = ath10k_g_rates; -++ } -+ -+ ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band; -+ } -diff --git a/package/kernel/mac80211/patches/310-ath10k-improve-tx-scheduling.patch b/package/kernel/mac80211/patches/310-ath10k-improve-tx-scheduling.patch -new file mode 100644 -index 0000000..81ac2db ---- /dev/null -+++ b/package/kernel/mac80211/patches/310-ath10k-improve-tx-scheduling.patch -@@ -0,0 +1,67 @@ -+From: Michal Kazior -+Date: Mon, 23 May 2016 23:12:45 +0300 -+Subject: [PATCH] ath10k: improve tx scheduling -+ -+Recent changes revolving around implementing -+wake_tx_queue support introduced a significant -+performance regressions on some (slower, uni-proc) -+systems. -+ -+Signed-off-by: Michal Kazior -+Signed-off-by: Kalle Valo -+--- -+ -+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c -++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -+@@ -2291,7 +2291,6 @@ bool ath10k_htt_t2h_msg_handler(struct a -+ ath10k_htt_tx_mgmt_dec_pending(htt); -+ spin_unlock_bh(&htt->tx_lock); -+ } -+- ath10k_mac_tx_push_pending(ar); -+ break; -+ } -+ case HTT_T2H_MSG_TYPE_TX_COMPL_IND: -+@@ -2442,8 +2441,6 @@ static void ath10k_htt_txrx_compl_task(u -+ dev_kfree_skb_any(skb); -+ } -+ -+- ath10k_mac_tx_push_pending(ar); -+- -+ num_mpdus = atomic_read(&htt->num_mpdus_ready); -+ -+ while (num_mpdus) { -+--- a/drivers/net/wireless/ath/ath10k/mac.c -++++ b/drivers/net/wireless/ath/ath10k/mac.c -+@@ -3827,6 +3827,9 @@ void ath10k_mac_tx_push_pending(struct a -+ int ret; -+ int max; -+ -++ if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2)) -++ return; -++ -+ spin_lock_bh(&ar->txqs_lock); -+ rcu_read_lock(); -+ -+@@ -4097,9 +4100,7 @@ static void ath10k_mac_op_wake_tx_queue( -+ list_add_tail(&artxq->list, &ar->txqs); -+ spin_unlock_bh(&ar->txqs_lock); -+ -+- if (ath10k_mac_tx_can_push(hw, txq)) -+- tasklet_schedule(&ar->htt.txrx_compl_task); -+- -++ ath10k_mac_tx_push_pending(ar); -+ ath10k_htt_tx_txq_update(hw, txq); -+ } -+ -+--- a/drivers/net/wireless/ath/ath10k/txrx.c -++++ b/drivers/net/wireless/ath/ath10k/txrx.c -+@@ -117,6 +117,9 @@ int ath10k_txrx_tx_unref(struct ath10k_h -+ -+ ieee80211_tx_status(htt->ar->hw, msdu); -+ /* we do not own the msdu anymore */ -++ -++ ath10k_mac_tx_push_pending(ar); -++ -+ return 0; -+ } ++ pskb_pull(skb, hdrlen); + diff --git a/package/kernel/mac80211/patches/310-ath9k_hw-ignore-eeprom-magic-mismatch-on-flash-based.patch b/package/kernel/mac80211/patches/310-ath9k_hw-ignore-eeprom-magic-mismatch-on-flash-based.patch deleted file mode 100644 @@ -2939,71 +2863,172 @@ index 287d6e1..0000000 - ath_err(common, - "Invalid EEPROM Magic (0x%04x).\n", magic); - return -EINVAL; -diff --git a/package/kernel/mac80211/patches/311-ath10k-fix-deadlock-while-processing-rx_in_ord_ind.patch b/package/kernel/mac80211/patches/311-ath10k-fix-deadlock-while-processing-rx_in_ord_ind.patch +diff --git a/package/kernel/mac80211/patches/310-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch b/package/kernel/mac80211/patches/310-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch new file mode 100644 -index 0000000..3664d70 +index 0000000..25929c9 --- /dev/null -+++ b/package/kernel/mac80211/patches/311-ath10k-fix-deadlock-while-processing-rx_in_ord_ind.patch -@@ -0,0 +1,59 @@ -+From: Rajkumar Manoharan -+Date: Thu, 9 Jun 2016 11:33:55 +0530 -+Subject: [PATCH] ath10k: fix deadlock while processing rx_in_ord_ind ++++ b/package/kernel/mac80211/patches/310-mac80211-minstrel-Enable-STBC-and-LDPC-for-VHT-Rates.patch +@@ -0,0 +1,81 @@ ++From: Chaitanya T K ++Date: Mon, 27 Jun 2016 15:23:26 +0530 ++Subject: [PATCH] mac80211: minstrel: Enable STBC and LDPC for VHT Rates + -+commit 5c86d97bcc1d ("ath10k: combine txrx and replenish task") -+introduced deadlock while processing rx in order indication message -+for qca6174 based devices. While merging replenish and txrx tasklets, -+replenish task should be called out of htt rx ring locking since it -+is also try to acquire the same lock. ++If peer support reception of STBC and LDPC, enable them for better ++performance. + -+Unfortunately this issue is not exposed by other solutions (qca988x, -+qca99x0 & qca4019), as rx_in_ord_ind message is specific to qca6174 -+based devices. This patch fixes -+ -+============================================= -+[ INFO: possible recursive locking detected ] -+4.7.0-rc2-wt-ath+ #1353 Tainted: G E -+--------------------------------------------- -+swapper/3/0 is trying to acquire lock: -+ (&(&htt->rx_ring.lock)->rlock){+.-...}, at: [] -+ath10k_htt_rx_msdu_buff_replenish+0x29/0x90 [ath10k_core] -+ -+but task is already holding lock: -+ (&(&htt->rx_ring.lock)->rlock){+.-...}, at: [] -+ath10k_htt_txrx_compl_task+0x21b/0x250 [ath10k_core] -+ -+other info that might help us debug this: -+ Possible unsafe locking scenario: -+ -+ CPU0 -+ ---- -+ lock(&(&htt->rx_ring.lock)->rlock); -+ lock(&(&htt->rx_ring.lock)->rlock); -+ -+ *** DEADLOCK *** -+ -+ May be due to missing lock nesting notation -+ -+1 lock held by swapper/3/0: -+ #0: (&(&htt->rx_ring.lock)->rlock){+.-...}, at: [] -+ath10k_htt_txrx_compl_task+0x21b/0x250 [ath10k_core] -+ -+Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=119151 -+Fixes: 5c86d97bcc1d ("ath10k: combine txrx and replenish task") -+Reported-by: Mike Lothian -+Signed-off-by: Rajkumar Manoharan -+Signed-off-by: Kalle Valo ++Signed-off-by: Chaitanya TK +--- + -+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c -++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c -+@@ -1904,7 +1904,6 @@ static void ath10k_htt_rx_in_ord_ind(str -+ return; -+ } ++--- a/include/linux/ieee80211.h +++++ b/include/linux/ieee80211.h ++@@ -1550,6 +1550,7 @@ struct ieee80211_vht_operation { ++ #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 ++ #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 ++ #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 +++#define IEEE80211_VHT_CAP_RXSTBC_SHIFT 8 ++ #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 ++ #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 ++ #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13 ++--- a/net/mac80211/rc80211_minstrel_ht.c +++++ b/net/mac80211/rc80211_minstrel_ht.c ++@@ -1166,13 +1166,14 @@ minstrel_ht_update_caps(void *priv, stru ++ struct minstrel_ht_sta_priv *msp = priv_sta; ++ struct minstrel_ht_sta *mi = &msp->ht; ++ struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; ++- u16 sta_cap = sta->ht_cap.cap; +++ u16 ht_cap = sta->ht_cap.cap; ++ struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; ++ int use_vht; ++ int n_supported = 0; ++ int ack_dur; ++ int stbc; ++ int i; +++ bool ldpc = false; ++ ++ /* fall back to the old minstrel for legacy stations */ ++ if (!sta->ht_cap.ht_supported) ++@@ -1210,16 +1211,24 @@ minstrel_ht_update_caps(void *priv, stru + } -+- ath10k_htt_rx_msdu_buff_replenish(htt); ++ mi->sample_tries = 4; ++ ++- /* TODO tx_flags for vht - ATM the RC API is not fine-grained enough */ ++ if (!use_vht) { ++- stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >> +++ stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >> ++ IEEE80211_HT_CAP_RX_STBC_SHIFT; ++- mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT; ++ ++- if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING) ++- mi->tx_flags |= IEEE80211_TX_CTL_LDPC; +++ if (ht_cap & IEEE80211_HT_CAP_LDPC_CODING) +++ ldpc = true; +++ } else { +++ stbc = (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) >> +++ IEEE80211_VHT_CAP_RXSTBC_SHIFT; +++ +++ if (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC) +++ ldpc = true; ++ } ++ +++ mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT; +++ if (ldpc) +++ mi->tx_flags |= IEEE80211_TX_CTL_LDPC; +++ ++ for (i = 0; i < ARRAY_SIZE(mi->groups); i++) { ++ u32 gflags = minstrel_mcs_groups[i].flags; ++ int bw, nss; ++@@ -1232,10 +1241,10 @@ minstrel_ht_update_caps(void *priv, stru ++ ++ if (gflags & IEEE80211_TX_RC_SHORT_GI) { ++ if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) { ++- if (!(sta_cap & IEEE80211_HT_CAP_SGI_40)) +++ if (!(ht_cap & IEEE80211_HT_CAP_SGI_40)) ++ continue; ++ } else { ++- if (!(sta_cap & IEEE80211_HT_CAP_SGI_20)) +++ if (!(ht_cap & IEEE80211_HT_CAP_SGI_20)) ++ continue; ++ } ++ } +diff --git a/package/kernel/mac80211/patches/311-ath10k-disable-wake_tx_queue-for-older-devices.patch b/package/kernel/mac80211/patches/311-ath10k-disable-wake_tx_queue-for-older-devices.patch +new file mode 100644 +index 0000000..4cf26a6 +--- /dev/null ++++ b/package/kernel/mac80211/patches/311-ath10k-disable-wake_tx_queue-for-older-devices.patch +@@ -0,0 +1,73 @@ ++From: Michal Kazior ++Date: Tue, 17 May 2016 14:47:01 +0200 ++Subject: [PATCH] ath10k: disable wake_tx_queue for older devices ++ ++Some setups suffer performance regressions with ++current wake_tx_queue implementation. ++ ++Signed-off-by: Michal Kazior ++--- ++ ++--- a/drivers/net/wireless/ath/ath10k/core.h +++++ b/drivers/net/wireless/ath/ath10k/core.h ++@@ -667,6 +667,7 @@ struct ath10k_fw_components { ++ struct ath10k { ++ struct ath_common ath_common; ++ struct ieee80211_hw *hw; +++ struct ieee80211_ops *ops; ++ struct device *dev; ++ u8 mac_addr[ETH_ALEN]; ++ ++--- a/drivers/net/wireless/ath/ath10k/mac.c +++++ b/drivers/net/wireless/ath/ath10k/mac.c ++@@ -7497,21 +7497,32 @@ static const struct ieee80211_channel at ++ struct ath10k *ath10k_mac_create(size_t priv_size) ++ { ++ struct ieee80211_hw *hw; +++ struct ieee80211_ops *ops; ++ struct ath10k *ar; ++ ++- hw = ieee80211_alloc_hw(sizeof(struct ath10k) + priv_size, &ath10k_ops); ++- if (!hw) +++ ops = kmemdup(&ath10k_ops, sizeof(ath10k_ops), GFP_KERNEL); +++ if (!ops) +++ return NULL; +++ +++ hw = ieee80211_alloc_hw(sizeof(struct ath10k) + priv_size, ops); +++ if (!hw) { +++ kfree(ops); ++ return NULL; +++ } ++ ++ ar = hw->priv; ++ ar->hw = hw; +++ ar->ops = ops; ++ ++ return ar; + } + -+ static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar, ++ void ath10k_mac_destroy(struct ath10k *ar) ++ { +++ struct ieee80211_ops *ops = ar->ops; +++ ++ ieee80211_free_hw(ar->hw); +++ kfree(ops); ++ } ++ ++ static const struct ieee80211_iface_limit ath10k_if_limits[] = { ++@@ -7945,6 +7956,15 @@ int ath10k_mac_register(struct ath10k *a ++ ath10k_warn(ar, "failed to initialise DFS pattern detector\n"); ++ } ++ +++ /* Current wake_tx_queue implementation imposes a significant +++ * performance penalty in some setups. The tx scheduling code needs +++ * more work anyway so disable the wake_tx_queue unless firmware +++ * supports the pull-push mechanism. +++ */ +++ if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL, +++ ar->running_fw->fw_file.fw_features)) +++ ar->ops->wake_tx_queue = NULL; +++ ++ ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy, ++ ath10k_reg_notifier); ++ if (ret) { diff --git a/package/kernel/mac80211/patches/311-ath9k-do-not-limit-the-number-of-DFS-interfaces-to-1.patch b/package/kernel/mac80211/patches/311-ath9k-do-not-limit-the-number-of-DFS-interfaces-to-1.patch deleted file mode 100644 index 070efa9..0000000 @@ -3065,6 +3090,57 @@ index 070efa9..0000000 - }; - - #ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT +diff --git a/package/kernel/mac80211/patches/312-ath9k-Correct-TSF-adjustment-to-align-the-beacon-tim.patch b/package/kernel/mac80211/patches/312-ath9k-Correct-TSF-adjustment-to-align-the-beacon-tim.patch +new file mode 100644 +index 0000000..df43105 +--- /dev/null ++++ b/package/kernel/mac80211/patches/312-ath9k-Correct-TSF-adjustment-to-align-the-beacon-tim.patch +@@ -0,0 +1,45 @@ ++From: Benjamin Berg ++Date: Mon, 4 Jul 2016 14:37:20 +0200 ++Subject: [PATCH] ath9k: Correct TSF adjustment to align the beacon time ++ correctly ++ ++Beacons were not send out at (timestamp % beacon_time == 0) for interfaces ++other than the primary one. To send out beacons with the correct timestamp ++according to 10.1.3.2 of the 802.11 standard the tsf_adjustment has to be ++set to the negative time difference instead of positive. This way the ++later beacons get corrected to have a lower (and similar) timestamp with ++regard to the beacon from slot 0. ++ ++I am not aware about any issues that have been caused by this. ++ ++Signed-off-by: Benjamin Berg ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/beacon.c +++++ b/drivers/net/wireless/ath/ath9k/beacon.c ++@@ -279,17 +279,21 @@ static void ath9k_set_tsfadjust(struct a ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ struct ath_vif *avp = (void *)vif->drv_priv; ++ struct ath_beacon_config *cur_conf = &avp->chanctx->beacon; ++- u32 tsfadjust; +++ s64 tsfadjust; ++ ++ if (avp->av_bslot == 0) ++ return; ++ +++ /* tsf_adjust is added to the TSF value. We send out the beacon late, +++ * so need to adjust the TSF starting point to be later in time (i.e. +++ * the theoretical first beacon has a TSF of 0 after correction). +++ */ ++ tsfadjust = cur_conf->beacon_interval * avp->av_bslot; ++- tsfadjust = TU_TO_USEC(tsfadjust) / ATH_BCBUF; +++ tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF; ++ avp->tsf_adjust = cpu_to_le64(tsfadjust); ++ ++- ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n", ++- (unsigned long long)tsfadjust, avp->av_bslot); +++ ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n", +++ (signed long long)tsfadjust, avp->av_bslot); ++ } ++ ++ bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif) diff --git a/package/kernel/mac80211/patches/312-mac80211-fix-txq-queue-related-crashes.patch b/package/kernel/mac80211/patches/312-mac80211-fix-txq-queue-related-crashes.patch deleted file mode 100644 index 61cafc7..0000000 @@ -3098,6 +3174,82 @@ index 61cafc7..0000000 - atomic_set(&sdata->txqs_len[txqi->txq.ac], 0); - } - +diff --git a/package/kernel/mac80211/patches/313-ath9k-Handle-channel-context-in-get_-set_-reset_tsf.patch b/package/kernel/mac80211/patches/313-ath9k-Handle-channel-context-in-get_-set_-reset_tsf.patch +new file mode 100644 +index 0000000..ef0afbe +--- /dev/null ++++ b/package/kernel/mac80211/patches/313-ath9k-Handle-channel-context-in-get_-set_-reset_tsf.patch +@@ -0,0 +1,70 @@ ++From: Benjamin Berg ++Date: Mon, 4 Jul 2016 14:37:21 +0200 ++Subject: [PATCH] ath9k: Handle channel context in get_/set_/reset_tsf ++ ++The ath9k TSF handling routines need to be aware of the channel context that ++is being modified. With this change the TSF related values that are stored ++in each channel context will be correctly tracked and the harware will only ++be updated if the modified context is currently the active one. ++ ++Without this change the TSF modifications done using these routines would ++for example be lost during a hardware reset as done by ath_complete_reset. ++ ++Signed-off-by: Benjamin Berg ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/main.c +++++ b/drivers/net/wireless/ath/ath9k/main.c ++@@ -1823,11 +1823,18 @@ static void ath9k_bss_info_changed(struc ++ static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++ { ++ struct ath_softc *sc = hw->priv; +++ struct ath_vif *avp = (void *)vif->drv_priv; ++ u64 tsf; ++ ++ mutex_lock(&sc->mutex); ++ ath9k_ps_wakeup(sc); ++- tsf = ath9k_hw_gettsf64(sc->sc_ah); +++ /* Get current TSF either from HW or kernel time. */ +++ if (sc->cur_chan == avp->chanctx) { +++ tsf = ath9k_hw_gettsf64(sc->sc_ah); +++ } else { +++ tsf = sc->cur_chan->tsf_val + +++ ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL); +++ } ++ ath9k_ps_restore(sc); ++ mutex_unlock(&sc->mutex); ++ ++@@ -1839,10 +1846,14 @@ static void ath9k_set_tsf(struct ieee802 ++ u64 tsf) ++ { ++ struct ath_softc *sc = hw->priv; +++ struct ath_vif *avp = (void *)vif->drv_priv; ++ ++ mutex_lock(&sc->mutex); ++ ath9k_ps_wakeup(sc); ++- ath9k_hw_settsf64(sc->sc_ah, tsf); +++ getrawmonotonic(&avp->chanctx->tsf_ts); +++ if (sc->cur_chan == avp->chanctx) +++ ath9k_hw_settsf64(sc->sc_ah, tsf); +++ avp->chanctx->tsf_val = tsf; ++ ath9k_ps_restore(sc); ++ mutex_unlock(&sc->mutex); ++ } ++@@ -1850,11 +1861,15 @@ static void ath9k_set_tsf(struct ieee802 ++ static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) ++ { ++ struct ath_softc *sc = hw->priv; +++ struct ath_vif *avp = (void *)vif->drv_priv; ++ ++ mutex_lock(&sc->mutex); ++ ++ ath9k_ps_wakeup(sc); ++- ath9k_hw_reset_tsf(sc->sc_ah); +++ getrawmonotonic(&avp->chanctx->tsf_ts); +++ if (sc->cur_chan == avp->chanctx) +++ ath9k_hw_reset_tsf(sc->sc_ah); +++ avp->chanctx->tsf_val = 0; ++ ath9k_ps_restore(sc); ++ ++ mutex_unlock(&sc->mutex); diff --git a/package/kernel/mac80211/patches/313-mac80211-fix-unnecessary-frame-drops-in-mesh-fwding.patch b/package/kernel/mac80211/patches/313-mac80211-fix-unnecessary-frame-drops-in-mesh-fwding.patch deleted file mode 100644 index 844d43b..0000000 @@ -3161,6 +3313,77 @@ index 844d43b..0000000 - if (ieee80211_queue_stopped(&local->hw, q)) { - IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion); - return RX_DROP_MONITOR; +diff --git a/package/kernel/mac80211/patches/314-ath9k-Use-tsf-offset-helper-in-ath9k_hw_reset.patch b/package/kernel/mac80211/patches/314-ath9k-Use-tsf-offset-helper-in-ath9k_hw_reset.patch +new file mode 100644 +index 0000000..e725a8b +--- /dev/null ++++ b/package/kernel/mac80211/patches/314-ath9k-Use-tsf-offset-helper-in-ath9k_hw_reset.patch +@@ -0,0 +1,65 @@ ++From: Benjamin Berg ++Date: Mon, 4 Jul 2016 14:37:22 +0200 ++Subject: [PATCH] ath9k: Use tsf offset helper in ath9k_hw_reset ++ ++These changes make ath9k_hw_reset more consistent with other places that ++handle the TSF value by using the same helper routine. ++ ++A slight improvement is to not assume that a fixed time of 1.5ms has ++passed for the initval writes when compared to the first write attempt. ++Instead the TSF value is re-calculated which will yield a higher accuracy ++of the restored TSF timer. ++ ++Signed-off-by: Benjamin Berg ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/hw.c +++++ b/drivers/net/wireless/ath/ath9k/hw.c ++@@ -1832,8 +1832,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++ u32 saveLedState; ++ u32 saveDefAntenna; ++ u32 macStaId1; +++ struct timespec tsf_ts; +++ u32 tsf_offset; ++ u64 tsf = 0; ++- s64 usec = 0; ++ int r; ++ bool start_mci_reset = false; ++ bool save_fullsleep = ah->chip_fullsleep; ++@@ -1877,8 +1878,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++ macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; ++ ++ /* Save TSF before chip reset, a cold reset clears it */ +++ getrawmonotonic(&tsf_ts); ++ tsf = ath9k_hw_gettsf64(ah); ++- usec = ktime_to_us(ktime_get_raw()); ++ ++ saveLedState = REG_READ(ah, AR_CFG_LED) & ++ (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | ++@@ -1911,8 +1912,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++ } ++ ++ /* Restore TSF */ ++- usec = ktime_to_us(ktime_get_raw()) - usec; ++- ath9k_hw_settsf64(ah, tsf + usec); +++ tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL); +++ ath9k_hw_settsf64(ah, tsf + tsf_offset); ++ ++ if (AR_SREV_9280_20_OR_LATER(ah)) ++ REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); ++@@ -1932,12 +1933,11 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++ /* ++ * Some AR91xx SoC devices frequently fail to accept TSF writes ++ * right after the chip reset. When that happens, write a new ++- * value after the initvals have been applied, with an offset ++- * based on measured time difference +++ * value after the initvals have been applied. ++ */ ++ if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) { ++- tsf += 1500; ++- ath9k_hw_settsf64(ah, tsf); +++ tsf_offset = ath9k_hw_get_tsf_offset(&tsf_ts, NULL); +++ ath9k_hw_settsf64(ah, tsf + tsf_offset); ++ } ++ ++ ath9k_hw_init_mfp(ah); diff --git a/package/kernel/mac80211/patches/314-mac80211-Requeue-work-after-scan-complete-for-all-VI.patch b/package/kernel/mac80211/patches/314-mac80211-Requeue-work-after-scan-complete-for-all-VI.patch deleted file mode 100644 index 5b3efbd..0000000 @@ -3270,6 +3493,44 @@ index 5b3efbd..0000000 - if (was_scanning) - ieee80211_start_next_roc(local); - } +diff --git a/package/kernel/mac80211/patches/315-ath9k-Expose-tsf_adjustment-in-mac80211-tsf-getters-.patch b/package/kernel/mac80211/patches/315-ath9k-Expose-tsf_adjustment-in-mac80211-tsf-getters-.patch +new file mode 100644 +index 0000000..c95ab7e +--- /dev/null ++++ b/package/kernel/mac80211/patches/315-ath9k-Expose-tsf_adjustment-in-mac80211-tsf-getters-.patch +@@ -0,0 +1,32 @@ ++From: Benjamin Berg ++Date: Mon, 4 Jul 2016 14:37:23 +0200 ++Subject: [PATCH] ath9k: Expose tsf_adjustment in mac80211 tsf getters and ++ setters. ++ ++The ath9k driver modifies the TSF for VIFs for the purpose of sending ++beacons in a staggered fashion. This patch exposes this VIF specific ++adjustment of the TSF value to mac80211. Without the change the TSF ++routines handle the hardware TSF value instead of the actual TSF value as ++seen on the air. ++ ++Signed-off-by: Benjamin Berg ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/main.c +++++ b/drivers/net/wireless/ath/ath9k/main.c ++@@ -1835,6 +1835,7 @@ static u64 ath9k_get_tsf(struct ieee8021 ++ tsf = sc->cur_chan->tsf_val + ++ ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL); ++ } +++ tsf += le64_to_cpu(avp->tsf_adjust); ++ ath9k_ps_restore(sc); ++ mutex_unlock(&sc->mutex); ++ ++@@ -1850,6 +1851,7 @@ static void ath9k_set_tsf(struct ieee802 ++ ++ mutex_lock(&sc->mutex); ++ ath9k_ps_wakeup(sc); +++ tsf -= le64_to_cpu(avp->tsf_adjust); ++ getrawmonotonic(&avp->chanctx->tsf_ts); ++ if (sc->cur_chan == avp->chanctx) ++ ath9k_hw_settsf64(sc->sc_ah, tsf); diff --git a/package/kernel/mac80211/patches/315-mac80211-fix-ibss-scan-parameters.patch b/package/kernel/mac80211/patches/315-mac80211-fix-ibss-scan-parameters.patch deleted file mode 100644 index 52fecb9..0000000 @@ -3333,6 +3594,149 @@ index 52fecb9..0000000 - } else { - int interval = IEEE80211_SCAN_INTERVAL; - +diff --git a/package/kernel/mac80211/patches/316-ath9k-Remove-some-defined-constants-to-decrease-verb.patch b/package/kernel/mac80211/patches/316-ath9k-Remove-some-defined-constants-to-decrease-verb.patch +new file mode 100644 +index 0000000..36aaa10 +--- /dev/null ++++ b/package/kernel/mac80211/patches/316-ath9k-Remove-some-defined-constants-to-decrease-verb.patch +@@ -0,0 +1,137 @@ ++From: Benjamin Berg ++Date: Mon, 4 Jul 2016 14:37:24 +0200 ++Subject: [PATCH] ath9k: Remove some #defined constants to decrease ++ verbosity ++ ++The removed ATH9K_SLOT_TIME_X constants simply map the value in microseconds ++to the same integer. These constants were not used consistently, so fix the ++inconsistency issue by replacing all occurances with the integer equivalent. ++ ++Signed-off-by: Benjamin Berg ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/beacon.c +++++ b/drivers/net/wireless/ath/ath9k/beacon.c ++@@ -50,7 +50,7 @@ static void ath9k_beaconq_config(struct ++ txq = sc->tx.txq_map[IEEE80211_AC_BE]; ++ ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); ++ qi.tqi_aifs = qi_be.tqi_aifs; ++- if (ah->slottime == ATH9K_SLOT_TIME_20) +++ if (ah->slottime == 20) ++ qi.tqi_cwmin = 2*qi_be.tqi_cwmin; ++ else ++ qi.tqi_cwmin = 4*qi_be.tqi_cwmin; ++--- a/drivers/net/wireless/ath/ath9k/dynack.c +++++ b/drivers/net/wireless/ath/ath9k/dynack.c ++@@ -280,7 +280,7 @@ EXPORT_SYMBOL(ath_dynack_sample_ack_ts); ++ void ath_dynack_node_init(struct ath_hw *ah, struct ath_node *an) ++ { ++ /* ackto = slottime + sifs + air delay */ ++- u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64; +++ u32 ackto = 9 + 16 + 64; ++ struct ath_dynack *da = &ah->dynack; ++ ++ an->ackto = ackto; ++@@ -315,7 +315,7 @@ EXPORT_SYMBOL(ath_dynack_node_deinit); ++ void ath_dynack_reset(struct ath_hw *ah) ++ { ++ /* ackto = slottime + sifs + air delay */ ++- u32 ackto = ATH9K_SLOT_TIME_9 + 16 + 64; +++ u32 ackto = 9 + 16 + 64; ++ struct ath_dynack *da = &ah->dynack; ++ ++ da->lto = jiffies; ++--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c ++@@ -45,7 +45,7 @@ void ath9k_htc_beaconq_config(struct ath ++ * Long slot time : 2x cwmin ++ * Short slot time : 4x cwmin ++ */ ++- if (ah->slottime == ATH9K_SLOT_TIME_20) +++ if (ah->slottime == 20) ++ qi.tqi_cwmin = 2*qi_be.tqi_cwmin; ++ else ++ qi.tqi_cwmin = 4*qi_be.tqi_cwmin; ++--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c ++@@ -678,7 +678,7 @@ static int ath9k_init_priv(struct ath9k_ ++ ++ for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) ++ priv->beacon.bslot[i] = NULL; ++- priv->beacon.slottime = ATH9K_SLOT_TIME_9; +++ priv->beacon.slottime = 9; ++ ++ ath9k_cmn_init_channels_rates(common); ++ ath9k_cmn_init_crypto(ah); ++--- a/drivers/net/wireless/ath/ath9k/hw.c +++++ b/drivers/net/wireless/ath/ath9k/hw.c ++@@ -454,7 +454,7 @@ static void ath9k_hw_init_defaults(struc ++ if (AR_SREV_9100(ah)) ++ ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; ++ ++- ah->slottime = ATH9K_SLOT_TIME_9; +++ ah->slottime = 9; ++ ah->globaltxtimeout = (u32) -1; ++ ah->power_mode = ATH9K_PM_UNDEFINED; ++ ah->htc_reset_init = true; ++--- a/drivers/net/wireless/ath/ath9k/init.c +++++ b/drivers/net/wireless/ath/ath9k/init.c ++@@ -372,7 +372,7 @@ static void ath9k_init_misc(struct ath_s ++ ++ common->last_rssi = ATH_RSSI_DUMMY_MARKER; ++ memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); ++- sc->beacon.slottime = ATH9K_SLOT_TIME_9; +++ sc->beacon.slottime = 9; ++ ++ for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) ++ sc->beacon.bslot[i] = NULL; ++--- a/drivers/net/wireless/ath/ath9k/mac.h +++++ b/drivers/net/wireless/ath/ath9k/mac.h ++@@ -65,10 +65,6 @@ ++ #define INIT_SSH_RETRY 32 ++ #define INIT_SLG_RETRY 32 ++ ++-#define ATH9K_SLOT_TIME_6 6 ++-#define ATH9K_SLOT_TIME_9 9 ++-#define ATH9K_SLOT_TIME_20 20 ++- ++ #define ATH9K_TXERR_XRETRY 0x01 ++ #define ATH9K_TXERR_FILT 0x02 ++ #define ATH9K_TXERR_FIFO 0x04 ++--- a/drivers/net/wireless/ath/ath9k/main.c +++++ b/drivers/net/wireless/ath/ath9k/main.c ++@@ -926,7 +926,7 @@ static void ath9k_vif_iter(struct ath9k_ ++ } ++ ++ if (!vif->bss_conf.use_short_slot) ++- iter_data->slottime = ATH9K_SLOT_TIME_20; +++ iter_data->slottime = 20; ++ ++ switch (vif->type) { ++ case NL80211_IFTYPE_AP: ++@@ -999,7 +999,7 @@ void ath9k_calculate_iter_data(struct at ++ */ ++ memset(iter_data, 0, sizeof(*iter_data)); ++ eth_broadcast_addr(iter_data->mask); ++- iter_data->slottime = ATH9K_SLOT_TIME_9; +++ iter_data->slottime = 9; ++ ++ list_for_each_entry(avp, &ctx->vifs, list) ++ ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif); ++@@ -1061,7 +1061,7 @@ static void ath9k_set_offchannel_state(s ++ ah->opmode = vif->type; ++ ah->imask &= ~ATH9K_INT_SWBA; ++ ah->imask &= ~ATH9K_INT_TSFOOR; ++- ah->slottime = ATH9K_SLOT_TIME_9; +++ ah->slottime = 9; ++ ++ ath_hw_setbssidmask(common); ++ ath9k_hw_setopmode(ah); ++@@ -1788,6 +1788,7 @@ static void ath9k_bss_info_changed(struc ++ slottime = 9; ++ else ++ slottime = 20; +++ ++ if (vif->type == NL80211_IFTYPE_AP) { ++ /* ++ * Defer update, so that connected stations can adjust diff --git a/package/kernel/mac80211/patches/316-net-mac80211-agg-rx.c-fix-use-of-uninitialised-value.patch b/package/kernel/mac80211/patches/316-net-mac80211-agg-rx.c-fix-use-of-uninitialised-value.patch deleted file mode 100644 index e78df36..0000000 @@ -3389,6 +3793,556 @@ index e78df36..0000000 - if (!tid_agg_rx) - goto end; - +diff --git a/package/kernel/mac80211/patches/317-ath9k-Fix-beacon-configuration-for-addition-removal-.patch b/package/kernel/mac80211/patches/317-ath9k-Fix-beacon-configuration-for-addition-removal-.patch +new file mode 100644 +index 0000000..360dfbf +--- /dev/null ++++ b/package/kernel/mac80211/patches/317-ath9k-Fix-beacon-configuration-for-addition-removal-.patch +@@ -0,0 +1,544 @@ ++From: Benjamin Berg ++Date: Mon, 4 Jul 2016 14:37:25 +0200 ++Subject: [PATCH] ath9k: Fix beacon configuration for addition/removal of ++ interfaces ++ ++This patch fixes some issues with interface reconfiguration. It could ++for example happen that an AP interface in beacon slot 0 was removed ++leaving an IBSS station in one of the other slots. When this happens ++the driver never sends out the beacon as it only tries to send a beacon ++from slot 0. ++ ++Appart from that the tracking of required changes to the beacon config is ++relatively complicated and prone to errors. ++ ++The approach taken here is to solve reconfiguration issues is to ++reconfigure the beacons when any interface changes. This means that ++the complexity of deciding whether an interface change may modify the ++beacon configuration is gone. It also means that the beacon config will ++be reliably updated when an interface is removed. ++ ++The issue that a single non-AP interface might not be in beacon ++slot 0 and wouldn't be send out is solved by moving it into the ++first slot. The TSF value in hardware is adjusted accordingly so ++that the timestamp of the beacons stay consistent. ++ ++Signed-off-by: Benjamin Berg ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ath9k.h +++++ b/drivers/net/wireless/ath/ath9k/ath9k.h ++@@ -637,6 +637,8 @@ struct ath9k_vif_iter_data { ++ int nwds; /* number of WDS vifs */ ++ int nadhocs; /* number of adhoc vifs */ ++ int nocbs; /* number of OCB vifs */ +++ int nbcnvifs; /* number of beaconing vifs */ +++ struct ieee80211_vif *primary_beacon_vif; ++ struct ieee80211_vif *primary_sta; ++ }; ++ ++@@ -685,10 +687,11 @@ struct ath_beacon { ++ }; ++ ++ void ath9k_beacon_tasklet(unsigned long data); ++-void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, ++- u32 changed); +++void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif, +++ bool beacons); ++ void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif); ++ void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif); +++void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc); ++ void ath9k_set_beacon(struct ath_softc *sc); ++ bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif); ++ void ath9k_csa_update(struct ath_softc *sc); ++--- a/drivers/net/wireless/ath/ath9k/beacon.c +++++ b/drivers/net/wireless/ath/ath9k/beacon.c ++@@ -209,7 +209,6 @@ void ath9k_beacon_assign_slot(struct ath ++ } ++ ++ sc->beacon.bslot[avp->av_bslot] = vif; ++- sc->nbcnvifs++; ++ ++ ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n", ++ avp->av_bslot); ++@@ -220,15 +219,12 @@ void ath9k_beacon_remove_slot(struct ath ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ struct ath_vif *avp = (void *)vif->drv_priv; ++ struct ath_buf *bf = avp->av_bcbuf; ++- struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon; ++ ++ ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n", ++ avp->av_bslot); ++ ++ tasklet_disable(&sc->bcon_tasklet); ++ ++- cur_conf->enable_beacon &= ~BIT(avp->av_bslot); ++- ++ if (bf && bf->bf_mpdu) { ++ struct sk_buff *skb = bf->bf_mpdu; ++ dma_unmap_single(sc->dev, bf->bf_buf_addr, ++@@ -240,12 +236,73 @@ void ath9k_beacon_remove_slot(struct ath ++ ++ avp->av_bcbuf = NULL; ++ sc->beacon.bslot[avp->av_bslot] = NULL; ++- sc->nbcnvifs--; ++ list_add_tail(&bf->list, &sc->beacon.bbuf); ++ ++ tasklet_enable(&sc->bcon_tasklet); ++ } ++ +++void ath9k_beacon_ensure_primary_slot(struct ath_softc *sc) +++{ +++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); +++ struct ieee80211_vif *vif; +++ struct ath_vif *avp; +++ s64 tsfadjust; +++ u32 offset; +++ int first_slot = ATH_BCBUF; +++ int slot; +++ +++ tasklet_disable(&sc->bcon_tasklet); +++ +++ /* Find first taken slot. */ +++ for (slot = 0; slot < ATH_BCBUF; slot++) { +++ if (sc->beacon.bslot[slot]) { +++ first_slot = slot; +++ break; +++ } +++ } +++ if (first_slot == 0) +++ goto out; +++ +++ /* Re-enumarate all slots, moving them forward. */ +++ for (slot = 0; slot < ATH_BCBUF; slot++) { +++ if (slot + first_slot < ATH_BCBUF) { +++ vif = sc->beacon.bslot[slot + first_slot]; +++ sc->beacon.bslot[slot] = vif; +++ +++ if (vif) { +++ avp = (void *)vif->drv_priv; +++ avp->av_bslot = slot; +++ } +++ } else { +++ sc->beacon.bslot[slot] = NULL; +++ } +++ } +++ +++ vif = sc->beacon.bslot[0]; +++ if (WARN_ON(!vif)) +++ goto out; +++ +++ /* Get the tsf_adjust value for the new first slot. */ +++ avp = (void *)vif->drv_priv; +++ tsfadjust = le64_to_cpu(avp->tsf_adjust); +++ +++ ath_dbg(common, CONFIG, +++ "Adjusting global TSF after beacon slot reassignment: %lld\n", +++ (signed long long)tsfadjust); +++ +++ /* Modify TSF as required and update the HW. */ +++ avp->chanctx->tsf_val += tsfadjust; +++ if (sc->cur_chan == avp->chanctx) { +++ offset = ath9k_hw_get_tsf_offset(&avp->chanctx->tsf_ts, NULL); +++ ath9k_hw_settsf64(sc->sc_ah, avp->chanctx->tsf_val + offset); +++ } +++ +++ /* The slots tsf_adjust will be updated by ath9k_beacon_config later. */ +++ +++out: +++ tasklet_enable(&sc->bcon_tasklet); +++} +++ ++ static int ath9k_beacon_choose_slot(struct ath_softc *sc) ++ { ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++@@ -274,26 +331,33 @@ static int ath9k_beacon_choose_slot(stru ++ return slot; ++ } ++ ++-static void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif) +++static void ath9k_set_tsfadjust(struct ath_softc *sc, +++ struct ath_beacon_config *cur_conf) ++ { ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++- struct ath_vif *avp = (void *)vif->drv_priv; ++- struct ath_beacon_config *cur_conf = &avp->chanctx->beacon; ++ s64 tsfadjust; +++ int slot; ++ ++- if (avp->av_bslot == 0) ++- return; +++ for (slot = 0; slot < ATH_BCBUF; slot++) { +++ struct ath_vif *avp; ++ ++- /* tsf_adjust is added to the TSF value. We send out the beacon late, ++- * so need to adjust the TSF starting point to be later in time (i.e. ++- * the theoretical first beacon has a TSF of 0 after correction). ++- */ ++- tsfadjust = cur_conf->beacon_interval * avp->av_bslot; ++- tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF; ++- avp->tsf_adjust = cpu_to_le64(tsfadjust); +++ if (!sc->beacon.bslot[slot]) +++ continue; ++ ++- ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n", ++- (signed long long)tsfadjust, avp->av_bslot); +++ avp = (void *)sc->beacon.bslot[slot]->drv_priv; +++ +++ /* tsf_adjust is added to the TSF value. We send out the +++ * beacon late, so need to adjust the TSF starting point to be +++ * later in time (i.e. the theoretical first beacon has a TSF +++ * of 0 after correction). +++ */ +++ tsfadjust = cur_conf->beacon_interval * avp->av_bslot; +++ tsfadjust = -TU_TO_USEC(tsfadjust) / ATH_BCBUF; +++ avp->tsf_adjust = cpu_to_le64(tsfadjust); +++ +++ ath_dbg(common, CONFIG, "tsfadjust is: %lld for bslot: %d\n", +++ (signed long long)tsfadjust, avp->av_bslot); +++ } ++ } ++ ++ bool ath9k_csa_is_finished(struct ath_softc *sc, struct ieee80211_vif *vif) ++@@ -447,20 +511,28 @@ void ath9k_beacon_tasklet(unsigned long ++ * Both nexttbtt and intval have to be in usecs. ++ */ ++ static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, ++- u32 intval, bool reset_tsf) +++ u32 intval) ++ { ++ struct ath_hw *ah = sc->sc_ah; ++ ++ ath9k_hw_disable_interrupts(ah); ++- if (reset_tsf) ++- ath9k_hw_reset_tsf(ah); ++ ath9k_beaconq_config(sc); ++ ath9k_hw_beaconinit(ah, nexttbtt, intval); +++ ah->imask |= ATH9K_INT_SWBA; ++ sc->beacon.bmisscnt = 0; ++ ath9k_hw_set_interrupts(ah); ++ ath9k_hw_enable_interrupts(ah); ++ } ++ +++static void ath9k_beacon_stop(struct ath_softc *sc) +++{ +++ ath9k_hw_disable_interrupts(sc->sc_ah); +++ sc->sc_ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); +++ sc->beacon.bmisscnt = 0; +++ ath9k_hw_set_interrupts(sc->sc_ah); +++ ath9k_hw_enable_interrupts(sc->sc_ah); +++} +++ ++ /* ++ * For multi-bss ap support beacons are either staggered evenly over N slots or ++ * burst together. For the former arrange for the SWBA to be delivered for each ++@@ -472,7 +544,7 @@ static void ath9k_beacon_config_ap(struc ++ struct ath_hw *ah = sc->sc_ah; ++ ++ ath9k_cmn_beacon_config_ap(ah, conf, ATH_BCBUF); ++- ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, false); +++ ath9k_beacon_init(sc, conf->nexttbtt, conf->intval); ++ } ++ ++ static void ath9k_beacon_config_sta(struct ath_hw *ah, ++@@ -501,7 +573,7 @@ static void ath9k_beacon_config_adhoc(st ++ ++ ath9k_cmn_beacon_config_adhoc(ah, conf); ++ ++- ath9k_beacon_init(sc, conf->nexttbtt, conf->intval, conf->ibss_creator); +++ ath9k_beacon_init(sc, conf->nexttbtt, conf->intval); ++ ++ /* ++ * Set the global 'beacon has been configured' flag for the ++@@ -511,44 +583,6 @@ static void ath9k_beacon_config_adhoc(st ++ set_bit(ATH_OP_BEACONS, &common->op_flags); ++ } ++ ++-static bool ath9k_allow_beacon_config(struct ath_softc *sc, ++- struct ieee80211_vif *vif) ++-{ ++- struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++- struct ath_vif *avp = (void *)vif->drv_priv; ++- ++- if (ath9k_is_chanctx_enabled()) { ++- /* ++- * If the VIF is not present in the current channel context, ++- * then we can't do the usual opmode checks. Allow the ++- * beacon config for the VIF to be updated in this case and ++- * return immediately. ++- */ ++- if (sc->cur_chan != avp->chanctx) ++- return true; ++- } ++- ++- if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { ++- if (vif->type != NL80211_IFTYPE_AP) { ++- ath_dbg(common, CONFIG, ++- "An AP interface is already present !\n"); ++- return false; ++- } ++- } ++- ++- if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { ++- if ((vif->type == NL80211_IFTYPE_STATION) && ++- test_bit(ATH_OP_BEACONS, &common->op_flags) && ++- vif != sc->cur_chan->primary_sta) { ++- ath_dbg(common, CONFIG, ++- "Beacon already configured for a station interface\n"); ++- return false; ++- } ++- } ++- ++- return true; ++-} ++- ++ static void ath9k_cache_beacon_config(struct ath_softc *sc, ++ struct ath_chanctx *ctx, ++ struct ieee80211_bss_conf *bss_conf) ++@@ -584,87 +618,79 @@ static void ath9k_cache_beacon_config(st ++ if (cur_conf->dtim_period == 0) ++ cur_conf->dtim_period = 1; ++ +++ ath9k_set_tsfadjust(sc, cur_conf); ++ } ++ ++-void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, ++- u32 changed) +++void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif, +++ bool beacons) ++ { ++- struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; ++- struct ath_hw *ah = sc->sc_ah; ++- struct ath_common *common = ath9k_hw_common(ah); ++- struct ath_vif *avp = (void *)vif->drv_priv; ++- struct ath_chanctx *ctx = avp->chanctx; +++ struct ath_hw *ah = sc->sc_ah; +++ struct ath_common *common = ath9k_hw_common(ah); +++ struct ath_vif *avp; +++ struct ath_chanctx *ctx; ++ struct ath_beacon_config *cur_conf; ++ unsigned long flags; +++ bool enabled; ++ bool skip_beacon = false; ++ ++- if (!ctx) +++ if (!beacons) { +++ clear_bit(ATH_OP_BEACONS, &common->op_flags); +++ ath9k_beacon_stop(sc); ++ return; +++ } ++ ++- cur_conf = &avp->chanctx->beacon; ++- if (vif->type == NL80211_IFTYPE_AP) ++- ath9k_set_tsfadjust(sc, vif); ++- ++- if (!ath9k_allow_beacon_config(sc, vif)) +++ if (WARN_ON(!main_vif)) ++ return; ++ ++- if (vif->type == NL80211_IFTYPE_STATION) { ++- ath9k_cache_beacon_config(sc, ctx, bss_conf); ++- if (ctx != sc->cur_chan) ++- return; +++ avp = (void *)main_vif->drv_priv; +++ ctx = avp->chanctx; +++ cur_conf = &ctx->beacon; +++ enabled = cur_conf->enable_beacon; +++ cur_conf->enable_beacon = beacons; +++ +++ if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { +++ ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf); ++ ++ ath9k_set_beacon(sc); ++ set_bit(ATH_OP_BEACONS, &common->op_flags); ++ return; ++ } ++ ++- /* ++- * Take care of multiple interfaces when ++- * enabling/disabling SWBA. ++- */ ++- if (changed & BSS_CHANGED_BEACON_ENABLED) { ++- bool enabled = cur_conf->enable_beacon; ++- ++- if (!bss_conf->enable_beacon) { ++- cur_conf->enable_beacon &= ~BIT(avp->av_bslot); ++- } else { ++- cur_conf->enable_beacon |= BIT(avp->av_bslot); ++- if (!enabled) ++- ath9k_cache_beacon_config(sc, ctx, bss_conf); ++- } ++- } ++- ++- if (ctx != sc->cur_chan) ++- return; +++ /* Update the beacon configuration. */ +++ ath9k_cache_beacon_config(sc, ctx, &main_vif->bss_conf); ++ ++ /* ++ * Configure the HW beacon registers only when we have a valid ++ * beacon interval. ++ */ ++ if (cur_conf->beacon_interval) { ++- /* ++- * If we are joining an existing IBSS network, start beaconing ++- * only after a TSF-sync has taken place. Ensure that this ++- * happens by setting the appropriate flags. +++ /* Special case to sync the TSF when joining an existing IBSS. +++ * This is only done if no AP interface is active. +++ * Note that mac80211 always resets the TSF when creating a new +++ * IBSS interface. ++ */ ++- if ((changed & BSS_CHANGED_IBSS) && !bss_conf->ibss_creator && ++- bss_conf->enable_beacon) { +++ if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC && +++ !enabled && beacons && !main_vif->bss_conf.ibss_creator) { ++ spin_lock_irqsave(&sc->sc_pm_lock, flags); ++ sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; ++ spin_unlock_irqrestore(&sc->sc_pm_lock, flags); ++ skip_beacon = true; ++- } else { ++- ath9k_set_beacon(sc); ++ } ++ ++ /* ++ * Do not set the ATH_OP_BEACONS flag for IBSS joiner mode ++ * here, it is done in ath9k_beacon_config_adhoc(). ++ */ ++- if (cur_conf->enable_beacon && !skip_beacon) +++ if (beacons && !skip_beacon) { ++ set_bit(ATH_OP_BEACONS, &common->op_flags); ++- else +++ ath9k_set_beacon(sc); +++ } else { ++ clear_bit(ATH_OP_BEACONS, &common->op_flags); +++ ath9k_beacon_stop(sc); +++ } +++ } else { +++ clear_bit(ATH_OP_BEACONS, &common->op_flags); +++ ath9k_beacon_stop(sc); ++ } ++ } ++ ++--- a/drivers/net/wireless/ath/ath9k/common.h +++++ b/drivers/net/wireless/ath/ath9k/common.h ++@@ -50,6 +50,7 @@ ++ #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) ++ ++ struct ath_beacon_config { +++ struct ieee80211_vif *main_vif; ++ int beacon_interval; ++ u16 dtim_period; ++ u16 bmiss_timeout; ++--- a/drivers/net/wireless/ath/ath9k/main.c +++++ b/drivers/net/wireless/ath/ath9k/main.c ++@@ -910,6 +910,22 @@ static bool ath9k_uses_beacons(int type) ++ } ++ } ++ +++static void ath9k_vif_iter_set_beacon(struct ath9k_vif_iter_data *iter_data, +++ struct ieee80211_vif *vif) +++{ +++ /* Use the first (configured) interface, but prefering AP interfaces. */ +++ if (!iter_data->primary_beacon_vif) { +++ iter_data->primary_beacon_vif = vif; +++ } else { +++ if (iter_data->primary_beacon_vif->type != NL80211_IFTYPE_AP && +++ vif->type == NL80211_IFTYPE_AP) +++ iter_data->primary_beacon_vif = vif; +++ } +++ +++ iter_data->beacons = true; +++ iter_data->nbcnvifs += 1; +++} +++ ++ static void ath9k_vif_iter(struct ath9k_vif_iter_data *iter_data, ++ u8 *mac, struct ieee80211_vif *vif) ++ { ++@@ -931,6 +947,8 @@ static void ath9k_vif_iter(struct ath9k_ ++ switch (vif->type) { ++ case NL80211_IFTYPE_AP: ++ iter_data->naps++; +++ if (vif->bss_conf.enable_beacon) +++ ath9k_vif_iter_set_beacon(iter_data, vif); ++ break; ++ case NL80211_IFTYPE_STATION: ++ iter_data->nstations++; ++@@ -943,12 +961,12 @@ static void ath9k_vif_iter(struct ath9k_ ++ case NL80211_IFTYPE_ADHOC: ++ iter_data->nadhocs++; ++ if (vif->bss_conf.enable_beacon) ++- iter_data->beacons = true; +++ ath9k_vif_iter_set_beacon(iter_data, vif); ++ break; ++ case NL80211_IFTYPE_MESH_POINT: ++ iter_data->nmeshes++; ++ if (vif->bss_conf.enable_beacon) ++- iter_data->beacons = true; +++ ath9k_vif_iter_set_beacon(iter_data, vif); ++ break; ++ case NL80211_IFTYPE_WDS: ++ iter_data->nwds++; ++@@ -1081,7 +1099,6 @@ void ath9k_calculate_summary_state(struc ++ struct ath_hw *ah = sc->sc_ah; ++ struct ath_common *common = ath9k_hw_common(ah); ++ struct ath9k_vif_iter_data iter_data; ++- struct ath_beacon_config *cur_conf; ++ ++ ath_chanctx_check_active(sc, ctx); ++ ++@@ -1103,13 +1120,12 @@ void ath9k_calculate_summary_state(struc ++ ath_hw_setbssidmask(common); ++ ++ if (iter_data.naps > 0) { ++- cur_conf = &ctx->beacon; ++ ath9k_hw_set_tsfadjust(ah, true); ++ ah->opmode = NL80211_IFTYPE_AP; ++- if (cur_conf->enable_beacon) ++- iter_data.beacons = true; ++ } else { ++ ath9k_hw_set_tsfadjust(ah, false); +++ if (iter_data.beacons) +++ ath9k_beacon_ensure_primary_slot(sc); ++ ++ if (iter_data.nmeshes) ++ ah->opmode = NL80211_IFTYPE_MESH_POINT; ++@@ -1134,7 +1150,6 @@ void ath9k_calculate_summary_state(struc ++ ctx->switch_after_beacon = true; ++ } ++ ++- ah->imask &= ~ATH9K_INT_SWBA; ++ if (ah->opmode == NL80211_IFTYPE_STATION) { ++ bool changed = (iter_data.primary_sta != ctx->primary_sta); ++ ++@@ -1151,16 +1166,12 @@ void ath9k_calculate_summary_state(struc ++ if (ath9k_hw_mci_is_enabled(sc->sc_ah)) ++ ath9k_mci_update_wlan_channels(sc, true); ++ } ++- } else if (iter_data.beacons) { ++- ah->imask |= ATH9K_INT_SWBA; ++ } +++ sc->nbcnvifs = iter_data.nbcnvifs; +++ ath9k_beacon_config(sc, iter_data.primary_beacon_vif, +++ iter_data.beacons); ++ ath9k_hw_set_interrupts(ah); ++ ++- if (iter_data.beacons) ++- set_bit(ATH_OP_BEACONS, &common->op_flags); ++- else ++- clear_bit(ATH_OP_BEACONS, &common->op_flags); ++- ++ if (ah->slottime != iter_data.slottime) { ++ ah->slottime = iter_data.slottime; ++ ath9k_hw_init_global_settings(ah); ++@@ -1777,9 +1788,7 @@ static void ath9k_bss_info_changed(struc ++ if ((changed & BSS_CHANGED_BEACON_ENABLED) || ++ (changed & BSS_CHANGED_BEACON_INT) || ++ (changed & BSS_CHANGED_BEACON_INFO)) { ++- ath9k_beacon_config(sc, vif, changed); ++- if (changed & BSS_CHANGED_BEACON_ENABLED) ++- ath9k_calculate_summary_state(sc, avp->chanctx); +++ ath9k_calculate_summary_state(sc, avp->chanctx); ++ } ++ ++ if ((avp->chanctx == sc->cur_chan) && diff --git a/package/kernel/mac80211/patches/317-mac80211-minstrel_ht-fix-out-of-bound-in-minstrel_ht.patch b/package/kernel/mac80211/patches/317-mac80211-minstrel_ht-fix-out-of-bound-in-minstrel_ht.patch deleted file mode 100644 index 5bf53b9..0000000 @@ -3440,6 +4394,120 @@ index 5bf53b9..0000000 - mg->max_group_prob_rate = index; - } - } +diff --git a/package/kernel/mac80211/patches/318-brcmfmac-slightly-simplify-building-interface-combin.patch b/package/kernel/mac80211/patches/318-brcmfmac-slightly-simplify-building-interface-combin.patch +new file mode 100644 +index 0000000..d946ecc +--- /dev/null ++++ b/package/kernel/mac80211/patches/318-brcmfmac-slightly-simplify-building-interface-combin.patch +@@ -0,0 +1,108 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Tue, 7 Jun 2016 21:10:18 +0200 ++Subject: [PATCH] brcmfmac: slightly simplify building interface combinations ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This change reorders some operations in brcmf_setup_ifmodes in hope to ++make it simpler: ++1) It allocates arrays right before filling them. This way it's easier ++ to follow requested array length as it's immediately followed by ++ code filling it. It's easier to check e.g. why we need 4 entries for ++ P2P. Other than that it deduplicates some checks (e.g. for P2P). ++2) It reorders code to first prepare limits and then define a new combo. ++ Previously this was mixed (e.g. we were setting num of channels ++ before preparing limits). ++3) It modifies mbss code to use i variable just like other combos do. ++ ++Signed-off-by: Rafał Miłecki ++Acked-by: Arend van Spriel ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++@@ -6284,29 +6284,15 @@ static int brcmf_setup_ifmodes(struct wi ++ if (!combo) ++ goto err; ++ ++- c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL); ++- if (!c0_limits) ++- goto err; ++- ++- if (p2p) { ++- p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL); ++- if (!p2p_limits) ++- goto err; ++- } ++- ++- if (mbss) { ++- mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL); ++- if (!mbss_limits) ++- goto err; ++- } ++- ++ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | ++ BIT(NL80211_IFTYPE_ADHOC) | ++ BIT(NL80211_IFTYPE_AP); ++ ++ c = 0; ++ i = 0; ++- combo[c].num_different_channels = 1; +++ c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL); +++ if (!c0_limits) +++ goto err; ++ c0_limits[i].max = 1; ++ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); ++ if (p2p) { ++@@ -6324,6 +6310,7 @@ static int brcmf_setup_ifmodes(struct wi ++ c0_limits[i].max = 1; ++ c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); ++ } +++ combo[c].num_different_channels = 1; ++ combo[c].max_interfaces = i; ++ combo[c].n_limits = i; ++ combo[c].limits = c0_limits; ++@@ -6331,7 +6318,9 @@ static int brcmf_setup_ifmodes(struct wi ++ if (p2p) { ++ c++; ++ i = 0; ++- combo[c].num_different_channels = 1; +++ p2p_limits = kcalloc(4, sizeof(*p2p_limits), GFP_KERNEL); +++ if (!p2p_limits) +++ goto err; ++ p2p_limits[i].max = 1; ++ p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION); ++ p2p_limits[i].max = 1; ++@@ -6340,6 +6329,7 @@ static int brcmf_setup_ifmodes(struct wi ++ p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT); ++ p2p_limits[i].max = 1; ++ p2p_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); +++ combo[c].num_different_channels = 1; ++ combo[c].max_interfaces = i; ++ combo[c].n_limits = i; ++ combo[c].limits = p2p_limits; ++@@ -6347,14 +6337,19 @@ static int brcmf_setup_ifmodes(struct wi ++ ++ if (mbss) { ++ c++; +++ i = 0; +++ mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL); +++ if (!mbss_limits) +++ goto err; +++ mbss_limits[i].max = 4; +++ mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP); ++ combo[c].beacon_int_infra_match = true; ++ combo[c].num_different_channels = 1; ++- mbss_limits[0].max = 4; ++- mbss_limits[0].types = BIT(NL80211_IFTYPE_AP); ++ combo[c].max_interfaces = 4; ++- combo[c].n_limits = 1; +++ combo[c].n_limits = i; ++ combo[c].limits = mbss_limits; ++ } +++ ++ wiphy->n_iface_combinations = n_combos; ++ wiphy->iface_combinations = combo; ++ return 0; diff --git a/package/kernel/mac80211/patches/318-mac80211-move-A-MSDU-skb_linearize-call-to-ieee80211.patch b/package/kernel/mac80211/patches/318-mac80211-move-A-MSDU-skb_linearize-call-to-ieee80211.patch deleted file mode 100644 index 655dc4b..0000000 @@ -3481,6 +4549,455 @@ index 655dc4b..0000000 - if (has_80211_header) { - err = ieee80211_data_to_8023(skb, addr, iftype); - if (err) +diff --git a/package/kernel/mac80211/patches/319-0001-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch b/package/kernel/mac80211/patches/319-0001-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch +new file mode 100644 +index 0000000..073d012 +--- /dev/null ++++ b/package/kernel/mac80211/patches/319-0001-brcmfmac-fix-lockup-when-removing-P2P-interface-afte.patch +@@ -0,0 +1,154 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Fri, 17 Jun 2016 12:29:21 +0200 ++Subject: [PATCH] brcmfmac: fix lockup when removing P2P interface after ++ event timeout ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Removing P2P interface is handled by sending a proper request to the ++firmware. On success firmware triggers an event and driver's handler ++removes a matching interface. ++ ++However on event timeout we remove interface directly from the cfg80211 ++callback. Current code doesn't handle this case correctly as it always ++assumes rtnl to be unlocked. ++ ++Fix it by adding an extra rtnl_locked parameter to functions and calling ++unregister_netdevice when needed. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++@@ -548,12 +548,16 @@ fail: ++ return -EBADE; ++ } ++ ++-static void brcmf_net_detach(struct net_device *ndev) +++static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) ++ { ++- if (ndev->reg_state == NETREG_REGISTERED) ++- unregister_netdev(ndev); ++- else +++ if (ndev->reg_state == NETREG_REGISTERED) { +++ if (rtnl_locked) +++ unregister_netdevice(ndev); +++ else +++ unregister_netdev(ndev); +++ } else { ++ brcmf_cfg80211_free_netdev(ndev); +++ } ++ } ++ ++ void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on) ++@@ -651,7 +655,7 @@ struct brcmf_if *brcmf_add_if(struct brc ++ brcmf_err("ERROR: netdev:%s already exists\n", ++ ifp->ndev->name); ++ netif_stop_queue(ifp->ndev); ++- brcmf_net_detach(ifp->ndev); +++ brcmf_net_detach(ifp->ndev, false); ++ drvr->iflist[bsscfgidx] = NULL; ++ } else { ++ brcmf_dbg(INFO, "netdev:%s ignore IF event\n", ++@@ -699,7 +703,8 @@ struct brcmf_if *brcmf_add_if(struct brc ++ return ifp; ++ } ++ ++-static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx) +++static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx, +++ bool rtnl_locked) ++ { ++ struct brcmf_if *ifp; ++ ++@@ -729,7 +734,7 @@ static void brcmf_del_if(struct brcmf_pu ++ cancel_work_sync(&ifp->multicast_work); ++ cancel_work_sync(&ifp->ndoffload_work); ++ } ++- brcmf_net_detach(ifp->ndev); +++ brcmf_net_detach(ifp->ndev, rtnl_locked); ++ } else { ++ /* Only p2p device interfaces which get dynamically created ++ * end up here. In this case the p2p module should be informed ++@@ -743,14 +748,14 @@ static void brcmf_del_if(struct brcmf_pu ++ } ++ } ++ ++-void brcmf_remove_interface(struct brcmf_if *ifp) +++void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked) ++ { ++ if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp)) ++ return; ++ brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", ifp->bsscfgidx, ++ ifp->ifidx); ++ brcmf_fws_del_interface(ifp); ++- brcmf_del_if(ifp->drvr, ifp->bsscfgidx); +++ brcmf_del_if(ifp->drvr, ifp->bsscfgidx, rtnl_locked); ++ } ++ ++ #ifdef CONFIG_INET ++@@ -1057,9 +1062,9 @@ fail: ++ brcmf_fws_deinit(drvr); ++ } ++ if (ifp) ++- brcmf_net_detach(ifp->ndev); +++ brcmf_net_detach(ifp->ndev, false); ++ if (p2p_ifp) ++- brcmf_net_detach(p2p_ifp->ndev); +++ brcmf_net_detach(p2p_ifp->ndev, false); ++ drvr->iflist[0] = NULL; ++ drvr->iflist[1] = NULL; ++ if (drvr->settings->ignore_probe_fail) ++@@ -1128,7 +1133,7 @@ void brcmf_detach(struct device *dev) ++ ++ /* make sure primary interface removed last */ ++ for (i = BRCMF_MAX_IFS-1; i > -1; i--) ++- brcmf_remove_interface(drvr->iflist[i]); +++ brcmf_remove_interface(drvr->iflist[i], false); ++ ++ brcmf_cfg80211_detach(drvr->config); ++ ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++@@ -216,7 +216,7 @@ struct brcmf_if *brcmf_get_ifp(struct br ++ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); ++ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx, ++ bool is_p2pdev, char *name, u8 *mac_addr); ++-void brcmf_remove_interface(struct brcmf_if *ifp); +++void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked); ++ void brcmf_txflowblock_if(struct brcmf_if *ifp, ++ enum brcmf_netif_stop_reason reason, bool state); ++ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c ++@@ -183,7 +183,7 @@ static void brcmf_fweh_handle_if_event(s ++ err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); ++ ++ if (ifp && ifevent->action == BRCMF_E_IF_DEL) ++- brcmf_remove_interface(ifp); +++ brcmf_remove_interface(ifp, false); ++ } ++ ++ /** ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c ++@@ -2289,7 +2289,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph ++ err = 0; ++ } ++ if (err) ++- brcmf_remove_interface(vif->ifp); +++ brcmf_remove_interface(vif->ifp, true); ++ ++ brcmf_cfg80211_arm_vif_event(cfg, NULL); ++ if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) ++@@ -2395,7 +2395,7 @@ void brcmf_p2p_detach(struct brcmf_p2p_i ++ if (vif != NULL) { ++ brcmf_p2p_cancel_remain_on_channel(vif->ifp); ++ brcmf_p2p_deinit_discovery(p2p); ++- brcmf_remove_interface(vif->ifp); +++ brcmf_remove_interface(vif->ifp, false); ++ } ++ /* just set it all to zero */ ++ memset(p2p, 0, sizeof(*p2p)); +diff --git a/package/kernel/mac80211/patches/319-0002-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch b/package/kernel/mac80211/patches/319-0002-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch +new file mode 100644 +index 0000000..6d3f3c6 +--- /dev/null ++++ b/package/kernel/mac80211/patches/319-0002-brcmfmac-use-const-char-for-interface-name-in-brcmf_.patch +@@ -0,0 +1,40 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Fri, 17 Jun 2016 12:48:44 +0200 ++Subject: [PATCH] brcmfmac: use const char * for interface name in ++ brcmf_add_if ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This function can work just fine with const pointer, it only calls ++alloc_netdev which take const as well. Moreover it makes this function ++more flexible as some cfg80211 callback may provide const char * as ++well, e.g. add_virtual_intf. This will be needed for more advanced ++interface management. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++@@ -638,7 +638,7 @@ fail: ++ } ++ ++ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx, ++- bool is_p2pdev, char *name, u8 *mac_addr) +++ bool is_p2pdev, const char *name, u8 *mac_addr) ++ { ++ struct brcmf_if *ifp; ++ struct net_device *ndev; ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++@@ -215,7 +215,7 @@ char *brcmf_ifname(struct brcmf_if *ifp) ++ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx); ++ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); ++ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx, ++- bool is_p2pdev, char *name, u8 *mac_addr); +++ bool is_p2pdev, const char *name, u8 *mac_addr); ++ void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked); ++ void brcmf_txflowblock_if(struct brcmf_if *ifp, ++ enum brcmf_netif_stop_reason reason, bool state); +diff --git a/package/kernel/mac80211/patches/319-0003-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch b/package/kernel/mac80211/patches/319-0003-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch +new file mode 100644 +index 0000000..eeda766 +--- /dev/null ++++ b/package/kernel/mac80211/patches/319-0003-brcmfmac-include-also-core.h-header-in-cfg80211.h.patch +@@ -0,0 +1,33 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Sat, 18 Jun 2016 18:49:38 +0200 ++Subject: [PATCH] brcmfmac: include also core.h header in cfg80211.h ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This header provides two inline functions using struct brcmf_if so we ++need core.h to avoid: ++ ++drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h: In function ‘ndev_to_prof’: ++drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:368:13: error: dereferencing pointer to incomplete type ++ return &ifp->vif->profile; ++ ^ ++drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h: In function ‘ndev_to_vif’: ++drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h:374:12: error: dereferencing pointer to incomplete type ++ return ifp->vif; ++ ^ ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h ++@@ -20,6 +20,7 @@ ++ /* for brcmu_d11inf */ ++ #include ++ +++#include "core.h" ++ #include "fwil_types.h" ++ #include "p2p.h" ++ +diff --git a/package/kernel/mac80211/patches/319-0004-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch b/package/kernel/mac80211/patches/319-0004-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch +new file mode 100644 +index 0000000..3819248 +--- /dev/null ++++ b/package/kernel/mac80211/patches/319-0004-brcmfmac-add-missing-break-when-deleting-P2P_DEVICE.patch +@@ -0,0 +1,27 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Sun, 19 Jun 2016 01:55:57 +0200 ++Subject: [PATCH] brcmfmac: add missing break when deleting P2P_DEVICE ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++We obviously don't want to fall through in that switch. With this change ++1) We wait for event (triggered by p2p_disc) as expected ++2) We remove interface manually on timeout ++3) We return 0 on success instead of -ENOTSUPP ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c ++@@ -2263,6 +2263,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiph ++ return 0; ++ brcmf_p2p_cancel_remain_on_channel(vif->ifp); ++ brcmf_p2p_deinit_discovery(p2p); +++ break; +++ ++ default: ++ return -ENOTSUPP; ++ } +diff --git a/package/kernel/mac80211/patches/319-0005-brcmfmac-delete-interface-directly-in-code-that-sent.patch b/package/kernel/mac80211/patches/319-0005-brcmfmac-delete-interface-directly-in-code-that-sent.patch +new file mode 100644 +index 0000000..12d7eb4 +--- /dev/null ++++ b/package/kernel/mac80211/patches/319-0005-brcmfmac-delete-interface-directly-in-code-that-sent.patch +@@ -0,0 +1,75 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Wed, 29 Jun 2016 21:54:26 +0200 ++Subject: [PATCH] brcmfmac: delete interface directly in code that sent fw ++ request ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++So far when receiving event about in-firmware-interface removal our ++event worker was notifying listener and afterwards it was removing Linux ++interface. ++ ++First of all it was resulting in slightly unexpected order. The listener ++(del_virtual_intf callback) was (usually) returning with success before ++we even called unregister_netdev(ice). ++ ++Please note this couldn't be simply fixed by changing order of calls in ++brcmf_fweh_handle_if_event as unregistering interface earlier could free ++struct brcmf_if. ++ ++Another problem of current implementation are possible lockups. Focus on ++the time slot between calling event handler and removing Linux ++interface. During that time original caller may leave (unlocking rtnl ++semaphore) *and* another call to the same code may be done (locking it ++again). If that happens our event handler will stuck at removing Linux ++interface, it won't handle another event and will block process holding ++rtnl lock. ++ ++This can be simply solved by unregistering interface in a proper ++callback, right after receiving confirmation event from firmware. This ++only required modifying worker to don't unregister on its own if there ++is someone waiting for the event. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c ++@@ -18,6 +18,7 @@ ++ #include "brcmu_wifi.h" ++ #include "brcmu_utils.h" ++ +++#include "cfg80211.h" ++ #include "core.h" ++ #include "debug.h" ++ #include "tracepoint.h" ++@@ -182,8 +183,13 @@ static void brcmf_fweh_handle_if_event(s ++ ++ err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); ++ ++- if (ifp && ifevent->action == BRCMF_E_IF_DEL) ++- brcmf_remove_interface(ifp, false); +++ if (ifp && ifevent->action == BRCMF_E_IF_DEL) { +++ bool armed = brcmf_cfg80211_vif_event_armed(drvr->config); +++ +++ /* Default handling in case no-one waits for this event */ +++ if (!armed) +++ brcmf_remove_interface(ifp, false); +++ } ++ } ++ ++ /** ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c ++@@ -2290,8 +2290,7 @@ int brcmf_p2p_del_vif(struct wiphy *wiph ++ else ++ err = 0; ++ } ++- if (err) ++- brcmf_remove_interface(vif->ifp, true); +++ brcmf_remove_interface(vif->ifp, true); ++ ++ brcmf_cfg80211_arm_vif_event(cfg, NULL); ++ if (vif->wdev.iftype != NL80211_IFTYPE_P2P_DEVICE) +diff --git a/package/kernel/mac80211/patches/319-0006-brcmfmac-support-removing-AP-interfaces-with-interfa.patch b/package/kernel/mac80211/patches/319-0006-brcmfmac-support-removing-AP-interfaces-with-interfa.patch +new file mode 100644 +index 0000000..2f7165e +--- /dev/null ++++ b/package/kernel/mac80211/patches/319-0006-brcmfmac-support-removing-AP-interfaces-with-interfa.patch +@@ -0,0 +1,84 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Wed, 29 Jun 2016 21:54:27 +0200 ++Subject: [PATCH] brcmfmac: support removing AP interfaces with ++ "interface_remove" ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++New firmwares (e.g. 10.10.69.36 for BCM4366) support "interface_remove" ++for removing interfaces. Try to use this method on cfg80211 request. In ++case of older firmwares (e.g. 7.35.177.56 for BCM43602 as I tested) this ++will just result in firmware rejecting command and this won't change any ++behavior. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++@@ -785,12 +785,48 @@ s32 brcmf_notify_escan_complete(struct b ++ return err; ++ } ++ +++static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy, +++ struct wireless_dev *wdev) +++{ +++ struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); +++ struct net_device *ndev = wdev->netdev; +++ struct brcmf_if *ifp = netdev_priv(ndev); +++ int ret; +++ int err; +++ +++ brcmf_cfg80211_arm_vif_event(cfg, ifp->vif); +++ +++ err = brcmf_fil_bsscfg_data_set(ifp, "interface_remove", NULL, 0); +++ if (err) { +++ brcmf_err("interface_remove failed %d\n", err); +++ goto err_unarm; +++ } +++ +++ /* wait for firmware event */ +++ ret = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL, +++ BRCMF_VIF_EVENT_TIMEOUT); +++ if (!ret) { +++ brcmf_err("timeout occurred\n"); +++ err = -EIO; +++ goto err_unarm; +++ } +++ +++ brcmf_remove_interface(ifp, true); +++ +++err_unarm: +++ brcmf_cfg80211_arm_vif_event(cfg, NULL); +++ return err; +++} +++ ++ static ++ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) ++ { ++ struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); ++ struct net_device *ndev = wdev->netdev; ++ +++ if (ndev && ndev == cfg_to_ndev(cfg)) +++ return -ENOTSUPP; +++ ++ /* vif event pending in firmware */ ++ if (brcmf_cfg80211_vif_event_armed(cfg)) ++ return -EBUSY; ++@@ -807,12 +843,13 @@ int brcmf_cfg80211_del_iface(struct wiph ++ switch (wdev->iftype) { ++ case NL80211_IFTYPE_ADHOC: ++ case NL80211_IFTYPE_STATION: ++- case NL80211_IFTYPE_AP: ++ case NL80211_IFTYPE_AP_VLAN: ++ case NL80211_IFTYPE_WDS: ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_MESH_POINT: ++ return -EOPNOTSUPP; +++ case NL80211_IFTYPE_AP: +++ return brcmf_cfg80211_del_ap_iface(wiphy, wdev); ++ case NL80211_IFTYPE_P2P_CLIENT: ++ case NL80211_IFTYPE_P2P_GO: ++ case NL80211_IFTYPE_P2P_DEVICE: diff --git a/package/kernel/mac80211/patches/319-cfg80211-add-function-for-802.3-conversion-with-sepa.patch b/package/kernel/mac80211/patches/319-cfg80211-add-function-for-802.3-conversion-with-sepa.patch deleted file mode 100644 index b646ab3..0000000 @@ -3673,6 +5190,883 @@ index b646ab3..0000000 - EXPORT_SYMBOL(ieee80211_data_to_8023); - - int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, +diff --git a/package/kernel/mac80211/patches/320-ath9k-Switch-to-using-mac80211-intermediate-software.patch b/package/kernel/mac80211/patches/320-ath9k-Switch-to-using-mac80211-intermediate-software.patch +new file mode 100644 +index 0000000..f8b8f86 +--- /dev/null ++++ b/package/kernel/mac80211/patches/320-ath9k-Switch-to-using-mac80211-intermediate-software.patch +@@ -0,0 +1,871 @@ ++From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= ++Date: Wed, 6 Jul 2016 21:34:17 +0200 ++Subject: [PATCH] ath9k: Switch to using mac80211 intermediate software queues. ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This switches ath9k over to using the mac80211 intermediate software ++queueing mechanism for data packets. It removes the queueing inside the ++driver, except for the retry queue, and instead pulls from mac80211 when ++a packet is needed. The retry queue is used to store a packet that was ++pulled but can't be sent immediately. ++ ++The old code path in ath_tx_start that would queue packets has been ++removed completely, as has the qlen limit tunables (since there's no ++longer a queue in the driver to limit). ++ ++Based on Tim's original patch set, but reworked quite thoroughly. ++ ++Cc: Tim Shepard ++Cc: Felix Fietkau ++Signed-off-by: Toke Høiland-Jørgensen ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ath9k.h +++++ b/drivers/net/wireless/ath/ath9k/ath9k.h ++@@ -91,7 +91,6 @@ int ath_descdma_setup(struct ath_softc * ++ #define ATH_RXBUF 512 ++ #define ATH_TXBUF 512 ++ #define ATH_TXBUF_RESERVE 5 ++-#define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) ++ #define ATH_TXMAXTRY 13 ++ #define ATH_MAX_SW_RETRIES 30 ++ ++@@ -145,7 +144,9 @@ int ath_descdma_setup(struct ath_softc * ++ #define BAW_WITHIN(_start, _bawsz, _seqno) \ ++ ((((_seqno) - (_start)) & 4095) < (_bawsz)) ++ ++-#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) +++#define ATH_STA_2_TID(_sta, _tidno) ((struct ath_atx_tid *)(_sta)->txq[_tidno]->drv_priv) +++#define ATH_VIF_2_TID(_vif) ((struct ath_atx_tid *)(_vif)->txq->drv_priv) +++#define ATH_AN_2_TID(_an, _tidno) ((_an)->sta ? ATH_STA_2_TID((_an)->sta, _tidno) : ATH_VIF_2_TID((_an)->vif)) ++ ++ #define IS_HT_RATE(rate) (rate & 0x80) ++ #define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e)) ++@@ -164,7 +165,6 @@ struct ath_txq { ++ spinlock_t axq_lock; ++ u32 axq_depth; ++ u32 axq_ampdu_depth; ++- bool stopped; ++ bool axq_tx_inprogress; ++ struct list_head txq_fifo[ATH_TXFIFO_DEPTH]; ++ u8 txq_headidx; ++@@ -232,7 +232,6 @@ 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_txq *txq; ++@@ -247,13 +246,13 @@ struct ath_atx_tid { ++ s8 bar_index; ++ bool active; ++ bool clear_ps_filter; +++ bool has_queued; ++ }; ++ ++ struct ath_node { ++ struct ath_softc *sc; ++ struct ieee80211_sta *sta; /* station struct we're part of */ ++ struct ieee80211_vif *vif; /* interface with which we're associated */ ++- struct ath_atx_tid tid[IEEE80211_NUM_TIDS]; ++ ++ u16 maxampdu; ++ u8 mpdudensity; ++@@ -276,7 +275,6 @@ struct ath_tx_control { ++ struct ath_node *an; ++ struct ieee80211_sta *sta; ++ u8 paprd; ++- bool force_channel; ++ }; ++ ++ ++@@ -293,7 +291,6 @@ struct ath_tx { ++ struct ath_descdma txdma; ++ struct ath_txq *txq_map[IEEE80211_NUM_ACS]; ++ struct ath_txq *uapsdq; ++- u32 txq_max_pending[IEEE80211_NUM_ACS]; ++ u16 max_aggr_framelen[IEEE80211_NUM_ACS][4][32]; ++ }; ++ ++@@ -585,6 +582,7 @@ void ath9k_release_buffered_frames(struc ++ u16 tids, int nframes, ++ enum ieee80211_frame_release_type reason, ++ bool more_data); +++void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue); ++ ++ /********/ ++ /* VIFs */ ++--- a/drivers/net/wireless/ath/ath9k/channel.c +++++ b/drivers/net/wireless/ath/ath9k/channel.c ++@@ -1007,7 +1007,6 @@ static void ath_scan_send_probe(struct a ++ goto error; ++ ++ txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; ++- txctl.force_channel = true; ++ if (ath_tx_start(sc->hw, skb, &txctl)) ++ goto error; ++ ++@@ -1130,7 +1129,6 @@ ath_chanctx_send_vif_ps_frame(struct ath ++ memset(&txctl, 0, sizeof(txctl)); ++ txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; ++ txctl.sta = sta; ++- txctl.force_channel = true; ++ if (ath_tx_start(sc->hw, skb, &txctl)) { ++ ieee80211_free_txskb(sc->hw, skb); ++ return false; ++--- a/drivers/net/wireless/ath/ath9k/debug.c +++++ b/drivers/net/wireless/ath/ath9k/debug.c ++@@ -600,7 +600,6 @@ static int read_file_xmit(struct seq_fil ++ PR("MPDUs XRetried: ", xretries); ++ PR("Aggregates: ", a_aggr); ++ PR("AMPDUs Queued HW:", a_queued_hw); ++- PR("AMPDUs Queued SW:", a_queued_sw); ++ PR("AMPDUs Completed:", a_completed); ++ PR("AMPDUs Retried: ", a_retries); ++ PR("AMPDUs XRetried: ", a_xretries); ++@@ -629,8 +628,7 @@ static void print_queue(struct ath_softc ++ seq_printf(file, "%s: %d ", "qnum", txq->axq_qnum); ++ seq_printf(file, "%s: %2d ", "qdepth", txq->axq_depth); ++ seq_printf(file, "%s: %2d ", "ampdu-depth", txq->axq_ampdu_depth); ++- seq_printf(file, "%s: %3d ", "pending", txq->pending_frames); ++- seq_printf(file, "%s: %d\n", "stopped", txq->stopped); +++ seq_printf(file, "%s: %3d\n", "pending", txq->pending_frames); ++ ++ ath_txq_unlock(sc, txq); ++ } ++@@ -1208,7 +1206,6 @@ static const char ath9k_gstrings_stats[] ++ AMKSTR(d_tx_mpdu_xretries), ++ AMKSTR(d_tx_aggregates), ++ AMKSTR(d_tx_ampdus_queued_hw), ++- AMKSTR(d_tx_ampdus_queued_sw), ++ AMKSTR(d_tx_ampdus_completed), ++ AMKSTR(d_tx_ampdu_retries), ++ AMKSTR(d_tx_ampdu_xretries), ++@@ -1288,7 +1285,6 @@ void ath9k_get_et_stats(struct ieee80211 ++ AWDATA(xretries); ++ AWDATA(a_aggr); ++ AWDATA(a_queued_hw); ++- AWDATA(a_queued_sw); ++ AWDATA(a_completed); ++ AWDATA(a_retries); ++ AWDATA(a_xretries); ++@@ -1346,14 +1342,6 @@ int ath9k_init_debug(struct ath_hw *ah) ++ read_file_xmit); ++ debugfs_create_devm_seqfile(sc->dev, "queues", sc->debug.debugfs_phy, ++ read_file_queues); ++- debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++- &sc->tx.txq_max_pending[IEEE80211_AC_BK]); ++- debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++- &sc->tx.txq_max_pending[IEEE80211_AC_BE]); ++- debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++- &sc->tx.txq_max_pending[IEEE80211_AC_VI]); ++- debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, ++- &sc->tx.txq_max_pending[IEEE80211_AC_VO]); ++ debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy, ++ read_file_misc); ++ debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy, ++--- a/drivers/net/wireless/ath/ath9k/debug.h +++++ b/drivers/net/wireless/ath/ath9k/debug.h ++@@ -147,7 +147,6 @@ struct ath_interrupt_stats { ++ * @completed: Total MPDUs (non-aggr) completed ++ * @a_aggr: Total no. of aggregates queued ++ * @a_queued_hw: Total AMPDUs queued to hardware ++- * @a_queued_sw: Total AMPDUs queued to software queues ++ * @a_completed: Total AMPDUs completed ++ * @a_retries: No. of AMPDUs retried (SW) ++ * @a_xretries: No. of AMPDUs dropped due to xretries ++@@ -174,7 +173,6 @@ struct ath_tx_stats { ++ u32 xretries; ++ u32 a_aggr; ++ u32 a_queued_hw; ++- u32 a_queued_sw; ++ u32 a_completed; ++ u32 a_retries; ++ u32 a_xretries; ++--- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++++ b/drivers/net/wireless/ath/ath9k/debug_sta.c ++@@ -52,8 +52,8 @@ static ssize_t read_file_node_aggr(struc ++ "TID", "SEQ_START", "SEQ_NEXT", "BAW_SIZE", ++ "BAW_HEAD", "BAW_TAIL", "BAR_IDX", "SCHED", "PAUSED"); ++ ++- for (tidno = 0, tid = &an->tid[tidno]; ++- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { +++ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { +++ tid = ATH_STA_2_TID(an->sta, tidno); ++ txq = tid->txq; ++ ath_txq_lock(sc, txq); ++ if (tid->active) { ++--- a/drivers/net/wireless/ath/ath9k/init.c +++++ b/drivers/net/wireless/ath/ath9k/init.c ++@@ -358,7 +358,6 @@ static int ath9k_init_queues(struct ath_ ++ for (i = 0; i < IEEE80211_NUM_ACS; i++) { ++ sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i); ++ sc->tx.txq_map[i]->mac80211_qnum = i; ++- sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH; ++ } ++ return 0; ++ } ++@@ -873,6 +872,7 @@ static void ath9k_set_hw_capab(struct at ++ hw->max_rate_tries = 10; ++ hw->sta_data_size = sizeof(struct ath_node); ++ hw->vif_data_size = sizeof(struct ath_vif); +++ hw->txq_data_size = sizeof(struct ath_atx_tid); ++ hw->extra_tx_headroom = 4; ++ ++ hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1; ++--- a/drivers/net/wireless/ath/ath9k/main.c +++++ b/drivers/net/wireless/ath/ath9k/main.c ++@@ -2695,4 +2695,5 @@ struct ieee80211_ops ath9k_ops = { ++ .sw_scan_start = ath9k_sw_scan_start, ++ .sw_scan_complete = ath9k_sw_scan_complete, ++ .get_txpower = ath9k_get_txpower, +++ .wake_tx_queue = ath9k_wake_tx_queue, ++ }; ++--- a/drivers/net/wireless/ath/ath9k/xmit.c +++++ b/drivers/net/wireless/ath/ath9k/xmit.c ++@@ -65,6 +65,8 @@ static struct ath_buf *ath_tx_setup_buff ++ struct ath_txq *txq, ++ struct ath_atx_tid *tid, ++ struct sk_buff *skb); +++static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, +++ struct ath_tx_control *txctl); ++ ++ enum { ++ MCS_HT20, ++@@ -118,6 +120,26 @@ static void ath_tx_queue_tid(struct ath_ ++ list_add_tail(&tid->list, list); ++ } ++ +++void ath9k_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_txq *queue) +++{ +++ struct ath_softc *sc = hw->priv; +++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); +++ struct ath_atx_tid *tid = (struct ath_atx_tid *) queue->drv_priv; +++ struct ath_txq *txq = tid->txq; +++ +++ ath_dbg(common, QUEUE, "Waking TX queue: %pM (%d)\n", +++ queue->sta ? queue->sta->addr : queue->vif->addr, +++ tid->tidno); +++ +++ ath_txq_lock(sc, txq); +++ +++ tid->has_queued = true; +++ ath_tx_queue_tid(sc, txq, tid); +++ ath_txq_schedule(sc, txq); +++ +++ ath_txq_unlock(sc, txq); +++} +++ ++ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) ++ { ++ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); ++@@ -160,7 +182,6 @@ static void ath_set_rates(struct ieee802 ++ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, ++ struct sk_buff *skb) ++ { ++- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); ++ struct ath_frame_info *fi = get_frame_info(skb); ++ int q = fi->txq; ++ ++@@ -171,14 +192,6 @@ static void ath_txq_skb_done(struct ath_ ++ if (WARN_ON(--txq->pending_frames < 0)) ++ txq->pending_frames = 0; ++ ++- if (txq->stopped && ++- txq->pending_frames < sc->tx.txq_max_pending[q]) { ++- if (ath9k_is_chanctx_enabled()) ++- ieee80211_wake_queue(sc->hw, info->hw_queue); ++- else ++- ieee80211_wake_queue(sc->hw, q); ++- txq->stopped = false; ++- } ++ } ++ ++ static struct ath_atx_tid * ++@@ -188,9 +201,47 @@ ath_get_skb_tid(struct ath_softc *sc, st ++ return ATH_AN_2_TID(an, tidno); ++ } ++ +++static struct sk_buff * +++ath_tid_pull(struct ath_atx_tid *tid) +++{ +++ struct ath_softc *sc = tid->an->sc; +++ struct ieee80211_hw *hw = sc->hw; +++ struct ath_tx_control txctl = { +++ .txq = tid->txq, +++ .sta = tid->an->sta, +++ }; +++ struct sk_buff *skb; +++ struct ath_frame_info *fi; +++ int q; +++ +++ if (!tid->has_queued) +++ return NULL; +++ +++ skb = ieee80211_tx_dequeue(hw, container_of((void*)tid, struct ieee80211_txq, drv_priv)); +++ if (!skb) { +++ tid->has_queued = false; +++ return NULL; +++ } +++ +++ if (ath_tx_prepare(hw, skb, &txctl)) { +++ ieee80211_free_txskb(hw, skb); +++ return NULL; +++ } +++ +++ q = skb_get_queue_mapping(skb); +++ if (tid->txq == sc->tx.txq_map[q]) { +++ fi = get_frame_info(skb); +++ fi->txq = q; +++ ++tid->txq->pending_frames; +++ } +++ +++ return skb; +++ } +++ +++ ++ static bool ath_tid_has_buffered(struct ath_atx_tid *tid) ++ { ++- return !skb_queue_empty(&tid->buf_q) || !skb_queue_empty(&tid->retry_q); +++ return !skb_queue_empty(&tid->retry_q) || tid->has_queued; ++ } ++ ++ static struct sk_buff *ath_tid_dequeue(struct ath_atx_tid *tid) ++@@ -199,46 +250,11 @@ static struct sk_buff *ath_tid_dequeue(s ++ ++ skb = __skb_dequeue(&tid->retry_q); ++ if (!skb) ++- skb = __skb_dequeue(&tid->buf_q); +++ skb = ath_tid_pull(tid); ++ ++ return skb; ++ } ++ ++-/* ++- * ath_tx_tid_change_state: ++- * - clears a-mpdu flag of previous session ++- * - force sequence number allocation to fix next BlockAck Window ++- */ ++-static void ++-ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid) ++-{ ++- struct ath_txq *txq = tid->txq; ++- struct ieee80211_tx_info *tx_info; ++- struct sk_buff *skb, *tskb; ++- struct ath_buf *bf; ++- struct ath_frame_info *fi; ++- ++- skb_queue_walk_safe(&tid->buf_q, skb, tskb) { ++- fi = get_frame_info(skb); ++- bf = fi->bf; ++- ++- tx_info = IEEE80211_SKB_CB(skb); ++- tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU; ++- ++- if (bf) ++- continue; ++- ++- bf = ath_tx_setup_buffer(sc, txq, tid, skb); ++- if (!bf) { ++- __skb_unlink(skb, &tid->buf_q); ++- ath_txq_skb_done(sc, txq, skb); ++- ieee80211_free_txskb(sc->hw, skb); ++- continue; ++- } ++- } ++- ++-} ++- ++ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) ++ { ++ struct ath_txq *txq = tid->txq; ++@@ -873,20 +889,16 @@ 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 sk_buff_head **q) +++ struct ath_atx_tid *tid) ++ { ++ struct ieee80211_tx_info *tx_info; ++ struct ath_frame_info *fi; ++- struct sk_buff *skb; +++ struct sk_buff *skb, *first_skb = NULL; ++ struct ath_buf *bf; ++ u16 seqno; ++ ++ while (1) { ++- *q = &tid->retry_q; ++- if (skb_queue_empty(*q)) ++- *q = &tid->buf_q; ++- ++- skb = skb_peek(*q); +++ skb = ath_tid_dequeue(tid); ++ if (!skb) ++ break; ++ ++@@ -898,7 +910,6 @@ ath_tx_get_tid_subframe(struct ath_softc ++ bf->bf_state.stale = false; ++ ++ if (!bf) { ++- __skb_unlink(skb, *q); ++ ath_txq_skb_done(sc, txq, skb); ++ ieee80211_free_txskb(sc->hw, skb); ++ continue; ++@@ -927,8 +938,19 @@ ath_tx_get_tid_subframe(struct ath_softc ++ seqno = bf->bf_state.seqno; ++ ++ /* do not step over block-ack window */ ++- if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) +++ if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { +++ __skb_queue_tail(&tid->retry_q, skb); +++ +++ /* If there are other skbs in the retry q, they are +++ * probably within the BAW, so loop immediately to get +++ * one of them. Otherwise the queue can get stuck. */ +++ if (!skb_queue_is_first(&tid->retry_q, skb) && skb != first_skb) { +++ if(!first_skb) /* infinite loop prevention */ +++ first_skb = skb; +++ continue; +++ } ++ break; +++ } ++ ++ if (tid->bar_index > ATH_BA_INDEX(tid->seq_start, seqno)) { ++ struct ath_tx_status ts = {}; ++@@ -936,7 +958,6 @@ ath_tx_get_tid_subframe(struct ath_softc ++ ++ INIT_LIST_HEAD(&bf_head); ++ list_add(&bf->list, &bf_head); ++- __skb_unlink(skb, *q); ++ ath_tx_update_baw(sc, tid, seqno); ++ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); ++ continue; ++@@ -948,11 +969,10 @@ ath_tx_get_tid_subframe(struct ath_softc ++ return NULL; ++ } ++ ++-static bool +++static int ++ ath_tx_form_aggr(struct ath_softc *sc, struct ath_txq *txq, ++ struct ath_atx_tid *tid, struct list_head *bf_q, ++- struct ath_buf *bf_first, struct sk_buff_head *tid_q, ++- int *aggr_len) +++ struct ath_buf *bf_first) ++ { ++ #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) ++ struct ath_buf *bf = bf_first, *bf_prev = NULL; ++@@ -962,12 +982,13 @@ ath_tx_form_aggr(struct ath_softc *sc, s ++ struct ieee80211_tx_info *tx_info; ++ struct ath_frame_info *fi; ++ struct sk_buff *skb; ++- bool closed = false; +++ ++ ++ bf = bf_first; ++ aggr_limit = ath_lookup_rate(sc, bf, tid); ++ ++- do { +++ while (bf) +++ { ++ skb = bf->bf_mpdu; ++ fi = get_frame_info(skb); ++ ++@@ -976,12 +997,12 @@ ath_tx_form_aggr(struct ath_softc *sc, s ++ if (nframes) { ++ if (aggr_limit < al + bpad + al_delta || ++ ath_lookup_legacy(bf) || nframes >= h_baw) ++- break; +++ goto stop; ++ ++ tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); ++ if ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) || ++ !(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) ++- break; +++ goto stop; ++ } ++ ++ /* add padding for previous frame to aggregation length */ ++@@ -1003,20 +1024,18 @@ ath_tx_form_aggr(struct ath_softc *sc, s ++ ath_tx_addto_baw(sc, tid, bf); ++ bf->bf_state.ndelim = ndelim; ++ ++- __skb_unlink(skb, tid_q); ++ list_add_tail(&bf->list, bf_q); ++ if (bf_prev) ++ bf_prev->bf_next = bf; ++ ++ bf_prev = bf; ++ ++- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); ++- if (!bf) { ++- closed = true; ++- break; ++- } ++- } while (ath_tid_has_buffered(tid)); ++- +++ bf = ath_tx_get_tid_subframe(sc, txq, tid); +++ } +++ goto finish; +++stop: +++ __skb_queue_tail(&tid->retry_q, bf->bf_mpdu); +++finish: ++ bf = bf_first; ++ bf->bf_lastbf = bf_prev; ++ ++@@ -1027,9 +1046,7 @@ ath_tx_form_aggr(struct ath_softc *sc, s ++ TX_STAT_INC(txq->axq_qnum, a_aggr); ++ } ++ ++- *aggr_len = al; ++- ++- return closed; +++ return al; ++ #undef PADBYTES ++ } ++ ++@@ -1406,18 +1423,15 @@ static void ath_tx_fill_desc(struct ath_ ++ static void ++ ath_tx_form_burst(struct ath_softc *sc, struct ath_txq *txq, ++ struct ath_atx_tid *tid, struct list_head *bf_q, ++- struct ath_buf *bf_first, struct sk_buff_head *tid_q) +++ struct ath_buf *bf_first) ++ { ++ struct ath_buf *bf = bf_first, *bf_prev = NULL; ++- struct sk_buff *skb; ++ int nframes = 0; ++ ++ do { ++ struct ieee80211_tx_info *tx_info; ++- skb = bf->bf_mpdu; ++ ++ nframes++; ++- __skb_unlink(skb, tid_q); ++ list_add_tail(&bf->list, bf_q); ++ if (bf_prev) ++ bf_prev->bf_next = bf; ++@@ -1426,13 +1440,15 @@ ath_tx_form_burst(struct ath_softc *sc, ++ if (nframes >= 2) ++ break; ++ ++- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); +++ bf = ath_tx_get_tid_subframe(sc, txq, tid); ++ if (!bf) ++ break; ++ ++ tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); ++- if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) +++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { +++ __skb_queue_tail(&tid->retry_q, bf->bf_mpdu); ++ break; +++ } ++ ++ ath_set_rates(tid->an->vif, tid->an->sta, bf, false); ++ } while (1); ++@@ -1443,34 +1459,33 @@ static bool ath_tx_sched_aggr(struct ath ++ { ++ struct ath_buf *bf; ++ struct ieee80211_tx_info *tx_info; ++- struct sk_buff_head *tid_q; ++ struct list_head bf_q; ++ int aggr_len = 0; ++- bool aggr, last = true; +++ bool aggr; ++ ++ if (!ath_tid_has_buffered(tid)) ++ return false; ++ ++ INIT_LIST_HEAD(&bf_q); ++ ++- bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); +++ bf = ath_tx_get_tid_subframe(sc, txq, tid); ++ if (!bf) ++ return false; ++ ++ tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); ++ aggr = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); ++ if ((aggr && txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) || ++- (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) { +++ (!aggr && txq->axq_depth >= ATH_NON_AGGR_MIN_QDEPTH)) { +++ __skb_queue_tail(&tid->retry_q, bf->bf_mpdu); ++ *stop = true; ++ return false; ++ } ++ ++ ath_set_rates(tid->an->vif, tid->an->sta, bf, false); ++ if (aggr) ++- last = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf, ++- tid_q, &aggr_len); +++ aggr_len = ath_tx_form_aggr(sc, txq, tid, &bf_q, bf); ++ else ++- ath_tx_form_burst(sc, txq, tid, &bf_q, bf, tid_q); +++ ath_tx_form_burst(sc, txq, tid, &bf_q, bf); ++ ++ if (list_empty(&bf_q)) ++ return false; ++@@ -1513,9 +1528,6 @@ int ath_tx_aggr_start(struct ath_softc * ++ an->mpdudensity = density; ++ } ++ ++- /* force sequence number allocation for pending frames */ ++- ath_tx_tid_change_state(sc, txtid); ++- ++ txtid->active = true; ++ *ssn = txtid->seq_start = txtid->seq_next; ++ txtid->bar_index = -1; ++@@ -1540,7 +1552,6 @@ void ath_tx_aggr_stop(struct ath_softc * ++ ath_txq_lock(sc, txq); ++ txtid->active = false; ++ ath_tx_flush_tid(sc, txtid); ++- ath_tx_tid_change_state(sc, txtid); ++ ath_txq_unlock_complete(sc, txq); ++ } ++ ++@@ -1550,14 +1561,12 @@ void ath_tx_aggr_sleep(struct ieee80211_ ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++ struct ath_atx_tid *tid; ++ struct ath_txq *txq; ++- bool buffered; ++ int tidno; ++ ++ ath_dbg(common, XMIT, "%s called\n", __func__); ++ ++- for (tidno = 0, tid = &an->tid[tidno]; ++- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { ++- +++ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { +++ tid = ATH_AN_2_TID(an, tidno); ++ txq = tid->txq; ++ ++ ath_txq_lock(sc, txq); ++@@ -1567,13 +1576,12 @@ void ath_tx_aggr_sleep(struct ieee80211_ ++ continue; ++ } ++ ++- buffered = ath_tid_has_buffered(tid); +++ if (!skb_queue_empty(&tid->retry_q)) +++ ieee80211_sta_set_buffered(sta, tid->tidno, true); ++ ++ list_del_init(&tid->list); ++ ++ ath_txq_unlock(sc, txq); ++- ++- ieee80211_sta_set_buffered(sta, tidno, buffered); ++ } ++ } ++ ++@@ -1586,19 +1594,16 @@ void ath_tx_aggr_wakeup(struct ath_softc ++ ++ ath_dbg(common, XMIT, "%s called\n", __func__); ++ ++- for (tidno = 0, tid = &an->tid[tidno]; ++- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { ++- +++ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { +++ tid = ATH_AN_2_TID(an, tidno); ++ txq = tid->txq; ++ ++ ath_txq_lock(sc, txq); ++ tid->clear_ps_filter = true; ++- ++ if (ath_tid_has_buffered(tid)) { ++ ath_tx_queue_tid(sc, txq, tid); ++ ath_txq_schedule(sc, txq); ++ } ++- ++ ath_txq_unlock_complete(sc, txq); ++ } ++ } ++@@ -1621,11 +1626,6 @@ void ath_tx_aggr_resume(struct ath_softc ++ ++ tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; ++ ++- if (ath_tid_has_buffered(tid)) { ++- ath_tx_queue_tid(sc, txq, tid); ++- ath_txq_schedule(sc, txq); ++- } ++- ++ ath_txq_unlock_complete(sc, txq); ++ } ++ ++@@ -1641,7 +1641,6 @@ 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; ++ ++@@ -1656,11 +1655,10 @@ void ath9k_release_buffered_frames(struc ++ ++ ath_txq_lock(sc, tid->txq); ++ while (nframes > 0) { ++- bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q); +++ bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid); ++ if (!bf) ++ break; ++ ++- __skb_unlink(bf->bf_mpdu, tid_q); ++ list_add_tail(&bf->list, &bf_q); ++ ath_set_rates(tid->an->vif, tid->an->sta, bf, true); ++ if (bf_isampdu(bf)) { ++@@ -1675,7 +1673,7 @@ void ath9k_release_buffered_frames(struc ++ sent++; ++ TX_STAT_INC(txq->axq_qnum, a_queued_hw); ++ ++- if (an->sta && !ath_tid_has_buffered(tid)) +++ if (an->sta && skb_queue_empty(&tid->retry_q)) ++ ieee80211_sta_set_buffered(an->sta, i, false); ++ } ++ ath_txq_unlock_complete(sc, tid->txq); ++@@ -1902,13 +1900,7 @@ bool ath_drain_all_txq(struct ath_softc ++ if (!ATH_TXQ_SETUP(sc, i)) ++ continue; ++ ++- /* ++- * The caller will resume queues with ieee80211_wake_queues. ++- * Mark the queue as not stopped to prevent ath_tx_complete ++- * from waking the queue too early. ++- */ ++ txq = &sc->tx.txq[i]; ++- txq->stopped = false; ++ ath_draintxq(sc, txq); ++ } ++ ++@@ -2308,15 +2300,12 @@ int ath_tx_start(struct ieee80211_hw *hw ++ struct ath_txq *txq = txctl->txq; ++ struct ath_atx_tid *tid = NULL; ++ struct ath_buf *bf; ++- bool queue, ps_resp; +++ bool ps_resp; ++ int q, ret; ++ ++ if (vif) ++ avp = (void *)vif->drv_priv; ++ ++- if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ++- txctl->force_channel = true; ++- ++ ps_resp = !!(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE); ++ ++ ret = ath_tx_prepare(hw, skb, txctl); ++@@ -2331,63 +2320,13 @@ int ath_tx_start(struct ieee80211_hw *hw ++ ++ q = skb_get_queue_mapping(skb); ++ +++ if (ps_resp) +++ txq = sc->tx.uapsdq; +++ ++ ath_txq_lock(sc, txq); ++ if (txq == sc->tx.txq_map[q]) { ++ fi->txq = q; ++- if (++txq->pending_frames > sc->tx.txq_max_pending[q] && ++- !txq->stopped) { ++- if (ath9k_is_chanctx_enabled()) ++- ieee80211_stop_queue(sc->hw, info->hw_queue); ++- else ++- ieee80211_stop_queue(sc->hw, q); ++- txq->stopped = true; ++- } ++- } ++- ++- queue = ieee80211_is_data_present(hdr->frame_control); ++- ++- /* If chanctx, queue all null frames while NOA could be there */ ++- if (ath9k_is_chanctx_enabled() && ++- ieee80211_is_nullfunc(hdr->frame_control) && ++- !txctl->force_channel) ++- queue = true; ++- ++- /* Force queueing of all frames that belong to a virtual interface on ++- * a different channel context, to ensure that they are sent on the ++- * correct channel. ++- */ ++- if (((avp && avp->chanctx != sc->cur_chan) || ++- sc->cur_chan->stopped) && !txctl->force_channel) { ++- if (!txctl->an) ++- txctl->an = &avp->mcast_node; ++- queue = true; ++- ps_resp = false; ++- } ++- ++- if (txctl->an && queue) ++- tid = ath_get_skb_tid(sc, txctl->an, skb); ++- ++- if (ps_resp) { ++- ath_txq_unlock(sc, txq); ++- txq = sc->tx.uapsdq; ++- ath_txq_lock(sc, txq); ++- } else if (txctl->an && queue) { ++- WARN_ON(tid->txq != txctl->txq); ++- ++- if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) ++- tid->clear_ps_filter = true; ++- ++- /* ++- * Add this frame to software queue for scheduling later ++- * for aggregation. ++- */ ++- TX_STAT_INC(txq->axq_qnum, a_queued_sw); ++- __skb_queue_tail(&tid->buf_q, skb); ++- if (!txctl->an->sleeping) ++- ath_tx_queue_tid(sc, txq, tid); ++- ++- ath_txq_schedule(sc, txq); ++- goto out; +++ ++txq->pending_frames; ++ } ++ ++ bf = ath_tx_setup_buffer(sc, txq, tid, skb); ++@@ -2871,9 +2810,8 @@ void ath_tx_node_init(struct ath_softc * ++ struct ath_atx_tid *tid; ++ int tidno, acno; ++ ++- for (tidno = 0, tid = &an->tid[tidno]; ++- tidno < IEEE80211_NUM_TIDS; ++- tidno++, tid++) { +++ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { +++ tid = ATH_AN_2_TID(an, tidno); ++ tid->an = an; ++ tid->tidno = tidno; ++ tid->seq_start = tid->seq_next = 0; ++@@ -2881,11 +2819,14 @@ void ath_tx_node_init(struct ath_softc * ++ tid->baw_head = tid->baw_tail = 0; ++ tid->active = false; ++ tid->clear_ps_filter = true; ++- __skb_queue_head_init(&tid->buf_q); +++ tid->has_queued = false; ++ __skb_queue_head_init(&tid->retry_q); ++ INIT_LIST_HEAD(&tid->list); ++ acno = TID_TO_WME_AC(tidno); ++ tid->txq = sc->tx.txq_map[acno]; +++ +++ if (!an->sta) +++ break; /* just one multicast ath_atx_tid */ ++ } ++ } ++ ++@@ -2895,9 +2836,8 @@ void ath_tx_node_cleanup(struct ath_soft ++ struct ath_txq *txq; ++ int tidno; ++ ++- for (tidno = 0, tid = &an->tid[tidno]; ++- tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { ++- +++ for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) { +++ tid = ATH_AN_2_TID(an, tidno); ++ txq = tid->txq; ++ ++ ath_txq_lock(sc, txq); ++@@ -2909,6 +2849,9 @@ void ath_tx_node_cleanup(struct ath_soft ++ tid->active = false; ++ ++ ath_txq_unlock(sc, txq); +++ +++ if (!an->sta) +++ break; /* just one multicast ath_atx_tid */ ++ } ++ } ++ diff --git a/package/kernel/mac80211/patches/320-cfg80211-add-support-for-non-linear-skbs-in-ieee8021.patch b/package/kernel/mac80211/patches/320-cfg80211-add-support-for-non-linear-skbs-in-ieee8021.patch deleted file mode 100644 index 2eeed22..0000000 @@ -3838,6 +6232,37 @@ index 2eeed22..0000000 - return; - - purge: +diff --git a/package/kernel/mac80211/patches/321-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch b/package/kernel/mac80211/patches/321-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch +new file mode 100644 +index 0000000..9caa76d +--- /dev/null ++++ b/package/kernel/mac80211/patches/321-ath9k_hw-reset-AHB-WMAC-interface-on-AR91xx.patch +@@ -0,0 +1,25 @@ ++From: Felix Fietkau ++Date: Sat, 9 Jul 2016 15:25:24 +0200 ++Subject: [PATCH] ath9k_hw: reset AHB-WMAC interface on AR91xx ++ ++Should fix a few stability issues ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/hw.c +++++ b/drivers/net/wireless/ath/ath9k/hw.c ++@@ -1398,8 +1398,12 @@ static bool ath9k_hw_set_reset(struct at ++ if (!AR_SREV_9100(ah)) ++ REG_WRITE(ah, AR_RC, 0); ++ ++- if (AR_SREV_9100(ah)) +++ if (AR_SREV_9100(ah)) { +++ /* Reset the AHB-WMAC interface */ +++ if (ah->external_reset) +++ ah->external_reset(); ++ udelay(50); +++ } ++ ++ return true; ++ } diff --git a/package/kernel/mac80211/patches/321-mac80211-Parse-legacy-and-HT-rate-in-injected-frames.patch b/package/kernel/mac80211/patches/321-mac80211-Parse-legacy-and-HT-rate-in-injected-frames.patch deleted file mode 100644 index c4155a1..0000000 @@ -3999,6 +6424,137 @@ index c4155a1..0000000 - goto fail; - - rcu_read_lock(); +diff --git a/package/kernel/mac80211/patches/322-ath9k_hw-issue-external-reset-for-QCA9550.patch b/package/kernel/mac80211/patches/322-ath9k_hw-issue-external-reset-for-QCA9550.patch +new file mode 100644 +index 0000000..5d4e849 +--- /dev/null ++++ b/package/kernel/mac80211/patches/322-ath9k_hw-issue-external-reset-for-QCA9550.patch +@@ -0,0 +1,125 @@ ++From: Felix Fietkau ++Date: Sat, 9 Jul 2016 15:26:44 +0200 ++Subject: [PATCH] ath9k_hw: issue external reset for QCA9550 ++ ++The RTC interface on the SoC needs to be reset along with the rest of ++the WMAC. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/hw.c +++++ b/drivers/net/wireless/ath/ath9k/hw.c ++@@ -1275,39 +1275,56 @@ void ath9k_hw_get_delta_slope_vals(struc ++ *coef_exponent = coef_exp - 16; ++ } ++ ++-/* AR9330 WAR: ++- * call external reset function to reset WMAC if: ++- * - doing a cold reset ++- * - we have pending frames in the TX queues. ++- */ ++-static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type) +++static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type) ++ { ++- int i, npend = 0; +++ int i; ++ ++- for (i = 0; i < AR_NUM_QCU; i++) { ++- npend = ath9k_hw_numtxpending(ah, i); ++- if (npend) ++- break; +++ if (type == ATH9K_RESET_COLD) +++ return true; +++ +++ if (AR_SREV_9550(ah)) +++ return true; +++ +++ /* AR9330 WAR: +++ * call external reset function to reset WMAC if: +++ * - doing a cold reset +++ * - we have pending frames in the TX queues. +++ */ +++ if (AR_SREV_9330(ah)) { +++ for (i = 0; i < AR_NUM_QCU; i++) { +++ if (ath9k_hw_numtxpending(ah, i)) +++ return true; +++ } ++ } ++ ++- if (ah->external_reset && ++- (npend || type == ATH9K_RESET_COLD)) { ++- int reset_err = 0; +++ return false; +++} ++ ++- ath_dbg(ath9k_hw_common(ah), RESET, ++- "reset MAC via external reset\n"); +++static bool ath9k_hw_external_reset(struct ath_hw *ah, int type) +++{ +++ int err; ++ ++- reset_err = ah->external_reset(); ++- if (reset_err) { ++- ath_err(ath9k_hw_common(ah), ++- "External reset failed, err=%d\n", ++- reset_err); ++- return false; ++- } +++ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type)) +++ return true; ++ ++- REG_WRITE(ah, AR_RTC_RESET, 1); +++ ath_dbg(ath9k_hw_common(ah), RESET, +++ "reset MAC via external reset\n"); +++ +++ err = ah->external_reset(); +++ if (err) { +++ ath_err(ath9k_hw_common(ah), +++ "External reset failed, err=%d\n", err); +++ return false; +++ } +++ +++ if (AR_SREV_9550(ah)) { +++ REG_WRITE(ah, AR_RTC_RESET, 0); +++ udelay(10); ++ } ++ +++ REG_WRITE(ah, AR_RTC_RESET, 1); +++ udelay(10); +++ ++ return true; ++ } ++ ++@@ -1360,24 +1377,23 @@ static bool ath9k_hw_set_reset(struct at ++ rst_flags |= AR_RTC_RC_MAC_COLD; ++ } ++ ++- if (AR_SREV_9330(ah)) { ++- if (!ath9k_hw_ar9330_reset_war(ah, type)) ++- return false; ++- } ++- ++ if (ath9k_hw_mci_is_enabled(ah)) ++ ar9003_mci_check_gpm_offset(ah); ++ ++ /* DMA HALT added to resolve ar9300 and ar9580 bus error during ++- * RTC_RC reg read +++ * RTC_RC reg read. Also needed for AR9550 external reset ++ */ ++- if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) { +++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) { ++ REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); ++ ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK, ++ 20 * AH_WAIT_TIMEOUT); ++- REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); ++ } ++ +++ ath9k_hw_external_reset(ah, type); +++ +++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) +++ REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ); +++ ++ REG_WRITE(ah, AR_RTC_RC, rst_flags); ++ ++ REGWRITE_BUFFER_FLUSH(ah); diff --git a/package/kernel/mac80211/patches/322-mac80211-add-A-MSDU-tx-support.patch b/package/kernel/mac80211/patches/322-mac80211-add-A-MSDU-tx-support.patch deleted file mode 100644 index e7bfb9c..0000000 @@ -4730,6 +7286,130 @@ index 35887fc..0000000 - BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_DEVICE_ID), - BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_2G_DEVICE_ID), - BRCMF_PCIE_DEVICE(BRCM_PCIE_4366_5G_DEVICE_ID), +diff --git a/package/kernel/mac80211/patches/323-ath9k-Fix-programming-of-minCCA-power-threshold.patch b/package/kernel/mac80211/patches/323-ath9k-Fix-programming-of-minCCA-power-threshold.patch +new file mode 100644 +index 0000000..59ac29b +--- /dev/null ++++ b/package/kernel/mac80211/patches/323-ath9k-Fix-programming-of-minCCA-power-threshold.patch +@@ -0,0 +1,26 @@ ++From: Sven Eckelmann ++Date: Fri, 17 Jun 2016 11:58:20 +0200 ++Subject: [PATCH] ath9k: Fix programming of minCCA power threshold ++ ++The function ar9003_hw_apply_minccapwr_thresh takes as second parameter not ++a pointer to the channel but a boolean value describing whether the channel ++is 2.4GHz or not. This broke (according to the origin commit) the ETSI ++regulatory compliance on 5GHz channels. ++ ++Fixes: 3533bf6b15a0 ("ath9k: Fix regulatory compliance") ++Signed-off-by: Sven Eckelmann ++Cc: Simon Wunderlich ++Cc: Sujith Manoharan ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c ++@@ -4175,7 +4175,7 @@ static void ath9k_hw_ar9300_set_board_va ++ if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9531(ah)) ++ ar9003_hw_internal_regulator_apply(ah); ++ ar9003_hw_apply_tuning_caps(ah); ++- ar9003_hw_apply_minccapwr_thresh(ah, chan); +++ ar9003_hw_apply_minccapwr_thresh(ah, is2ghz); ++ ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz); ++ ar9003_hw_thermometer_apply(ah); ++ ar9003_hw_thermo_cal_apply(ah); +diff --git a/package/kernel/mac80211/patches/324-ath9k_hw-fix-spectral-scan-on-AR9285-and-newer.patch b/package/kernel/mac80211/patches/324-ath9k_hw-fix-spectral-scan-on-AR9285-and-newer.patch +new file mode 100644 +index 0000000..b6f4868 +--- /dev/null ++++ b/package/kernel/mac80211/patches/324-ath9k_hw-fix-spectral-scan-on-AR9285-and-newer.patch +@@ -0,0 +1,86 @@ ++From: Felix Fietkau ++Date: Mon, 11 Jul 2016 10:34:37 +0200 ++Subject: [PATCH] ath9k_hw: fix spectral scan on AR9285 and newer ++ ++The register layout of AR_PHY_SPECTRAL_SCAN has changed, only AR9280 ++uses the old layout ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c ++@@ -476,6 +476,7 @@ static void ar9002_hw_set_bt_ant_diversi ++ static void ar9002_hw_spectral_scan_config(struct ath_hw *ah, ++ struct ath_spec_scan *param) ++ { +++ u32 repeat_bit; ++ u8 count; ++ ++ if (!param->enabled) { ++@@ -486,12 +487,15 @@ static void ar9002_hw_spectral_scan_conf ++ REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA); ++ REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE); ++ +++ if (AR_SREV_9280(ah)) +++ repeat_bit = AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT; +++ else +++ repeat_bit = AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI; +++ ++ if (param->short_repeat) ++- REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, ++- AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); +++ REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit); ++ else ++- REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, ++- AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT); +++ REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN, repeat_bit); ++ ++ /* on AR92xx, the highest bit of count will make the the chip send ++ * spectral samples endlessly. Check if this really was intended, ++@@ -499,15 +503,25 @@ static void ar9002_hw_spectral_scan_conf ++ */ ++ count = param->count; ++ if (param->endless) { ++- if (AR_SREV_9271(ah)) ++- count = 0; ++- else +++ if (AR_SREV_9280(ah)) ++ count = 0x80; +++ else +++ count = 0; ++ } else if (count & 0x80) ++ count = 0x7f; +++ else if (!count) +++ count = 1; +++ +++ if (AR_SREV_9280(ah)) { +++ REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, +++ AR_PHY_SPECTRAL_SCAN_COUNT, count); +++ } else { +++ REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, +++ AR_PHY_SPECTRAL_SCAN_COUNT_KIWI, count); +++ REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, +++ AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT); +++ } ++ ++- REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, ++- AR_PHY_SPECTRAL_SCAN_COUNT, count); ++ REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, ++ AR_PHY_SPECTRAL_SCAN_PERIOD, param->period); ++ REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, ++--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h ++@@ -177,8 +177,11 @@ ++ #define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8 ++ #define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/ ++ #define AR_PHY_SPECTRAL_SCAN_COUNT_S 16 +++#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI 0x0FFF0000 /* Number of reports, reg 68, bits 16-27*/ +++#define AR_PHY_SPECTRAL_SCAN_COUNT_KIWI_S 16 ++ #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/ ++-#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/ +++#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_KIWI 0x10000000 /* Short repeat, reg 68, bit 28*/ +++#define AR_PHY_SPECTRAL_SCAN_PHYERR_MASK_SELECT 0x40000000 ++ ++ #define AR_PHY_RX_DELAY 0x9914 ++ #define AR_PHY_SEARCH_START_DELAY 0x9918 diff --git a/package/kernel/mac80211/patches/324-brcmfmac-treat-NULL-character-in-NVRAM-as-separator.patch b/package/kernel/mac80211/patches/324-brcmfmac-treat-NULL-character-in-NVRAM-as-separator.patch deleted file mode 100644 index 6ce60f1..0000000 @@ -4768,6 +7448,69 @@ index 6ce60f1..0000000 - goto proceed; - if (c == '#') - return COMMENT; +diff --git a/package/kernel/mac80211/patches/325-ath9k_hw-fix-duplicate-and-partially-wrong-definitio.patch b/package/kernel/mac80211/patches/325-ath9k_hw-fix-duplicate-and-partially-wrong-definitio.patch +new file mode 100644 +index 0000000..6685f33 +--- /dev/null ++++ b/package/kernel/mac80211/patches/325-ath9k_hw-fix-duplicate-and-partially-wrong-definitio.patch +@@ -0,0 +1,57 @@ ++From: Felix Fietkau ++Date: Mon, 11 Jul 2016 11:31:39 +0200 ++Subject: [PATCH] ath9k_hw: fix duplicate (and partially wrong) definition ++ of AR_CH0_THERM ++ ++AR_PHY_65NM_CH0_THERM and AR_CH0_THERM were supposed to refer to the ++same register, however they had different SREV checks. ++ ++Remove the duplicate and use the checks. Since there were other SREV ++checks present in the only place that uses this, this will probaby not ++affect runtime behavior. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h ++@@ -689,13 +689,6 @@ ++ #define AR_CH0_TOP_XPABIASLVL (AR_SREV_9550(ah) ? 0x3c0 : 0x300) ++ #define AR_CH0_TOP_XPABIASLVL_S (AR_SREV_9550(ah) ? 6 : 8) ++ ++-#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : \ ++- ((AR_SREV_9485(ah) ? 0x1628c : 0x16294))) ++-#define AR_CH0_THERM_XPABIASLVL_MSB 0x3 ++-#define AR_CH0_THERM_XPABIASLVL_MSB_S 0 ++-#define AR_CH0_THERM_XPASHORT2GND 0x4 ++-#define AR_CH0_THERM_XPASHORT2GND_S 2 ++- ++ #define AR_SWITCH_TABLE_COM_ALL (0xffff) ++ #define AR_SWITCH_TABLE_COM_ALL_S (0) ++ #define AR_SWITCH_TABLE_COM_AR9462_ALL (0xffffff) ++@@ -712,15 +705,17 @@ ++ #define AR_SWITCH_TABLE_ALL (0xfff) ++ #define AR_SWITCH_TABLE_ALL_S (0) ++ ++-#define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\ ++- ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16294 : 0x1628c)) +++#define AR_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 :\ +++ ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16294 : 0x1628c)) +++#define AR_CH0_THERM_XPABIASLVL_MSB 0x3 +++#define AR_CH0_THERM_XPABIASLVL_MSB_S 0 +++#define AR_CH0_THERM_XPASHORT2GND 0x4 +++#define AR_CH0_THERM_XPASHORT2GND_S 2 ++ ++-#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 ++-#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 ++-#define AR_PHY_65NM_CH0_THERM_START 0x20000000 ++-#define AR_PHY_65NM_CH0_THERM_START_S 29 ++-#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT 0x0000ff00 ++-#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8 +++#define AR_CH0_THERM_LOCAL 0x80000000 +++#define AR_CH0_THERM_START 0x20000000 +++#define AR_CH0_THERM_SAR_ADC_OUT 0x0000ff00 +++#define AR_CH0_THERM_SAR_ADC_OUT_S 8 ++ ++ #define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \ ++ (AR_SREV_9462(ah) ? 0x16290 : 0x16284)) diff --git a/package/kernel/mac80211/patches/325-brcmfmac-sdio-Increase-the-default-timeouts-a-bit.patch b/package/kernel/mac80211/patches/325-brcmfmac-sdio-Increase-the-default-timeouts-a-bit.patch deleted file mode 100644 index 012dea1..0000000 @@ -4908,6 +7651,200 @@ index 71f7a40..0000000 - ath_dbg(common, ANY, - "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", - REG_READ(ah, AR_PHY_AGC_CONTROL)); +diff --git a/package/kernel/mac80211/patches/326-ath9k_hw-simplify-ar9003_hw_per_calibration.patch b/package/kernel/mac80211/patches/326-ath9k_hw-simplify-ar9003_hw_per_calibration.patch +new file mode 100644 +index 0000000..999d993 +--- /dev/null ++++ b/package/kernel/mac80211/patches/326-ath9k_hw-simplify-ar9003_hw_per_calibration.patch +@@ -0,0 +1,88 @@ ++From: Felix Fietkau ++Date: Mon, 11 Jul 2016 11:34:47 +0200 ++Subject: [PATCH] ath9k_hw: simplify ar9003_hw_per_calibration ++ ++Reduce indentation, use a variable to save a few pointer dereferences ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c ++@@ -75,50 +75,49 @@ static bool ar9003_hw_per_calibration(st ++ struct ath9k_cal_list *currCal) ++ { ++ struct ath9k_hw_cal_data *caldata = ah->caldata; ++- /* Cal is assumed not done until explicitly set below */ ++- bool iscaldone = false; +++ const struct ath9k_percal_data *cur_caldata = currCal->calData; ++ ++ /* Calibration in progress. */ ++ if (currCal->calState == CAL_RUNNING) { ++ /* Check to see if it has finished. */ ++- if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) { ++- /* ++- * Accumulate cal measures for active chains ++- */ ++- currCal->calData->calCollect(ah); ++- ah->cal_samples++; +++ if (REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL) +++ return false; ++ ++- if (ah->cal_samples >= ++- currCal->calData->calNumSamples) { ++- unsigned int i, numChains = 0; ++- for (i = 0; i < AR9300_MAX_CHAINS; i++) { ++- if (rxchainmask & (1 << i)) ++- numChains++; ++- } +++ /* +++ * Accumulate cal measures for active chains +++ */ +++ cur_caldata->calCollect(ah); +++ ah->cal_samples++; ++ ++- /* ++- * Process accumulated data ++- */ ++- currCal->calData->calPostProc(ah, numChains); +++ if (ah->cal_samples >= cur_caldata->calNumSamples) { +++ unsigned int i, numChains = 0; +++ for (i = 0; i < AR9300_MAX_CHAINS; i++) { +++ if (rxchainmask & (1 << i)) +++ numChains++; +++ } ++ ++- /* Calibration has finished. */ ++- caldata->CalValid |= currCal->calData->calType; ++- currCal->calState = CAL_DONE; ++- iscaldone = true; ++- } else { +++ /* +++ * Process accumulated data +++ */ +++ cur_caldata->calPostProc(ah, numChains); +++ +++ /* Calibration has finished. */ +++ caldata->CalValid |= cur_caldata->calType; +++ currCal->calState = CAL_DONE; +++ return true; +++ } else { ++ /* ++ * Set-up collection of another sub-sample until we ++ * get desired number ++ */ ++ ar9003_hw_setup_calibration(ah, currCal); ++- } ++ } ++- } else if (!(caldata->CalValid & currCal->calData->calType)) { +++ } else if (!(caldata->CalValid & cur_caldata->calType)) { ++ /* If current cal is marked invalid in channel, kick it off */ ++ ath9k_hw_reset_calibration(ah, currCal); ++ } ++ ++- return iscaldone; +++ return false; ++ } ++ ++ static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, +diff --git a/package/kernel/mac80211/patches/327-ath9k_hw-get-rid-of-some-duplicate-code-in-calibrati.patch b/package/kernel/mac80211/patches/327-ath9k_hw-get-rid-of-some-duplicate-code-in-calibrati.patch +new file mode 100644 +index 0000000..b7f3823 +--- /dev/null ++++ b/package/kernel/mac80211/patches/327-ath9k_hw-get-rid-of-some-duplicate-code-in-calibrati.patch +@@ -0,0 +1,94 @@ ++From: Felix Fietkau ++Date: Mon, 11 Jul 2016 11:35:20 +0200 ++Subject: [PATCH] ath9k_hw: get rid of some duplicate code in calibration ++ init ++ ++Remove a misleading debug message as well ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c ++@@ -1373,6 +1373,26 @@ static void ar9003_hw_cl_cal_post_proc(s ++ } ++ } ++ +++static void ar9003_hw_init_cal_common(struct ath_hw *ah) +++{ +++ struct ath9k_hw_cal_data *caldata = ah->caldata; +++ +++ /* Initialize list pointers */ +++ ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; +++ +++ INIT_CAL(&ah->iq_caldata); +++ INSERT_CAL(ah, &ah->iq_caldata); +++ +++ /* Initialize current pointer to first element in list */ +++ ah->cal_list_curr = ah->cal_list; +++ +++ if (ah->cal_list_curr) +++ ath9k_hw_reset_calibration(ah, ah->cal_list_curr); +++ +++ if (caldata) +++ caldata->CalValid = 0; +++} +++ ++ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah, ++ struct ath9k_channel *chan) ++ { ++@@ -1532,21 +1552,7 @@ skip_tx_iqcal: ++ /* Revert chainmask to runtime parameters */ ++ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); ++ ++- /* Initialize list pointers */ ++- ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; ++- ++- INIT_CAL(&ah->iq_caldata); ++- INSERT_CAL(ah, &ah->iq_caldata); ++- ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n"); ++- ++- /* Initialize current pointer to first element in list */ ++- ah->cal_list_curr = ah->cal_list; ++- ++- if (ah->cal_list_curr) ++- ath9k_hw_reset_calibration(ah, ah->cal_list_curr); ++- ++- if (caldata) ++- caldata->CalValid = 0; +++ ar9003_hw_init_cal_common(ah); ++ ++ return true; ++ } ++@@ -1577,8 +1583,6 @@ static bool do_ar9003_agc_cal(struct ath ++ 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 status = true; ++ bool run_agc_cal = false, sep_iq_cal = false; ++@@ -1676,21 +1680,7 @@ skip_tx_iqcal: ++ /* Revert chainmask to runtime parameters */ ++ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); ++ ++- /* Initialize list pointers */ ++- ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; ++- ++- INIT_CAL(&ah->iq_caldata); ++- INSERT_CAL(ah, &ah->iq_caldata); ++- ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n"); ++- ++- /* Initialize current pointer to first element in list */ ++- ah->cal_list_curr = ah->cal_list; ++- ++- if (ah->cal_list_curr) ++- ath9k_hw_reset_calibration(ah, ah->cal_list_curr); ++- ++- if (caldata) ++- caldata->CalValid = 0; +++ ar9003_hw_init_cal_common(ah); ++ ++ return true; ++ } diff --git a/package/kernel/mac80211/patches/327-mac80211-Remove-MPP-table-entries-with-MPath.patch b/package/kernel/mac80211/patches/327-mac80211-Remove-MPP-table-entries-with-MPath.patch deleted file mode 100644 index f7f9df9..0000000 @@ -4968,6 +7905,109 @@ index f7f9df9..0000000 - read_lock_bh(&pathtbl_resize_lock); - tbl = resize_dereference_mesh_paths(); - hash_idx = mesh_table_hash(addr, sdata, tbl); +diff --git a/package/kernel/mac80211/patches/328-ath9k_hw-implement-temperature-compensation-support-.patch b/package/kernel/mac80211/patches/328-ath9k_hw-implement-temperature-compensation-support-.patch +new file mode 100644 +index 0000000..cff32ad +--- /dev/null ++++ b/package/kernel/mac80211/patches/328-ath9k_hw-implement-temperature-compensation-support-.patch +@@ -0,0 +1,97 @@ ++From: Felix Fietkau ++Date: Mon, 11 Jul 2016 11:35:55 +0200 ++Subject: [PATCH] ath9k_hw: implement temperature compensation support for ++ AR9003+ ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c ++@@ -33,6 +33,7 @@ struct coeff { ++ ++ enum ar9003_cal_types { ++ IQ_MISMATCH_CAL = BIT(0), +++ TEMP_COMP_CAL = BIT(1), ++ }; ++ ++ static void ar9003_hw_setup_calibration(struct ath_hw *ah, ++@@ -58,6 +59,12 @@ static void ar9003_hw_setup_calibration( ++ /* Kick-off cal */ ++ REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); ++ break; +++ case TEMP_COMP_CAL: +++ ath_dbg(common, CALIBRATE, +++ "starting Temperature Compensation Calibration\n"); +++ REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_LOCAL); +++ REG_SET_BIT(ah, AR_CH0_THERM, AR_CH0_THERM_START); +++ break; ++ default: ++ ath_err(common, "Invalid calibration type\n"); ++ break; ++@@ -86,7 +93,8 @@ static bool ar9003_hw_per_calibration(st ++ /* ++ * Accumulate cal measures for active chains ++ */ ++- cur_caldata->calCollect(ah); +++ if (cur_caldata->calCollect) +++ cur_caldata->calCollect(ah); ++ ah->cal_samples++; ++ ++ if (ah->cal_samples >= cur_caldata->calNumSamples) { ++@@ -99,7 +107,8 @@ static bool ar9003_hw_per_calibration(st ++ /* ++ * Process accumulated data ++ */ ++- cur_caldata->calPostProc(ah, numChains); +++ if (cur_caldata->calPostProc) +++ cur_caldata->calPostProc(ah, numChains); ++ ++ /* Calibration has finished. */ ++ caldata->CalValid |= cur_caldata->calType; ++@@ -314,9 +323,16 @@ static const struct ath9k_percal_data iq ++ ar9003_hw_iqcalibrate ++ }; ++ +++static const struct ath9k_percal_data temp_cal_single_sample = { +++ TEMP_COMP_CAL, +++ MIN_CAL_SAMPLES, +++ PER_MAX_LOG_COUNT, +++}; +++ ++ static void ar9003_hw_init_cal_settings(struct ath_hw *ah) ++ { ++ ah->iq_caldata.calData = &iq_cal_single_sample; +++ ah->temp_caldata.calData = &temp_cal_single_sample; ++ ++ if (AR_SREV_9300_20_OR_LATER(ah)) { ++ ah->enabled_cals |= TX_IQ_CAL; ++@@ -324,7 +340,7 @@ static void ar9003_hw_init_cal_settings( ++ ah->enabled_cals |= TX_IQ_ON_AGC_CAL; ++ } ++ ++- ah->supp_cals = IQ_MISMATCH_CAL; +++ ah->supp_cals = IQ_MISMATCH_CAL | TEMP_COMP_CAL; ++ } ++ ++ #define OFF_UPPER_LT 24 ++@@ -1383,6 +1399,9 @@ static void ar9003_hw_init_cal_common(st ++ INIT_CAL(&ah->iq_caldata); ++ INSERT_CAL(ah, &ah->iq_caldata); ++ +++ INIT_CAL(&ah->temp_caldata); +++ INSERT_CAL(ah, &ah->temp_caldata); +++ ++ /* Initialize current pointer to first element in list */ ++ ah->cal_list_curr = ah->cal_list; ++ ++--- a/drivers/net/wireless/ath/ath9k/hw.h +++++ b/drivers/net/wireless/ath/ath9k/hw.h ++@@ -830,6 +830,7 @@ struct ath_hw { ++ /* Calibration */ ++ u32 supp_cals; ++ struct ath9k_cal_list iq_caldata; +++ struct ath9k_cal_list temp_caldata; ++ struct ath9k_cal_list adcgain_caldata; ++ struct ath9k_cal_list adcdc_caldata; ++ struct ath9k_cal_list *cal_list; diff --git a/package/kernel/mac80211/patches/328-mac80211-let-unused-MPP-table-entries-timeout.patch b/package/kernel/mac80211/patches/328-mac80211-let-unused-MPP-table-entries-timeout.patch deleted file mode 100644 index 740993c..0000000 @@ -5227,6 +8267,75 @@ index 0c36b1d..0000000 - return err; - } - +diff --git a/package/kernel/mac80211/patches/329-mac80211-fix-check-for-buffered-powersave-frames-wit.patch b/package/kernel/mac80211/patches/329-mac80211-fix-check-for-buffered-powersave-frames-wit.patch +new file mode 100644 +index 0000000..38e541c +--- /dev/null ++++ b/package/kernel/mac80211/patches/329-mac80211-fix-check-for-buffered-powersave-frames-wit.patch +@@ -0,0 +1,21 @@ ++From: Felix Fietkau ++Date: Mon, 11 Jul 2016 15:07:06 +0200 ++Subject: [PATCH] mac80211: fix check for buffered powersave frames with txq ++ ++The logic was inverted here, set the bit if frames are pending. ++ ++Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/mac80211/rx.c +++++ b/net/mac80211/rx.c ++@@ -1268,7 +1268,7 @@ static void sta_ps_start(struct sta_info ++ for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { ++ struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]); ++ ++- if (!txqi->tin.backlog_packets) +++ if (txqi->tin.backlog_packets) ++ set_bit(tid, &sta->txq_buffered_tids); ++ else ++ clear_bit(tid, &sta->txq_buffered_tids); +diff --git a/package/kernel/mac80211/patches/330-ath10k-fix-rx-status-reporting-for-A-MSDU-subframes.patch b/package/kernel/mac80211/patches/330-ath10k-fix-rx-status-reporting-for-A-MSDU-subframes.patch +new file mode 100644 +index 0000000..a6031b9 +--- /dev/null ++++ b/package/kernel/mac80211/patches/330-ath10k-fix-rx-status-reporting-for-A-MSDU-subframes.patch +@@ -0,0 +1,36 @@ ++From: Felix Fietkau ++Date: Sun, 17 Jul 2016 12:49:59 +0200 ++Subject: [PATCH] ath10k: fix rx status reporting for A-MSDU subframes ++ ++Patch by Nagarajan, Ashok Raj ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c ++@@ -1525,7 +1525,7 @@ static void ath10k_htt_rx_h_filter(struc ++ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) ++ { ++ struct ath10k *ar = htt->ar; ++- static struct ieee80211_rx_status rx_status; +++ struct ieee80211_rx_status *rx_status = &htt->rx_status; ++ struct sk_buff_head amsdu; ++ int ret; ++ ++@@ -1549,11 +1549,11 @@ static int ath10k_htt_rx_handle_amsdu(st ++ return ret; ++ } ++ ++- ath10k_htt_rx_h_ppdu(ar, &amsdu, &rx_status, 0xffff); +++ ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff); ++ ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0); ++- ath10k_htt_rx_h_filter(ar, &amsdu, &rx_status); ++- ath10k_htt_rx_h_mpdu(ar, &amsdu, &rx_status); ++- ath10k_htt_rx_h_deliver(ar, &amsdu, &rx_status); +++ ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); +++ ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); +++ ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); ++ ++ return 0; ++ } diff --git a/package/kernel/mac80211/patches/330-mac80211-minstrel-Change-expected-throughput-unit-ba.patch b/package/kernel/mac80211/patches/330-mac80211-minstrel-Change-expected-throughput-unit-ba.patch deleted file mode 100644 index 4dc6d66..0000000 @@ -6614,26 +9723,26 @@ index 7351353..4634283 100644 WLAN_VENDOR_ATH= ATH_DEBUG= diff --git a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch -index 1a62484..819e64f 100644 +index 1a62484..f2f52f9 100644 --- a/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch +++ b/package/kernel/mac80211/patches/410-ath9k_allow_adhoc_and_ap.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -722,6 +722,7 @@ static const struct ieee80211_iface_limi -+@@ -728,6 +728,7 @@ static const struct ieee80211_iface_limi ++@@ -727,6 +727,7 @@ static const struct ieee80211_iface_limi BIT(NL80211_IFTYPE_AP) }, { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) }, diff --git a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch -index a7f9d9f..4b6da97 100644 +index a7f9d9f..f21eed1 100644 --- a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch +++ b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1301,6 +1301,53 @@ void ath9k_deinit_debug(struct ath_softc -+@@ -1319,6 +1319,53 @@ void ath9k_deinit_debug(struct ath_softc ++@@ -1315,6 +1315,53 @@ void ath9k_deinit_debug(struct ath_softc ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); } @@ -6642,7 +9751,7 @@ index a7f9d9f..4b6da97 100644 { struct ath_common *common = ath9k_hw_common(ah); -@@ -1320,6 +1367,8 @@ int ath9k_init_debug(struct ath_hw *ah) -+@@ -1338,6 +1385,8 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1334,6 +1381,8 @@ int ath9k_init_debug(struct ath_hw *ah) ath9k_tx99_init_debug(sc); ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); @@ -6658,15 +9767,25 @@ index 5892c3e..1825d77 100644 { int error; +diff --git a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch +index 6766111..15b8d7b 100644 +--- a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch ++++ b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch +@@ -8,4 +8,4 @@ + +#define ATH_RXBUF 256 + #define ATH_TXBUF 512 + #define ATH_TXBUF_RESERVE 5 +- #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) ++ #define ATH_TXMAXTRY 13 diff --git a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch -index 5ecf528..a105d40 100644 +index 5ecf528..c98072b 100644 --- a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch +++ b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1348,6 +1348,52 @@ static const struct file_operations fops -+@@ -1366,6 +1366,52 @@ static const struct file_operations fops ++@@ -1362,6 +1362,52 @@ static const struct file_operations fops .owner = THIS_MODULE }; @@ -6675,7 +9794,7 @@ index 5ecf528..a105d40 100644 { struct ath_common *common = ath9k_hw_common(ah); -@@ -1369,6 +1415,8 @@ int ath9k_init_debug(struct ath_hw *ah) -+@@ -1387,6 +1433,8 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1383,6 +1429,8 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_eeprom); @@ -6702,14 +9821,14 @@ index c84d1bc..167eeff 100644 #endif diff --git a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch -index e151a12..28f5dcc 100644 +index e151a12..c40598d 100644 --- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch +++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch @@ -1,6 +1,6 @@ --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h -@@ -2363,6 +2363,7 @@ struct cfg80211_qos_map { -+@@ -2406,6 +2406,7 @@ struct cfg80211_qos_map { ++@@ -2410,6 +2410,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 @@ -6718,7 +9837,7 @@ index e151a12..28f5dcc 100644 * @set_wds_peer: set the WDS peer for a WDS interface * -@@ -2624,6 +2625,7 @@ struct cfg80211_ops { -+@@ -2667,6 +2668,7 @@ struct cfg80211_ops { ++@@ -2671,6 +2672,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); @@ -6727,7 +9846,7 @@ index e151a12..28f5dcc 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h -@@ -1286,6 +1286,7 @@ enum ieee80211_smps_mode { -+@@ -1305,6 +1305,7 @@ enum ieee80211_smps_mode { ++@@ -1317,6 +1317,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 @@ -6736,7 +9855,7 @@ index e151a12..28f5dcc 100644 * @chandef: the channel definition to tune to * @radar_enabled: whether radar detection is enabled -@@ -1306,6 +1307,7 @@ enum ieee80211_smps_mode { -+@@ -1325,6 +1326,7 @@ enum ieee80211_smps_mode { ++@@ -1337,6 +1338,7 @@ enum ieee80211_smps_mode { struct ieee80211_conf { u32 flags; int power_level, dynamic_ps_timeout; @@ -6747,9 +9866,9 @@ index e151a12..28f5dcc 100644 -@@ -1790,6 +1790,9 @@ enum nl80211_commands { - * between scans. The scan plans are executed sequentially. - * Each scan plan is a nested attribute of &enum nl80211_sched_scan_plan. -+@@ -1819,6 +1819,9 @@ enum nl80211_commands { -+ * -+ * @NL80211_ATTR_PAD: attribute used for padding for 64-bit alignment ++@@ -1829,6 +1829,9 @@ enum nl80211_commands { ++ * %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per ++ * interface type. * + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce + * transmit power to stay within regulatory limits. u32, dBi. @@ -6760,9 +9879,9 @@ index e151a12..28f5dcc 100644 -@@ -2164,6 +2167,8 @@ enum nl80211_attrs { - NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS, - NL80211_ATTR_SCHED_SCAN_PLANS, -+@@ -2201,6 +2204,8 @@ enum nl80211_attrs { ++@@ -2213,6 +2216,8 @@ enum nl80211_attrs { + -+ NL80211_ATTR_PAD, ++ NL80211_ATTR_IFTYPE_EXT_CAPA, + NL80211_ATTR_WIPHY_ANTENNA_GAIN, + @@ -6789,7 +9908,7 @@ index e151a12..28f5dcc 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -1318,6 +1318,7 @@ struct ieee80211_local { -+@@ -1322,6 +1322,7 @@ struct ieee80211_local { ++@@ -1338,6 +1338,7 @@ struct ieee80211_local { int dynamic_ps_forced_timeout; int user_power_level; /* in dBm, for all interfaces */ @@ -6810,7 +9929,7 @@ index e151a12..28f5dcc 100644 - [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 }, - [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 }, - [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG }, -+@@ -406,6 +406,7 @@ static const struct nla_policy nl80211_p ++@@ -407,6 +407,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_PBSS] = { .type = NLA_FLAG }, + [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED }, + [NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 }, @@ -6819,19 +9938,18 @@ index e151a12..28f5dcc 100644 /* policy for the key attributes */ -@@ -2220,6 +2221,20 @@ static int nl80211_set_wiphy(struct sk_b -+@@ -2251,6 +2252,20 @@ static int nl80211_set_wiphy(struct sk_b ++@@ -2294,6 +2295,20 @@ static int nl80211_set_wiphy(struct sk_b if (result) return result; } diff --git a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch -index 5a5e464..6001266 100644 +index 5a5e464..0b25749 100644 --- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch +++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch @@ -1,16 +1,16 @@ --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h --@@ -814,6 +814,9 @@ static inline int ath9k_dump_btcoex(stru -+@@ -813,6 +813,9 @@ static inline int ath9k_dump_btcoex(stru + @@ -814,6 +814,9 @@ static inline int ath9k_dump_btcoex(stru + #ifdef CPTCFG_MAC80211_LEDS void ath_init_leds(struct ath_softc *sc); void ath_deinit_leds(struct ath_softc *sc); @@ -6844,7 +9962,7 @@ index 5a5e464..6001266 100644 static inline void ath_init_leds(struct ath_softc *sc) { -@@ -953,6 +956,13 @@ void ath_ant_comb_scan(struct ath_softc -+@@ -949,6 +952,13 @@ void ath_ant_comb_scan(struct ath_softc ++@@ -950,6 +953,13 @@ void ath_ant_comb_scan(struct ath_softc #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ @@ -6853,7 +9971,7 @@ index 5a5e464..6001266 100644 struct ieee80211_hw *hw; struct device *dev; -@@ -1005,9 +1015,8 @@ struct ath_softc { -+@@ -1001,9 +1011,8 @@ struct ath_softc { ++@@ -1002,9 +1012,8 @@ struct ath_softc { spinlock_t chan_lock; #ifdef CPTCFG_MAC80211_LEDS @@ -7005,7 +10123,7 @@ index 5a5e464..6001266 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c -@@ -1393,6 +1393,61 @@ static const struct file_operations fops -+@@ -1411,6 +1411,61 @@ static const struct file_operations fops ++@@ -1407,6 +1407,61 @@ static const struct file_operations fops .llseek = default_llseek, }; @@ -7014,7 +10132,7 @@ index 5a5e464..6001266 100644 int ath9k_init_debug(struct ath_hw *ah) { -@@ -1417,6 +1472,10 @@ int ath9k_init_debug(struct ath_hw *ah) -+@@ -1435,6 +1490,10 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1431,6 +1486,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); @@ -7070,7 +10188,7 @@ index 7c10ea6..f656697 100644 - void ath_fill_led_pin(struct ath_softc *sc) diff --git a/package/kernel/mac80211/patches/532-ath9k_get_led_polarity_from_platform_data.patch b/package/kernel/mac80211/patches/532-ath9k_get_led_polarity_from_platform_data.patch -index 6d62a2b..986f155 100644 +index 6d62a2b..50d8a7a 100644 --- a/package/kernel/mac80211/patches/532-ath9k_get_led_polarity_from_platform_data.patch +++ b/package/kernel/mac80211/patches/532-ath9k_get_led_polarity_from_platform_data.patch @@ -1,6 +1,6 @@ @@ -7086,36 +10204,40 @@ index 6d62a2b..986f155 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -577,6 +577,7 @@ static int ath9k_init_softc(u16 devid, s -+@@ -581,6 +581,7 @@ static int ath9k_init_softc(u16 devid, s ++@@ -580,6 +580,7 @@ static int ath9k_init_softc(u16 devid, s ah->external_reset = pdata->external_reset; ah->disable_2ghz = pdata->disable_2ghz; ah->disable_5ghz = pdata->disable_5ghz; -diff --git a/package/kernel/mac80211/patches/533-mac80211_correct_4addr_skbsize.patch b/package/kernel/mac80211/patches/533-mac80211_correct_4addr_skbsize.patch -new file mode 100644 -index 0000000..afd8cca ---- /dev/null -+++ b/package/kernel/mac80211/patches/533-mac80211_correct_4addr_skbsize.patch -@@ -0,0 +1,11 @@ -+--- a/net/wireless/util.c -++++ b/net/wireless/util.c -+@@ -509,7 +509,7 @@ static int __ieee80211_data_to_8023(stru -+ * replace EtherType */ -+ hdrlen += ETH_ALEN + 2; -+ else -+- tmp.h_proto = htons(skb->len); -++ tmp.h_proto = htons(skb->len - hdrlen); -+ -+ pskb_pull(skb, hdrlen); -+ +diff --git a/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch b/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch +index 3c5e9f5..c2d2781 100644 +--- a/package/kernel/mac80211/patches/541-ath9k_rx_dma_stop_check.patch ++++ b/package/kernel/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 +-@@ -695,7 +695,7 @@ bool ath9k_hw_stopdmarecv(struct ath_hw ++@@ -698,7 +698,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 */ +-@@ -725,6 +725,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw ++@@ -728,6 +728,16 @@ bool ath9k_hw_stopdmarecv(struct ath_hw + } + + if (i == 0) { diff --git a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch -index e83c6bf..f4bb0f2 100644 +index e83c6bf..4615643 100644 --- a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch +++ b/package/kernel/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 -@@ -1449,6 +1449,50 @@ static const struct file_operations fops -+@@ -1467,6 +1467,50 @@ static const struct file_operations fops ++@@ -1463,6 +1463,50 @@ static const struct file_operations fops #endif @@ -7124,7 +10246,7 @@ index e83c6bf..f4bb0f2 100644 { struct ath_common *common = ath9k_hw_common(ah); -@@ -1476,6 +1520,8 @@ int ath9k_init_debug(struct ath_hw *ah) -+@@ -1494,6 +1538,8 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1490,6 +1534,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 @@ -7151,7 +10273,7 @@ index e83c6bf..f4bb0f2 100644 bool htc_reset_init; -@@ -1066,6 +1074,7 @@ void ath9k_hw_check_nav(struct ath_hw *a -+@@ -1067,6 +1075,7 @@ void ath9k_hw_check_nav(struct ath_hw *a ++@@ -1068,6 +1076,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); @@ -7160,7 +10282,7 @@ index e83c6bf..f4bb0f2 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1819,6 +1819,20 @@ u32 ath9k_hw_get_tsf_offset(struct times -+@@ -1821,6 +1821,20 @@ u32 ath9k_hw_get_tsf_offset(struct times ++@@ -1841,6 +1841,20 @@ u32 ath9k_hw_get_tsf_offset(struct times } EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); @@ -7169,12 +10291,12 @@ index e83c6bf..f4bb0f2 100644 struct ath9k_hw_cal_data *caldata, bool fastcc) { -@@ -2027,6 +2041,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st -+@@ -2029,6 +2043,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++@@ -2049,6 +2063,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st ar9003_hw_disable_phy_restart(ah); ath9k_hw_apply_gpio_override(ah); diff --git a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch -index d7bb5a1..7da7165 100644 +index d7bb5a1..656ed43 100644 --- a/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch +++ b/package/kernel/mac80211/patches/543-ath9k_entropy_from_adc.patch @@ -1,6 +1,6 @@ @@ -7217,7 +10339,7 @@ index d7bb5a1..7da7165 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c -@@ -711,7 +711,8 @@ static void ath9k_init_txpower_limits(st -+@@ -717,7 +717,8 @@ static void ath9k_init_txpower_limits(st ++@@ -716,7 +716,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); + ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ); @@ -7260,16 +10382,46 @@ index d7bb5a1..7da7165 100644 if (ret) return ret; +@@ -175,7 +175,7 @@ + #define AR_PHY_TIMING2 0x9810 + #define AR_PHY_TIMING3 0x9814 + #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 +-@@ -390,6 +399,8 @@ ++@@ -393,6 +402,8 @@ + #define AR_PHY_RFBUS_GRANT 0x9C20 + #define AR_PHY_RFBUS_GRANT_EN 0x00000001 + diff --git a/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch -index 8768c5d..9462fca 100644 +index 8768c5d..b9c962e 100644 --- a/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch +++ b/package/kernel/mac80211/patches/544-ath9k-ar933x-usb-hang-workaround.patch +@@ -20,9 +20,9 @@ + /******************/ + /* Chip Revisions */ + /******************/ +-@@ -1397,6 +1410,9 @@ static bool ath9k_hw_set_reset(struct at +- if (AR_SREV_9100(ah)) ++@@ -1417,6 +1430,9 @@ static bool ath9k_hw_set_reset(struct at + udelay(50); ++ } + + + if (AR_SREV_9330(ah) || AR_SREV_9340(ah)) + + ath9k_hw_disable_pll_lock_detect(ah); +@@ -30,7 +30,7 @@ + return true; + } + +-@@ -1496,6 +1512,9 @@ static bool ath9k_hw_chip_reset(struct a ++@@ -1516,6 +1532,9 @@ static bool ath9k_hw_chip_reset(struct a + ar9003_hw_internal_regulator_apply(ah); + ath9k_hw_init_pll(ah, chan); + @@ -40,7 +40,7 @@ return true; } -@@ -1797,8 +1816,14 @@ static int ath9k_hw_do_fastcc(struct ath -+@@ -1799,8 +1818,14 @@ static int ath9k_hw_do_fastcc(struct ath ++@@ -1819,8 +1838,14 @@ static int ath9k_hw_do_fastcc(struct ath if (AR_SREV_9271(ah)) ar9002_hw_load_ani_reg(ah, chan); @@ -7278,7 +10430,7 @@ index 8768c5d..9462fca 100644 } -@@ -2052,6 +2077,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st -+@@ -2054,6 +2079,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++@@ -2074,6 +2099,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st ath9k_hw_set_radar_params(ah); } @@ -7403,10 +10555,10 @@ index 0000000..5d84cf0 + } diff --git a/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch new file mode 100644 -index 0000000..1c89e42 +index 0000000..de7c0ac --- /dev/null +++ b/package/kernel/mac80211/patches/548-ath9k_enable_gpio_chip.patch -@@ -0,0 +1,237 @@ +@@ -0,0 +1,234 @@ +From: Michal Cieslakiewicz +Date: Sun, 31 Jan 2016 21:01:31 +0100 +Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO @@ -7427,7 +10579,7 @@ index 0000000..1c89e42 + + #include "common.h" + #include "debug.h" -+@@ -959,6 +960,14 @@ struct ath_led { ++@@ -960,6 +961,14 @@ struct ath_led { + struct led_classdev cdev; + }; + @@ -7442,7 +10594,7 @@ index 0000000..1c89e42 + struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; -+@@ -1013,6 +1022,9 @@ struct ath_softc { ++@@ -1014,6 +1023,9 @@ struct ath_softc { + #ifdef CPTCFG_MAC80211_LEDS + const char *led_default_trigger; + struct list_head leds; @@ -7454,7 +10606,7 @@ index 0000000..1c89e42 + #ifdef CPTCFG_ATH9K_DEBUGFS +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c -+@@ -16,13 +16,138 @@ ++@@ -16,13 +16,135 @@ + + #include "ath9k.h" + #include @@ -7526,15 +10678,7 @@ index 0000000..1c89e42 ++static void ath9k_register_gpio_chip(struct ath_softc *sc) ++{ ++ struct ath9k_gpio_chip *gc; -++ u16 ng; -++ -++ /* for now only AR9285 and AR9287 are recognized */ -++ if (AR_SREV_9287(sc->sc_ah)) -++ ng = AR9287_NUM_GPIO; -++ else if (AR_SREV_9285(sc->sc_ah)) -++ ng = AR9285_NUM_GPIO; -++ else -++ return; +++ struct ath_hw *ah = sc->sc_ah; ++ ++ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL); ++ if (!gc) @@ -7542,21 +10686,26 @@ index 0000000..1c89e42 ++ ++ snprintf(gc->label, sizeof(gc->label), "ath9k-%s", ++ wiphy_name(sc->hw->wiphy)); +++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) +++ gc->gchip.parent = sc->dev; +++#else +++ gc->gchip.dev = sc->dev; +++#endif ++ gc->gchip.label = gc->label; ++ gc->gchip.base = -1; /* determine base automatically */ -++ gc->gchip.ngpio = ng; +++ gc->gchip.ngpio = ah->caps.num_gpio_pins; ++ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input; ++ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output; ++ gc->gchip.get_direction = ath9k_gpio_pin_get_dir; ++ gc->gchip.get = ath9k_gpio_pin_get; ++ gc->gchip.set = ath9k_gpio_pin_set; -++ gc->gchip.owner = THIS_MODULE; ++ ++ if (gpiochip_add(&gc->gchip)) { ++ kfree(gc); ++ return; ++ } ++ +++ gc->gchip.owner = NULL; ++ sc->gpiochip = gc; ++ gc->sc = sc; ++} @@ -7595,7 +10744,7 @@ index 0000000..1c89e42 + static void ath_fill_led_pin(struct ath_softc *sc) + { + struct ath_hw *ah = sc->sc_ah; -+@@ -80,6 +205,12 @@ static int ath_add_led(struct ath_softc ++@@ -80,6 +202,12 @@ static int ath_add_led(struct ath_softc + else + ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); + @@ -7608,7 +10757,7 @@ index 0000000..1c89e42 + return 0; + } + -+@@ -136,12 +267,18 @@ void ath_deinit_leds(struct ath_softc *s ++@@ -136,12 +264,18 @@ void ath_deinit_leds(struct ath_softc *s + + while (!list_empty(&sc->leds)) { + led = list_first_entry(&sc->leds, struct ath_led, list); @@ -7627,7 +10776,7 @@ index 0000000..1c89e42 + } + + void ath_init_leds(struct ath_softc *sc) -+@@ -158,6 +295,8 @@ void ath_init_leds(struct ath_softc *sc) ++@@ -158,6 +292,8 @@ void ath_init_leds(struct ath_softc *sc) + + ath_fill_led_pin(sc); + @@ -7636,7 +10785,7 @@ index 0000000..1c89e42 + if (pdata && pdata->led_name) + strncpy(led_name, pdata->led_name, sizeof(led_name)); + else -+@@ -178,6 +317,7 @@ void ath_init_leds(struct ath_softc *sc) ++@@ -178,6 +314,7 @@ void ath_init_leds(struct ath_softc *sc) + for (i = 0; i < pdata->num_leds; i++) + ath_create_platform_led(sc, &pdata->leds[i]); + } @@ -7646,7 +10795,7 @@ index 0000000..1c89e42 + /*******************/ diff --git a/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch new file mode 100644 -index 0000000..c7973bb +index 0000000..b9d1883 --- /dev/null +++ b/package/kernel/mac80211/patches/549-ath9k_enable_gpio_buttons.patch @@ -0,0 +1,149 @@ @@ -7662,7 +10811,7 @@ index 0000000..c7973bb +--- +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h -+@@ -1024,6 +1024,7 @@ struct ath_softc { ++@@ -1025,6 +1025,7 @@ struct ath_softc { + struct list_head leds; + #ifdef CONFIG_GPIOLIB + struct ath9k_gpio_chip *gpiochip; @@ -7681,7 +10830,7 @@ index 0000000..c7973bb + + #ifdef CPTCFG_MAC80211_LEDS + -+@@ -132,6 +134,64 @@ static void ath9k_unregister_gpio_chip(s ++@@ -129,6 +131,64 @@ static void ath9k_unregister_gpio_chip(s + sc->gpiochip = NULL; + } + @@ -7746,7 +10895,7 @@ index 0000000..c7973bb + #else /* CONFIG_GPIOLIB */ + + static inline void ath9k_register_gpio_chip(struct ath_softc *sc) -+@@ -142,6 +202,14 @@ static inline void ath9k_unregister_gpio ++@@ -139,6 +199,14 @@ static inline void ath9k_unregister_gpio + { + } + @@ -7761,7 +10910,7 @@ index 0000000..c7973bb + #endif /* CONFIG_GPIOLIB */ + + /********************************/ -+@@ -265,6 +333,7 @@ void ath_deinit_leds(struct ath_softc *s ++@@ -262,6 +330,7 @@ void ath_deinit_leds(struct ath_softc *s + { + struct ath_led *led; + @@ -7769,7 +10918,7 @@ index 0000000..c7973bb + while (!list_empty(&sc->leds)) { + led = list_first_entry(&sc->leds, struct ath_led, list); + #ifdef CONFIG_GPIOLIB -+@@ -296,6 +365,7 @@ void ath_init_leds(struct ath_softc *sc) ++@@ -293,6 +362,7 @@ void ath_init_leds(struct ath_softc *sc) + ath_fill_led_pin(sc); + + ath9k_register_gpio_chip(sc); @@ -7777,7 +10926,7 @@ index 0000000..c7973bb + + if (pdata && pdata->led_name) + strncpy(led_name, pdata->led_name, sizeof(led_name)); -+@@ -311,7 +381,7 @@ void ath_init_leds(struct ath_softc *sc) ++@@ -308,7 +378,7 @@ void ath_init_leds(struct ath_softc *sc) + ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, + !sc->sc_ah->config.led_active_high); + @@ -7799,39 +10948,6 @@ index 0000000..c7973bb + }; + + #endif /* _LINUX_ATH9K_PLATFORM_H */ -diff --git a/package/kernel/mac80211/patches/550-ath9k_add_ar9280_gpio_chip.patch b/package/kernel/mac80211/patches/550-ath9k_add_ar9280_gpio_chip.patch -new file mode 100644 -index 0000000..22e2c66 ---- /dev/null -+++ b/package/kernel/mac80211/patches/550-ath9k_add_ar9280_gpio_chip.patch -@@ -0,0 +1,27 @@ -+From: Michal Cieslakiewicz -+Date: Thu, 21 Apr 2016 23:00:54 +0200 -+Subject: [PATCH] mac80211: ath9k: add GPIO support for AR9280 chip -+ -+Enable access to GPIO on Atheros wireless chip AR9280. -+Support for 9280 is added to existing 9285/9287 subsystem -+because these 3 chips differ only in number of GPIO pins. -+ -+Signed-off-by: Michal Cieslakiewicz -+--- -+--- a/drivers/net/wireless/ath/ath9k/gpio.c -++++ b/drivers/net/wireless/ath/ath9k/gpio.c -+@@ -88,11 +88,13 @@ static void ath9k_register_gpio_chip(str -+ struct ath9k_gpio_chip *gc; -+ u16 ng; -+ -+- /* for now only AR9285 and AR9287 are recognized */ -++ /* supported chips are AR9280, AR9285 and AR9287 */ -+ if (AR_SREV_9287(sc->sc_ah)) -+ ng = AR9287_NUM_GPIO; -+ else if (AR_SREV_9285(sc->sc_ah)) -+ ng = AR9285_NUM_GPIO; -++ else if (AR_SREV_9280(sc->sc_ah)) -++ ng = AR9280_NUM_GPIO; -+ else -+ return; -+ diff --git a/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch b/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch index 8245909..db70a33 100644 --- a/package/kernel/mac80211/patches/600-0002-rt2x00-rt2800lib-introduce-RT2800_HAS_HIGH_SHARED_ME.patch @@ -8224,15 +11340,42 @@ index 74cd448..0000000 - #endif - #ifdef CPTCFG_B43_SSB diff --git a/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch b/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch -index 06c731f..b60ef76 100644 +index 06c731f..f8f555f 100644 --- a/package/kernel/mac80211/patches/820-b43-add-antenna-control.patch +++ b/package/kernel/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. */ +-@@ -3300,8 +3300,8 @@ static int b43_chip_init(struct b43_wlde ++@@ -3297,8 +3297,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); +-@@ -4001,7 +4001,6 @@ static int b43_op_config(struct ieee8021 ++@@ -3998,7 +3998,6 @@ static int b43_op_config(struct ieee8021 + struct b43_wldev *dev = wl->current_dev; + struct b43_phy *phy = &dev->phy; + struct ieee80211_conf *conf = &hw->conf; +@@ -28,7 +28,7 @@ + int err = 0; + + mutex_lock(&wl->mutex); +-@@ -4044,11 +4043,9 @@ static int b43_op_config(struct ieee8021 ++@@ -4041,11 +4040,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) { -@@ -5209,6 +5206,47 @@ static int b43_op_get_survey(struct ieee -+@@ -5207,6 +5204,47 @@ static int b43_op_get_survey(struct ieee ++@@ -5189,6 +5186,47 @@ static int b43_op_get_survey(struct ieee return 0; } @@ -8241,7 +11384,7 @@ index 06c731f..b60ef76 100644 .tx = b43_op_tx, .conf_tx = b43_op_conf_tx, -@@ -5230,6 +5268,8 @@ static const struct ieee80211_ops b43_hw -+@@ -5228,6 +5266,8 @@ static const struct ieee80211_ops b43_hw ++@@ -5210,6 +5248,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, @@ -8250,7 +11393,7 @@ index 06c731f..b60ef76 100644 /* Hard-reset the chip. Do not call this directly. -@@ -5538,6 +5578,8 @@ static int b43_one_core_attach(struct b4 -+@@ -5536,6 +5576,8 @@ static int b43_one_core_attach(struct b4 ++@@ -5513,6 +5553,8 @@ static int b43_one_core_attach(struct b4 if (!wldev) goto out; @@ -8259,84 +11402,277 @@ index 06c731f..b60ef76 100644 wldev->dev = dev; wldev->wl = wl; -@@ -5628,6 +5670,9 @@ static struct b43_wl *b43_wireless_init( -+@@ -5626,6 +5668,9 @@ static struct b43_wl *b43_wireless_init( ++@@ -5603,6 +5645,9 @@ static struct b43_wl *b43_wireless_init( hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; -diff --git a/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch b/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch +diff --git a/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch new file mode 100644 -index 0000000..46227c4 +index 0000000..ae571c9 --- /dev/null -+++ b/package/kernel/mac80211/patches/860-brcmfmac-add-missing-eth_type_trans-call.patch -@@ -0,0 +1,26 @@ ++++ b/package/kernel/mac80211/patches/860-brcmfmac-register-wiphy-s-during-module_init.patch +@@ -0,0 +1,97 @@ +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= -+Subject: [PATCH] brcmfmac: add missing eth_type_trans call ++Date: Mon, 8 Jun 2015 16:11:40 +0200 ++Subject: [PATCH] brcmfmac: register wiphy(s) during module_init +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + -+There are 2 protocols supported by brcmfmac and msgbuf one was missing a -+proper skb setup before passing it to the netif. This was triggering -+"NULL pointer dereference". ++This is needed by OpenWrt which expects all PHYs to be created after ++module loads successfully. + -+Fixes: 9c349892ccc9 ("brcmfmac: revise handling events in receive path") +Signed-off-by: Rafał Miłecki +--- + -+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c -++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c -+@@ -1157,6 +1157,9 @@ brcmf_msgbuf_process_rx_complete(struct -+ brcmu_pkt_buf_free_skb(skb); -+ return; -+ } -++ -++ skb->protocol = eth_type_trans(skb, ifp->ndev); -++ -+ brcmf_netif_rx(ifp, skb); ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++@@ -1213,6 +1213,7 @@ int __init brcmf_core_init(void) ++ { ++ if (!schedule_work(&brcmf_driver_work)) ++ return -EBUSY; +++ flush_work(&brcmf_driver_work); ++ ++ return 0; ++ } ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c ++@@ -444,6 +444,7 @@ struct brcmf_fw { ++ u16 bus_nr; ++ void (*done)(struct device *dev, const struct firmware *fw, ++ void *nvram_image, u32 nvram_len); +++ struct completion *completion; ++ }; ++ ++ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) ++@@ -478,6 +479,8 @@ static void brcmf_fw_request_nvram_done( ++ goto fail; ++ ++ fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length); +++ if (fwctx->completion) +++ complete(fwctx->completion); ++ kfree(fwctx); ++ return; ++ ++@@ -485,6 +488,8 @@ fail: ++ brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); ++ release_firmware(fwctx->code); ++ device_release_driver(fwctx->dev); +++ if (fwctx->completion) +++ complete(fwctx->completion); ++ kfree(fwctx); + } + ++@@ -500,6 +505,8 @@ static void brcmf_fw_request_code_done(c ++ /* only requested code so done here */ ++ if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) { ++ fwctx->done(fwctx->dev, fw, NULL, 0); +++ if (fwctx->completion) +++ complete(fwctx->completion); ++ kfree(fwctx); ++ return; ++ } ++@@ -517,6 +524,8 @@ static void brcmf_fw_request_code_done(c ++ fail: ++ brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); ++ device_release_driver(fwctx->dev); +++ if (fwctx->completion) +++ complete(fwctx->completion); ++ kfree(fwctx); ++ } ++ ++@@ -528,6 +537,8 @@ int brcmf_fw_get_firmwares_pcie(struct d ++ u16 domain_nr, u16 bus_nr) ++ { ++ struct brcmf_fw *fwctx; +++ struct completion completion; +++ int err; ++ ++ brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); ++ if (!fw_cb || !code) ++@@ -548,9 +559,17 @@ int brcmf_fw_get_firmwares_pcie(struct d ++ fwctx->domain_nr = domain_nr; ++ fwctx->bus_nr = bus_nr; ++ ++- return request_firmware_nowait(THIS_MODULE, true, code, dev, +++ init_completion(&completion); +++ fwctx->completion = &completion; +++ +++ err = request_firmware_nowait(THIS_MODULE, true, code, dev, ++ GFP_KERNEL, fwctx, ++ brcmf_fw_request_code_done); +++ if (!err) +++ wait_for_completion_timeout(fwctx->completion, +++ msecs_to_jiffies(5000)); +++ fwctx->completion = NULL; +++ return err; ++ } ++ ++ int brcmf_fw_get_firmwares(struct device *dev, u16 flags, diff --git a/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch -index 00181f6..8cf9ea2 100644 +deleted file mode 100644 +index 00181f6..0000000 --- a/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch -+++ b/package/kernel/mac80211/patches/861-brcmfmac-register-wiphy-s-during-module_init.patch -@@ -13,8 +13,8 @@ Signed-off-by: Rafał Miłecki - - --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c - +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ /dev/null +@@ -1,97 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Mon, 8 Jun 2015 16:11:40 +0200 +-Subject: [PATCH] brcmfmac: register wiphy(s) during module_init +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-This is needed by OpenWrt which expects all PHYs to be created after +-module loads successfully. +- +-Signed-off-by: Rafał Miłecki +---- +- +---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -1332,6 +1332,7 @@ static int __init brcmfmac_module_init(v - #endif -+@@ -1232,6 +1232,7 @@ int __init brcmf_core_init(void) -+ { - if (!schedule_work(&brcmf_driver_work)) - return -EBUSY; - + flush_work(&brcmf_driver_work); -diff --git a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch -index 4295b4b..4f22a4e 100644 ---- a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch -+++ b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch -@@ -10,7 +10,7 @@ Signed-off-by: Rafał Miłecki - - --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c - +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c --@@ -615,9 +615,37 @@ static struct wireless_dev *brcmf_cfg802 -+@@ -650,9 +650,37 @@ static struct wireless_dev *brcmf_cfg802 - u32 *flags, - struct vif_params *params) - { -@@ -42,7 +42,7 @@ Signed-off-by: Rafał Miłecki - + dev = dev_get_by_name(&init_net, name); - + if (dev) { - + dev_put(dev); --+ return ERR_PTR(-EEXIST); -++ return ERR_PTR(-ENFILE); - + } - + - brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); -diff --git a/package/kernel/mac80211/patches/863-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/863-brcmfmac-Disable-power-management.patch +- if (!schedule_work(&brcmf_driver_work)) +- return -EBUSY; +-+ flush_work(&brcmf_driver_work); +- +- return 0; +- } +---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +-@@ -444,6 +444,7 @@ struct brcmf_fw { +- u16 bus_nr; +- void (*done)(struct device *dev, const struct firmware *fw, +- void *nvram_image, u32 nvram_len); +-+ struct completion *completion; +- }; +- +- static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) +-@@ -478,6 +479,8 @@ static void brcmf_fw_request_nvram_done( +- goto fail; +- +- fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length); +-+ if (fwctx->completion) +-+ complete(fwctx->completion); +- kfree(fwctx); +- return; +- +-@@ -485,6 +488,8 @@ fail: +- brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); +- release_firmware(fwctx->code); +- device_release_driver(fwctx->dev); +-+ if (fwctx->completion) +-+ complete(fwctx->completion); +- kfree(fwctx); +- } +- +-@@ -500,6 +505,8 @@ static void brcmf_fw_request_code_done(c +- /* only requested code so done here */ +- if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) { +- fwctx->done(fwctx->dev, fw, NULL, 0); +-+ if (fwctx->completion) +-+ complete(fwctx->completion); +- kfree(fwctx); +- return; +- } +-@@ -517,6 +524,8 @@ static void brcmf_fw_request_code_done(c +- fail: +- brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); +- device_release_driver(fwctx->dev); +-+ if (fwctx->completion) +-+ complete(fwctx->completion); +- kfree(fwctx); +- } +- +-@@ -528,6 +537,8 @@ int brcmf_fw_get_firmwares_pcie(struct d +- u16 domain_nr, u16 bus_nr) +- { +- struct brcmf_fw *fwctx; +-+ struct completion completion; +-+ int err; +- +- brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); +- if (!fw_cb || !code) +-@@ -548,9 +559,17 @@ int brcmf_fw_get_firmwares_pcie(struct d +- fwctx->domain_nr = domain_nr; +- fwctx->bus_nr = bus_nr; +- +-- return request_firmware_nowait(THIS_MODULE, true, code, dev, +-+ init_completion(&completion); +-+ fwctx->completion = &completion; +-+ +-+ err = request_firmware_nowait(THIS_MODULE, true, code, dev, +- GFP_KERNEL, fwctx, +- brcmf_fw_request_code_done); +-+ if (!err) +-+ wait_for_completion_timeout(fwctx->completion, +-+ msecs_to_jiffies(5000)); +-+ fwctx->completion = NULL; +-+ return err; +- } +- +- int brcmf_fw_get_firmwares(struct device *dev, u16 flags, +diff --git a/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch new file mode 100644 -index 0000000..f971bb7 +index 0000000..8721155 --- /dev/null -+++ b/package/kernel/mac80211/patches/863-brcmfmac-Disable-power-management.patch ++++ b/package/kernel/mac80211/patches/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch +@@ -0,0 +1,50 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Thu, 9 Jul 2015 00:07:59 +0200 ++Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Signed-off-by: Rafał Miłecki ++--- ++ ++--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++@@ -665,9 +665,37 @@ static struct wireless_dev *brcmf_cfg802 ++ u32 *flags, ++ struct vif_params *params) ++ { +++ struct net_device *dev; ++ struct wireless_dev *wdev; ++ int err; ++ +++ /* +++ * There is a bug with in-firmware BSS management. When adding virtual +++ * interface brcmfmac first tells firmware to create new BSS and then +++ * it creates new struct net_device. +++ * +++ * If creating/registering netdev(ice) fails, BSS remains in some bugged +++ * state. It conflicts with existing BSSes by overtaking their auth +++ * requests. +++ * +++ * It results in one BSS (addresss X) sending beacons and another BSS +++ * (address Y) replying to authentication requests. This makes interface +++ * unusable as AP. +++ * +++ * To workaround this bug we may try to guess if register_netdev(ice) +++ * will fail. The most obvious case is using interface name that already +++ * exists. This is actually quite likely with brcmfmac & some user space +++ * scripts as brcmfmac doesn't allow deleting virtual interfaces. +++ * So this bug can be triggered even by something trivial like: +++ * iw dev wlan0 delete +++ * iw phy phy0 interface add wlan0 type __ap +++ */ +++ dev = dev_get_by_name(&init_net, name); +++ if (dev) { +++ dev_put(dev); +++ return ERR_PTR(-ENFILE); +++ } +++ ++ brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); ++ err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); ++ if (err) { +diff --git a/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch +new file mode 100644 +index 0000000..f301fe1 +--- /dev/null ++++ b/package/kernel/mac80211/patches/862-brcmfmac-Disable-power-management.patch @@ -0,0 +1,27 @@ +From 66ae1b1750720a33e29792a177b1e696f4f005fb Mon Sep 17 00:00:00 2001 +From: Phil Elwell @@ -8354,7 +11690,7 @@ index 0000000..f971bb7 + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -+@@ -2711,6 +2711,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip ++@@ -2783,6 +2783,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip + * preference in cfg struct to apply this to + * FW later while initializing the dongle + */ @@ -8365,6 +11701,62 @@ index 0000000..f971bb7 + cfg->pwr_save = enabled; + if (!check_vif_up(ifp->vif)) { + +diff --git a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch +deleted file mode 100644 +index 4295b4b..0000000 +--- a/package/kernel/mac80211/patches/862-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch ++++ /dev/null +@@ -1,50 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Thu, 9 Jul 2015 00:07:59 +0200 +-Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-Signed-off-by: Rafał Miłecki +---- +- +---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +-@@ -615,9 +615,37 @@ static struct wireless_dev *brcmf_cfg802 +- u32 *flags, +- struct vif_params *params) +- { +-+ struct net_device *dev; +- struct wireless_dev *wdev; +- int err; +- +-+ /* +-+ * There is a bug with in-firmware BSS management. When adding virtual +-+ * interface brcmfmac first tells firmware to create new BSS and then +-+ * it creates new struct net_device. +-+ * +-+ * If creating/registering netdev(ice) fails, BSS remains in some bugged +-+ * state. It conflicts with existing BSSes by overtaking their auth +-+ * requests. +-+ * +-+ * It results in one BSS (addresss X) sending beacons and another BSS +-+ * (address Y) replying to authentication requests. This makes interface +-+ * unusable as AP. +-+ * +-+ * To workaround this bug we may try to guess if register_netdev(ice) +-+ * will fail. The most obvious case is using interface name that already +-+ * exists. This is actually quite likely with brcmfmac & some user space +-+ * scripts as brcmfmac doesn't allow deleting virtual interfaces. +-+ * So this bug can be triggered even by something trivial like: +-+ * iw dev wlan0 delete +-+ * iw phy phy0 interface add wlan0 type __ap +-+ */ +-+ dev = dev_get_by_name(&init_net, name); +-+ if (dev) { +-+ dev_put(dev); +-+ return ERR_PTR(-EEXIST); +-+ } +-+ +- brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); +- err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); +- if (err) { diff --git a/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch b/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch index f2e21ea..be210f2 100644 --- a/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch @@ -8388,7 +11780,7 @@ index f2e21ea..be210f2 100644 case RF5390: case RF5392: diff --git a/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch -index 8c6d720..9322b45 100644 +index 8c6d720..e842d61 100644 --- a/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch +++ b/package/kernel/mac80211/patches/921-ath10k_init_devices_synchronously.patch @@ -14,7 +14,7 @@ Signed-off-by: Sven Eckelmann @@ -8396,40 +11788,45 @@ index 8c6d720..9322b45 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c -@@ -1914,6 +1914,16 @@ int ath10k_core_register(struct ath10k * -+@@ -2012,6 +2012,16 @@ int ath10k_core_register(struct ath10k * ++@@ -2107,6 +2107,16 @@ int ath10k_core_register(struct ath10k * ar->chip_id = chip_id; queue_work(ar->workqueue, &ar->register_work); diff --git a/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch -index 281b447..1bfded0 100644 +index 281b447..a501b99 100644 --- a/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch +++ b/package/kernel/mac80211/patches/930-ath10k_add_tpt_led_trigger.patch @@ -1,6 +1,6 @@ --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c -@@ -7141,6 +7141,21 @@ struct ath10k_vif *ath10k_get_arvif(stru -+@@ -7717,6 +7717,21 @@ struct ath10k_vif *ath10k_get_arvif(stru ++@@ -7742,6 +7742,21 @@ struct ath10k_vif *ath10k_get_arvif(stru return arvif_iter.arvif; } -@@ -22,7 +22,7 @@ +@@ -22,11 +22,11 @@ int ath10k_mac_register(struct ath10k *ar) { static const u32 cipher_suites[] = { -@@ -7357,6 +7372,12 @@ int ath10k_mac_register(struct ath10k *a -+@@ -7941,6 +7956,12 @@ int ath10k_mac_register(struct ath10k *a ++@@ -7975,6 +7990,12 @@ int ath10k_mac_register(struct ath10k *a ar->hw->wiphy->cipher_suites = cipher_suites; ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); +-+#if CPTCFG_MAC80211_LEDS +++#ifdef CPTCFG_MAC80211_LEDS + + ieee80211_create_tpt_led_trigger(ar->hw, + + IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink, + + ARRAY_SIZE(ath10k_tpt_blink)); diff --git a/package/kernel/mac80211/patches/936-ath10k_skip_otp_check.patch b/package/kernel/mac80211/patches/936-ath10k_skip_otp_check.patch new file mode 100644 -index 0000000..7f51dd2 +index 0000000..596ef98 --- /dev/null +++ b/package/kernel/mac80211/patches/936-ath10k_skip_otp_check.patch -@@ -0,0 +1,42 @@ +@@ -0,0 +1,51 @@ +--- a/drivers/net/wireless/ath/ath10k/core.c ++++ b/drivers/net/wireless/ath/ath10k/core.c -+@@ -1168,9 +1168,6 @@ static int ath10k_core_fetch_firmware_fi ++@@ -1243,9 +1243,6 @@ static int ath10k_core_fetch_firmware_fi + { + int ret; + @@ -8439,17 +11836,26 @@ index 0000000..7f51dd2 + ar->fw_api = 5; + ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); + -+@@ -1873,6 +1870,9 @@ static int ath10k_core_probe_fw(struct a ++@@ -1944,7 +1941,7 @@ EXPORT_SYMBOL(ath10k_core_stop); ++ static int ath10k_core_probe_fw(struct ath10k *ar) ++ { ++ struct bmi_target_info target_info; ++- int ret = 0; +++ int calret, ret = 0; ++ ++ ret = ath10k_hif_power_up(ar); ++ if (ret) { ++@@ -1968,6 +1965,9 @@ static int ath10k_core_probe_fw(struct a + goto err_power_down; + } + ++ /* calibration file is optional, don't check for any errors */ -++ int calret = ath10k_fetch_cal_file(ar); +++ calret = ath10k_fetch_cal_file(ar); ++ + ret = ath10k_core_fetch_firmware_files(ar); + if (ret) { + ath10k_err(ar, "could not fetch firmware files (%d)\n", ret); -+@@ -1895,11 +1895,14 @@ static int ath10k_core_probe_fw(struct a ++@@ -1990,11 +1990,14 @@ static int ath10k_core_probe_fw(struct a + "could not load pre cal data: %d\n", ret); + } + @@ -8470,7 +11876,7 @@ index 0000000..7f51dd2 + + ret = ath10k_core_fetch_board_file(ar); diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile -index e49dd48..0f832e4 100644 +index e49dd48..90430b9 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -1,7 +1,7 @@ @@ -8478,7 +11884,7 @@ index e49dd48..0f832e4 100644 PKG_NAME:=mt76 -PKG_VERSION:=2016-03-03 -+PKG_VERSION:=2016-06-17 ++PKG_VERSION:=2016-07-08 PKG_RELEASE=1 PKG_LICENSE:=GPLv2 @@ -8487,7 +11893,7 @@ index e49dd48..0f832e4 100644 PKG_SOURCE_PROTO:=git PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE_VERSION:=310d420178c86e253a172413da30ecf479b64251 -+PKG_SOURCE_VERSION:=f06ed811cda67ab2ed9932c3e87ba03229e75f4e ++PKG_SOURCE_VERSION:=9226e96c40e9ae19996a262365ce764f7b0b9c4a PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz -PKG_MAINTAINER:=Felix Fietkau @@ -8529,7 +11935,7 @@ index e49dd48..0f832e4 100644 $(PKG_BUILD_DIR)/firmware/mt7662.bin \ $(1)/lib/firmware diff --git a/package/kernel/mwlwifi/Makefile b/package/kernel/mwlwifi/Makefile -index 091928d..6a59a02 100644 +index 091928d..880803e 100644 --- a/package/kernel/mwlwifi/Makefile +++ b/package/kernel/mwlwifi/Makefile @@ -8,7 +8,7 @@ @@ -8537,7 +11943,7 @@ index 091928d..6a59a02 100644 PKG_NAME:=mwlwifi -PKG_VERSION:=10.3.0.16-20160105 -+PKG_VERSION:=10.3.0.17-20160520-1 ++PKG_VERSION:=10.3.0.17-20160617 PKG_RELEASE=1 PKG_LICENSE:=ISC @@ -8546,424 +11952,133 @@ index 091928d..6a59a02 100644 PKG_SOURCE_PROTO:=git PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE_VERSION:=99d3879cc72f2a25d44fb4bee96fd84eca028b04 -+PKG_SOURCE_VERSION:=7d49296d12b44025278a52c5a26fb1b4236f320f ++PKG_SOURCE_VERSION:=b7aff3c2839b048407d716d1cb9326122ee401f8 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz PKG_MAINTAINER:=Imre Kaloz diff --git a/package/kernel/mwlwifi/patches/100-drop_old_api.patch b/package/kernel/mwlwifi/patches/100-drop_old_api.patch -index d2e149e..086edeb 100644 +deleted file mode 100644 +index d2e149e..0000000 --- a/package/kernel/mwlwifi/patches/100-drop_old_api.patch -+++ b/package/kernel/mwlwifi/patches/100-drop_old_api.patch -@@ -1,6 +1,6 @@ - --- a/main.c - +++ b/main.c ++++ /dev/null +@@ -1,92 +0,0 @@ +---- a/main.c +-+++ b/main.c -@@ -418,11 +418,7 @@ static void mwl_set_ht_caps(struct mwl_p -+@@ -423,11 +423,7 @@ static void mwl_set_ht_caps(struct mwl_p - band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; - band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; - -@@ -12,7 +12,7 @@ - band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; - --@@ -524,29 +520,16 @@ static int mwl_wl_init(struct mwl_priv * -+@@ -563,29 +559,16 @@ static int mwl_wl_init(struct mwl_priv * - hw->queues = SYSADPT_TX_WMM_QUEUES; - - /* Set rssi values to dBm */ -@@ -41,10 +41,10 @@ - -#endif - - hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; +- band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20; +- band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; - -+ hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; - --- a/dev.h - +++ b/dev.h +--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +-- hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; +--#else +- ieee80211_hw_set(hw, AMPDU_AGGREGATION); +--#endif +- band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; +- band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; +- +-@@ -524,29 +520,16 @@ static int mwl_wl_init(struct mwl_priv * +- hw->queues = SYSADPT_TX_WMM_QUEUES; +- +- /* Set rssi values to dBm */ +--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +-- hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL; +--#else +- ieee80211_hw_set(hw, SIGNAL_DBM); +- ieee80211_hw_set(hw, HAS_RATE_CONTROL); +--#endif +- +- /* Ask mac80211 not to trigger PS mode +- * based on PM bit of incoming frames. +- */ +--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +-- hw->flags |= IEEE80211_HW_AP_LINK_PS; +--#else +- ieee80211_hw_set(hw, AP_LINK_PS); +--#endif +- +--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) +-- hw->flags |= IEEE80211_HW_SUPPORTS_PER_STA_GTK | +-- IEEE80211_HW_MFP_CAPABLE; +--#else +- ieee80211_hw_set(hw, SUPPORTS_PER_STA_GTK); +- ieee80211_hw_set(hw, MFP_CAPABLE); +--#endif +- +- hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; +- +---- a/dev.h +-+++ b/dev.h -@@ -484,10 +484,6 @@ static inline struct mwl_sta *mwl_dev_ge -+@@ -506,10 +506,6 @@ static inline struct mwl_sta *mwl_dev_ge - return (struct mwl_sta *)&sta->drv_priv; - } - -@@ -57,7 +57,7 @@ - - --- a/mac80211.c - +++ b/mac80211.c +- return (struct mwl_sta *)&sta->drv_priv; +- } +- +--#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) +--#define ether_addr_copy(dst, src) memcpy(dst, src, ETH_ALEN) +--#endif +-- +- /* Defined in mac80211.c. */ +- extern const struct ieee80211_ops mwl_mac80211_ops; +- +---- a/mac80211.c +-+++ b/mac80211.c -@@ -572,19 +572,11 @@ static int mwl_mac80211_get_survey(struc -+@@ -598,19 +598,11 @@ static int mwl_mac80211_get_survey(struc - return 0; - } - +- return 0; +- } +- +--#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) +--static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, +-- struct ieee80211_vif *vif, +-- enum ieee80211_ampdu_mlme_action action, +-- struct ieee80211_sta *sta, +-- u16 tid, u16 *ssn, u8 buf_size) +--#else +- static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- enum ieee80211_ampdu_mlme_action action, +- struct ieee80211_sta *sta, +- u16 tid, u16 *ssn, u8 buf_size, bool amsdu) +--#endif +- { +- int rc = 0; +- struct mwl_priv *priv = hw->priv; +---- a/rx.c +-+++ b/rx.c +-@@ -232,10 +232,8 @@ static inline void mwl_rx_prepare_status +- status->flag |= RX_FLAG_VHT; +- if (bw == RX_RATE_INFO_HT40) +- status->flag |= RX_FLAG_40MHZ; +--#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 18, 0) +- if (bw == RX_RATE_INFO_HT80) +- status->vht_flag |= RX_VHT_FLAG_80MHZ; +--#endif +- if (gi == RX_RATE_INFO_SHORT_INTERVAL) +- status->flag |= RX_FLAG_SHORT_GI; +- status->vht_nss = (nss + 1); diff --git a/package/kernel/mwlwifi/patches/110-api_sync.patch b/package/kernel/mwlwifi/patches/110-api_sync.patch -index ed3e06a..920cb8c 100644 +deleted file mode 100644 +index ed3e06a..0000000 --- a/package/kernel/mwlwifi/patches/110-api_sync.patch -+++ b/package/kernel/mwlwifi/patches/110-api_sync.patch -@@ -1,6 +1,30 @@ - --- a/mac80211.c - +++ b/mac80211.c ++++ /dev/null +@@ -1,19 +0,0 @@ +---- a/mac80211.c +-+++ b/mac80211.c -@@ -597,10 +597,13 @@ static int mwl_mac80211_get_survey(struc -+@@ -260,12 +260,12 @@ static int mwl_mac80211_config(struct ie -+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { -+ int rate = 0; -+ -+- if (conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { -++ if (conf->chandef.chan->band == NL80211_BAND_2GHZ) { -+ mwl_fwcmd_set_apmode(hw, AP_MODE_2_4GHZ_11AC_MIXED); -+ mwl_fwcmd_set_linkadapt_cs_mode(hw, -+ LINK_CS_STATE_CONSERV); -+ rate = mwl_rates_24[0].hw_value; -+- } else if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) { -++ } else if (conf->chandef.chan->band == NL80211_BAND_5GHZ) { -+ mwl_fwcmd_set_apmode(hw, AP_MODE_11AC); -+ mwl_fwcmd_set_linkadapt_cs_mode(hw, -+ LINK_CS_STATE_AUTO); -+@@ -333,7 +333,7 @@ static void mwl_mac80211_bss_info_change -+ if (idx) -+ idx--; -+ -+- if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) -++ if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) -+ rate = mwl_rates_24[idx].hw_value; -+ else -+ rate = mwl_rates_50[idx].hw_value; -+@@ -600,10 +600,13 @@ static int mwl_mac80211_get_survey(struc - - static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, -@@ -17,3 +41,227 @@ - int rc = 0; - struct mwl_priv *priv = hw->priv; - struct mwl_ampdu_stream *stream; -+--- a/fwcmd.c -++++ b/fwcmd.c -+@@ -730,9 +730,9 @@ static int mwl_fwcmd_set_country_code(st -+ bool enable = false; -+ -+ if (b_inf->ie_country_ptr) { -+- if (bss_conf->chandef.chan->band == IEEE80211_BAND_2GHZ) -++ if (bss_conf->chandef.chan->band == NL80211_BAND_2GHZ) -+ a_band = false; -+- else if (bss_conf->chandef.chan->band == IEEE80211_BAND_5GHZ) -++ else if (bss_conf->chandef.chan->band == NL80211_BAND_5GHZ) -+ a_band = true; -+ else -+ return -EINVAL; -+@@ -1075,9 +1075,9 @@ int mwl_fwcmd_max_tx_power(struct ieee80 -+ break; -+ } -+ -+- if (channel->band == IEEE80211_BAND_2GHZ) -++ if (channel->band == NL80211_BAND_2GHZ) -+ band = FREQ_BAND_2DOT4GHZ; -+- else if (channel->band == IEEE80211_BAND_5GHZ) -++ else if (channel->band == NL80211_BAND_5GHZ) -+ band = FREQ_BAND_5GHZ; -+ -+ switch (conf->chandef.width) { -+@@ -1161,9 +1161,9 @@ int mwl_fwcmd_tx_power(struct ieee80211_ -+ break; -+ } -+ -+- if (channel->band == IEEE80211_BAND_2GHZ) -++ if (channel->band == NL80211_BAND_2GHZ) -+ band = FREQ_BAND_2DOT4GHZ; -+- else if (channel->band == IEEE80211_BAND_5GHZ) -++ else if (channel->band == NL80211_BAND_5GHZ) -+ band = FREQ_BAND_5GHZ; -+ -+ switch (conf->chandef.width) { -+@@ -1354,9 +1354,9 @@ int mwl_fwcmd_set_rf_channel(struct ieee -+ pcmd->action = cpu_to_le16(WL_SET); -+ pcmd->curr_chnl = channel->hw_value; -+ -+- if (channel->band == IEEE80211_BAND_2GHZ) { -++ if (channel->band == NL80211_BAND_2GHZ) { -+ freq_band = FREQ_BAND_2DOT4GHZ; -+- } else if (channel->band == IEEE80211_BAND_5GHZ) { -++ } else if (channel->band == NL80211_BAND_5GHZ) { -+ freq_band = FREQ_BAND_5GHZ; -+ } else { -+ mutex_unlock(&priv->fwcmd_mutex); -+@@ -1923,10 +1923,10 @@ int mwl_fwcmd_set_new_stn_add(struct iee -+ } -+ ether_addr_copy(pcmd->mac_addr, sta->addr); -+ -+- if (hw->conf.chandef.chan->band == IEEE80211_BAND_2GHZ) -+- rates = sta->supp_rates[IEEE80211_BAND_2GHZ]; -++ if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ) -++ rates = sta->supp_rates[NL80211_BAND_2GHZ]; -+ else -+- rates = sta->supp_rates[IEEE80211_BAND_5GHZ] << 5; -++ rates = sta->supp_rates[NL80211_BAND_5GHZ] << 5; -+ pcmd->peer_info.legacy_rate_bitmap = cpu_to_le32(rates); -+ -+ if (sta->ht_cap.ht_supported) { -+@@ -2097,9 +2097,9 @@ int mwl_fwcmd_set_switch_channel(struct -+ if (priv->csa_active) -+ return 0; -+ -+- if (channel->band == IEEE80211_BAND_2GHZ) -++ if (channel->band == NL80211_BAND_2GHZ) -+ freq_band = FREQ_BAND_2DOT4GHZ; -+- else if (channel->band == IEEE80211_BAND_5GHZ) -++ else if (channel->band == NL80211_BAND_5GHZ) -+ freq_band = FREQ_BAND_5GHZ; -+ else -+ return -EINVAL; -+--- a/main.c -++++ b/main.c -+@@ -63,20 +63,20 @@ static struct mwl_chip_info mwl_chip_tbl -+ }; -+ -+ static const struct ieee80211_channel mwl_channels_24[] = { -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, }, -+- { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, }, -++ { .band = NL80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, }, -+ }; -+ -+ static const struct ieee80211_rate mwl_rates_24[] = { -+@@ -96,30 +96,30 @@ static const struct ieee80211_rate mwl_r -+ }; -+ -+ static const struct ieee80211_channel mwl_channels_50[] = { -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5260, .hw_value = 52, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5280, .hw_value = 56, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5300, .hw_value = 60, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5320, .hw_value = 64, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5500, .hw_value = 100, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5520, .hw_value = 104, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5540, .hw_value = 108, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5560, .hw_value = 112, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5580, .hw_value = 116, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5600, .hw_value = 120, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5620, .hw_value = 124, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5640, .hw_value = 128, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5660, .hw_value = 132, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5680, .hw_value = 136, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5700, .hw_value = 140, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5720, .hw_value = 144, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5745, .hw_value = 149, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5765, .hw_value = 153, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5785, .hw_value = 157, }, -+- { .band = IEEE80211_BAND_5GHZ, .center_freq = 5805, .hw_value = 161, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5260, .hw_value = 52, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5280, .hw_value = 56, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5300, .hw_value = 60, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5320, .hw_value = 64, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5500, .hw_value = 100, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5520, .hw_value = 104, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5540, .hw_value = 108, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5560, .hw_value = 112, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5580, .hw_value = 116, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5600, .hw_value = 120, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5620, .hw_value = 124, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5640, .hw_value = 128, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5660, .hw_value = 132, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5680, .hw_value = 136, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5700, .hw_value = 140, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5720, .hw_value = 144, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5745, .hw_value = 149, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5765, .hw_value = 153, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5785, .hw_value = 157, }, -++ { .band = NL80211_BAND_5GHZ, .center_freq = 5805, .hw_value = 161, }, -+ }; -+ -+ static const struct ieee80211_rate mwl_rates_50[] = { -+@@ -478,7 +478,7 @@ static void mwl_set_caps(struct mwl_priv -+ BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl_rates_24)); -+ memcpy(priv->rates_24, mwl_rates_24, sizeof(mwl_rates_24)); -+ -+- priv->band_24.band = IEEE80211_BAND_2GHZ; -++ priv->band_24.band = NL80211_BAND_2GHZ; -+ priv->band_24.channels = priv->channels_24; -+ priv->band_24.n_channels = ARRAY_SIZE(mwl_channels_24); -+ priv->band_24.bitrates = priv->rates_24; -+@@ -487,7 +487,7 @@ static void mwl_set_caps(struct mwl_priv -+ mwl_set_ht_caps(priv, &priv->band_24); -+ mwl_set_vht_caps(priv, &priv->band_24); -+ -+- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band_24; -++ hw->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band_24; -+ } -+ -+ /* set up band information for 5G */ -+@@ -500,7 +500,7 @@ static void mwl_set_caps(struct mwl_priv -+ BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl_rates_50)); -+ memcpy(priv->rates_50, mwl_rates_50, sizeof(mwl_rates_50)); -+ -+- priv->band_50.band = IEEE80211_BAND_5GHZ; -++ priv->band_50.band = NL80211_BAND_5GHZ; -+ priv->band_50.channels = priv->channels_50; -+ priv->band_50.n_channels = ARRAY_SIZE(mwl_channels_50); -+ priv->band_50.bitrates = priv->rates_50; -+@@ -509,7 +509,7 @@ static void mwl_set_caps(struct mwl_priv -+ mwl_set_ht_caps(priv, &priv->band_50); -+ mwl_set_vht_caps(priv, &priv->band_50); -+ -+- hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->band_50; -++ hw->wiphy->bands[NL80211_BAND_5GHZ] = &priv->band_50; -+ } -+ } -+ -+--- a/rx.c -++++ b/rx.c -+@@ -243,7 +243,7 @@ static inline void mwl_rx_prepare_status -+ status->rate_idx = rt; -+ -+ if (pdesc->channel > BAND_24_CHANNEL_NUM) { -+- status->band = IEEE80211_BAND_5GHZ; -++ status->band = NL80211_BAND_5GHZ; -+ if ((!(status->flag & RX_FLAG_HT)) && -+ (!(status->flag & RX_FLAG_VHT))) { -+ status->rate_idx -= 5; -+@@ -251,7 +251,7 @@ static inline void mwl_rx_prepare_status -+ status->rate_idx = BAND_50_RATE_NUM - 1; -+ } -+ } else { -+- status->band = IEEE80211_BAND_2GHZ; -++ status->band = NL80211_BAND_2GHZ; -+ if ((!(status->flag & RX_FLAG_HT)) && -+ (!(status->flag & RX_FLAG_VHT))) { -+ if (status->rate_idx >= BAND_24_RATE_NUM) -diff --git a/package/kernel/mwlwifi/patches/200-fix_excessive_delays.patch b/package/kernel/mwlwifi/patches/200-fix_excessive_delays.patch -new file mode 100644 -index 0000000..43523ed ---- /dev/null -+++ b/package/kernel/mwlwifi/patches/200-fix_excessive_delays.patch -@@ -0,0 +1,73 @@ -+--- a/fwcmd.c -++++ b/fwcmd.c -+@@ -132,7 +132,7 @@ static int mwl_fwcmd_wait_complete(struc -+ int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[2])); -+ else -+ int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[0])); -+- mdelay(1); -++ usleep_range(1000, 2000); -+ } while ((int_code != cmd) && (--curr_iteration)); -+ -+ if (curr_iteration == 0) { -+@@ -142,7 +142,7 @@ static int mwl_fwcmd_wait_complete(struc -+ return -EIO; -+ } -+ -+- mdelay(3); -++ usleep_range(3000, 5000); -+ -+ return 0; -+ } -+--- a/fwdl.c -++++ b/fwdl.c -+@@ -74,7 +74,7 @@ int mwl_fwdl_download_firmware(struct ie -+ /* FW before jumping to boot rom, it will enable PCIe transaction retry, -+ * wait for boot code to stop it. -+ */ -+- mdelay(FW_CHECK_MSECS); -++ usleep_range(FW_CHECK_MSECS * 1000, FW_CHECK_MSECS * 2000); -+ -+ writel(MACREG_A2HRIC_BIT_MASK, -+ priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CLEAR_SEL); -+@@ -95,7 +95,7 @@ int mwl_fwdl_download_firmware(struct ie -+ -+ /* make sure SCRATCH2 C40 is clear, in case we are too quick */ -+ while (readl(priv->iobase1 + 0xc40) == 0) -+- ; -++ cond_resched(); -+ -+ while (size_fw_downloaded < fw->size) { -+ len = readl(priv->iobase1 + 0xc40); -+@@ -125,6 +125,7 @@ int mwl_fwdl_download_firmware(struct ie -+ int_code = readl(priv->iobase1 + 0xc1c); -+ if (int_code != 0) -+ break; -++ cond_resched(); -+ curr_iteration--; -+ } while (curr_iteration); -+ -+@@ -133,6 +134,7 @@ int mwl_fwdl_download_firmware(struct ie -+ if ((int_code & MACREG_H2ARIC_BIT_DOOR_BELL) != -+ MACREG_H2ARIC_BIT_DOOR_BELL) -+ break; -++ cond_resched(); -+ curr_iteration--; -+ } while (curr_iteration); -+ -+@@ -167,12 +169,14 @@ int mwl_fwdl_download_firmware(struct ie -+ do { -+ curr_iteration--; -+ if (priv->mfg_mode && priv->chip_type == MWL8897) { -+- mdelay(FW_CHECK_MSECS); -++ usleep_range(FW_CHECK_MSECS * 1000, -++ FW_CHECK_MSECS * 2000); -+ int_code = readl(priv->iobase1 + 0xc44); -+ } else { -+ writel(HOSTCMD_SOFTAP_MODE, -+ priv->iobase1 + MACREG_REG_GEN_PTR); -+- mdelay(FW_CHECK_MSECS); -++ usleep_range(FW_CHECK_MSECS * 1000, -++ FW_CHECK_MSECS * 2000); -+ int_code = readl(priv->iobase1 + MACREG_REG_INT_CODE); -+ } -+ if (!(curr_iteration % 0xff) && (int_code != 0)) -diff --git a/package/kernel/mwlwifi/patches/210-fix_logspam.patch b/package/kernel/mwlwifi/patches/210-fix_logspam.patch -new file mode 100644 -index 0000000..99b247f ---- /dev/null -+++ b/package/kernel/mwlwifi/patches/210-fix_logspam.patch -@@ -0,0 +1,22 @@ -+--- a/fwcmd.c -++++ b/fwcmd.c -+@@ -2393,8 +2393,6 @@ int mwl_fwcmd_check_ba(struct ieee80211_ -+ -+ if (pcmd->cmd_hdr.result != 0) { -+ mutex_unlock(&priv->fwcmd_mutex); -+- wiphy_err(hw->wiphy, "check ba result error %d\n", -+- le16_to_cpu(pcmd->cmd_hdr.result)); -+ return -EINVAL; -+ } -+ -+--- a/mac80211.c -++++ b/mac80211.c -+@@ -644,8 +644,6 @@ static int mwl_mac80211_ampdu_action(str -+ spin_lock_bh(&priv->stream_lock); -+ if (rc) { -+ mwl_fwcmd_remove_stream(hw, stream); -+- wiphy_err(hw->wiphy, -+- "ampdu start error code: %d\n", rc); -+ rc = -EPERM; -+ break; -+ } +- +- static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +-- enum ieee80211_ampdu_mlme_action action, +-- struct ieee80211_sta *sta, +-- u16 tid, u16 *ssn, u8 buf_size, bool amsdu) +-+ struct ieee80211_ampdu_params *params) +- { +-+ enum ieee80211_ampdu_mlme_action action = params->action; +-+ struct ieee80211_sta *sta = params->sta; +-+ u16 tid = params->tid; +-+ u16 *ssn = ¶ms->ssn; +-+ u8 buf_size = params->buf_size; +- int rc = 0; +- struct mwl_priv *priv = hw->priv; +- struct mwl_ampdu_stream *stream; diff --git a/package/network/utils/iw/Makefile b/package/network/utils/iw/Makefile index ad82081..d17cbca 100644 --- a/package/network/utils/iw/Makefile diff --git a/patches/openwrt/0105-mt76-fix-build-with-kernel-3.18.patch b/patches/openwrt/0105-mt76-fix-build-with-kernel-3.18.patch index 8a731f92..d7eeb7ab 100644 --- a/patches/openwrt/0105-mt76-fix-build-with-kernel-3.18.patch +++ b/patches/openwrt/0105-mt76-fix-build-with-kernel-3.18.patch @@ -20,7 +20,7 @@ index 0000000..ea389cd + + /* diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile -index 0f832e4..801188f 100644 +index 90430b9..47f41da 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -24,7 +24,7 @@ include $(INCLUDE_DIR)/package.mk diff --git a/targets/ar71xx-generic/profiles.mk b/targets/ar71xx-generic/profiles.mk index 3db73aa2..123e3c0d 100644 --- a/targets/ar71xx-generic/profiles.mk +++ b/targets/ar71xx-generic/profiles.mk @@ -158,7 +158,7 @@ $(eval $(call GluonModel,TLWR2543,tl-wr2543-v1,tp-link-tl-wr2543n-nd-v1)) ifneq ($(BROKEN),) # Archer C5 v1, C7 v2 -$(eval $(call GluonProfile,ARCHERC7,kmod-ath10k ath10k-firmware-qca988x-ct)) +$(eval $(call GluonProfile,ARCHERC7,kmod-ath10k-ct ath10k-firmware-qca988x-ct)) $(eval $(call GluonModel,ARCHERC7,archer-c5,tp-link-archer-c5-v1)) # BROKEN: ath10k $(eval $(call GluonModel,ARCHERC7,archer-c7-v2,tp-link-archer-c7-v2)) # BROKEN: ath10k endif @@ -195,11 +195,11 @@ endif # Ubiquiti (ath10k) ifneq ($(BROKEN),) -$(eval $(call GluonProfile,UBNTUNIFIACLITE,kmod-ath10k ath10k-firmware-qca988x-ct)) +$(eval $(call GluonProfile,UBNTUNIFIACLITE,kmod-ath10k-ct ath10k-firmware-qca988x-ct)) $(eval $(call GluonProfileFactorySuffix,UBNTUNIFIACLITE)) $(eval $(call GluonModel,UBNTUNIFIACLITE,ubnt-unifiac-lite,ubiquiti-unifi-ac-lite)) # BROKEN: untested, ath10k -$(eval $(call GluonProfile,UBNTUNIFIACPRO,kmod-ath10k ath10k-firmware-qca988x-ct)) +$(eval $(call GluonProfile,UBNTUNIFIACPRO,kmod-ath10k-ct ath10k-firmware-qca988x-ct)) $(eval $(call GluonProfileFactorySuffix,UBNTUNIFIACPRO)) $(eval $(call GluonModel,UBNTUNIFIACPRO,ubnt-unifiac-pro,ubiquiti-unifi-ac-pro)) # BROKEN: ath10k endif @@ -314,7 +314,7 @@ $(eval $(call GluonModel,OMEGA,onion-omega,onion-omega)) ## OpenMesh # MR1750 -$(eval $(call GluonProfile,MR1750,om-watchdog uboot-envtools kmod-ath10k ath10k-firmware-qca988x-ct)) +$(eval $(call GluonProfile,MR1750,om-watchdog uboot-envtools kmod-ath10k-ct ath10k-firmware-qca988x-ct)) $(eval $(call GluonModel,MR1750,mr1750,openmesh-mr1750)) $(eval $(call GluonModelAlias,MR1750,openmesh-mr1750,openmesh-mr1750v2)) @@ -343,7 +343,7 @@ $(eval $(call GluonModel,OM5P,om5p,openmesh-om5p)) $(eval $(call GluonModelAlias,OM5P,openmesh-om5p,openmesh-om5p-an)) # OM5P-AC -$(eval $(call GluonProfile,OM5PAC,om-watchdog uboot-envtools kmod-ath10k ath10k-firmware-qca988x-ct)) +$(eval $(call GluonProfile,OM5PAC,om-watchdog uboot-envtools kmod-ath10k-ct ath10k-firmware-qca988x-ct)) $(eval $(call GluonModel,OM5PAC,om5pac,openmesh-om5p-ac)) $(eval $(call GluonModelAlias,OM5PAC,openmesh-om5p-ac,openmesh-om5p-acv2))