diff --git a/patches/openwrt/0006-base-files-disable-reset-button-handling.patch b/patches/openwrt/0005-base-files-disable-reset-button-handling.patch similarity index 100% rename from patches/openwrt/0006-base-files-disable-reset-button-handling.patch rename to patches/openwrt/0005-base-files-disable-reset-button-handling.patch diff --git a/patches/openwrt/0006-mac80211-backport-from-trunk-r46760.patch b/patches/openwrt/0006-mac80211-backport-from-trunk-r46760.patch new file mode 100644 index 00000000..03aa5c5e --- /dev/null +++ b/patches/openwrt/0006-mac80211-backport-from-trunk-r46760.patch @@ -0,0 +1,20504 @@ +From: Matthias Schiffer +Date: Tue, 1 Sep 2015 18:50:16 +0200 +Subject: mac80211: backport from trunk r46760 + +diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile +index a1eedce..04dfd3b 100644 +--- a/package/kernel/mac80211/Makefile ++++ b/package/kernel/mac80211/Makefile +@@ -10,11 +10,11 @@ include $(INCLUDE_DIR)/kernel.mk + + PKG_NAME:=mac80211 + +-PKG_VERSION:=2015-03-09 +-PKG_RELEASE:=3 ++PKG_VERSION:=2015-07-21 ++PKG_RELEASE:=1 + PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources + PKG_BACKPORT_VERSION:= +-PKG_MD5SUM:=6d4b04e4ce8a1f54dabfb04f4709453c ++PKG_MD5SUM:=ec529acfb9c942daf8116e5cff47c999 + + PKG_SOURCE:=compat-wireless-$(PKG_VERSION)$(PKG_BACKPORT_VERSION).tar.bz2 + PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION) +@@ -31,7 +31,7 @@ PKG_DRIVERS = \ + mwl8k mwifiex-pcie net-hermes net-hermes-pci net-hermes-plx net-hermes-pcmcia \ + iwl-legacy iwl3945 iwl4965 iwlagn wlcore wl12xx wl18xx lib80211 \ + rtlwifi rtlwifi-pci rtlwifi-usb rtl8192c-common rtl8192ce rtl8192se \ +- rtl8192de rtl8192cu ++ rtl8192de rtl8192cu mt7601u + + PKG_CONFIG_DEPENDS:= \ + CONFIG_PACKAGE_kmod-mac80211 \ +@@ -60,7 +60,6 @@ define KernelPackage/mac80211/Default + SUBMENU:=$(WMENU) + URL:=https://wireless.wiki.kernel.org/ + MAINTAINER:=Felix Fietkau +- DEPENDS:=@!TARGET_uml + endef + + define KernelPackage/cfg80211 +@@ -79,7 +78,7 @@ endef + define KernelPackage/mac80211 + $(call KernelPackage/mac80211/Default) + TITLE:=Linux 802.11 Wireless Networking Stack +- DEPENDS+= +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-aes +kmod-cfg80211 +hostapd-common ++ DEPENDS+= +kmod-crypto-core +kmod-crypto-arc4 +kmod-cfg80211 +hostapd-common + KCONFIG:=\ + CONFIG_AVERAGE=y + FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko +@@ -128,7 +127,7 @@ endef + $(eval $(call Download,linux-firmware)) + + PKG_ATH10K_LINUX_FIRMWARE_NAME:=ath10k-firmware +-PKG_ATH10K_LINUX_FIRMWARE_VERSION:=da0f85d924226ee30c46e037120621c9e192b39e ++PKG_ATH10K_LINUX_FIRMWARE_VERSION:=b46f3e01a6c1f9150fb4612ef53611d714565842 + PKG_ATH10K_LINUX_FIRMWARE_SOURCE:=$(PKG_ATH10K_LINUX_FIRMWARE_NAME)-$(PKG_ATH10K_LINUX_FIRMWARE_VERSION).tar.bz2 + PKG_ATH10K_LINUX_FIRMWARE_PROTO:=git + PKG_ATH10K_LINUX_FIRMWARE_SOURCE_URL:=https://github.com/kvalo/ath10k-firmware.git +@@ -516,7 +515,7 @@ define KernelPackage/ath/config + bool "Atheros wireless debugging" + help + Say Y, if you want to debug atheros wireless drivers. +- Right now only ath9k makes use of this. ++ Only ath9k & ath10k make use of this. + + config PACKAGE_ATH_DFS + bool "Enable DFS support" +@@ -624,17 +623,9 @@ endef + define KernelPackage/ath10k/config + if PACKAGE_kmod-ath10k + +- config ATH10K_STA_FW +- bool "Firmware optimized for STA operation" +- default n +- help +- Use the ath10k firmware optimized for wireless client instead +- of access point operation. +- + config ATH10K_API2_FW + bool "Firmware optimized for AP operation (v10.1 / API v2)" + default n +- depends on !ATH10K_STA_FW + help + Use the ath10k firmware from the 10.1 SDK using API v2 optimized + for access point operation if the default firmware keeps crashing. +@@ -704,10 +695,31 @@ define KernelPackage/mac80211-hwsim + AUTOLOAD:=$(call AutoProbe,mac80211_hwsim) + endef + ++PKG_MT7601U_FW_NAME:=DPO_MT7601U_LinuxSTA ++PKG_MT7601U_FW_VERSION:=3.0.0.4_20130913 ++PKG_MT7601U_FW_MD5SUM:=5f440dccc8bc952745a191994fc34699 ++PKG_MT7601U_FW_SOURCE:=$(PKG_MT7601U_FW_NAME)_$(PKG_MT7601U_FW_VERSION).tar.bz2 ++PKG_MT7601U_FW_SOURCE_URL:=http://www.mediatek.com/AmazonS3/Downloads/linux/ ++define Download/mt7601u-firmware ++ FILE:=$(PKG_MT7601U_FW_SOURCE) ++ URL:=$(PKG_MT7601U_FW_SOURCE_URL) ++ MD5SUM:=$(PKG_MT7601U_FW_MD5SUM) ++ SUBDIR:=$(PKG_MT7601U_FW_NAME)_$(PKG_MT7601U_FW_VERSION) ++endef ++$(eval $(call Download,mt7601u-firmware)) ++ ++define KernelPackage/mt7601u ++ $(call KernelPackage/mac80211/Default) ++ TITLE:=MT7601U-based USB dongles Wireless Driver ++ DEPENDS+= +kmod-mac80211 +@DRIVER_11N_SUPPORT @USB_SUPPORT +kmod-usb-core ++ FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mediatek/mt7601u/mt7601u.ko ++ AUTOLOAD:=$(call AutoProbe,mt7601) ++endef ++ + define KernelPackage/net-libipw + $(call KernelPackage/mac80211/Default) + TITLE:=libipw for ipw2100 and ipw2200 +- DEPENDS:=@PCI_SUPPORT +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-aes +kmod-crypto-michael-mic +kmod-lib80211 +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT @!BIG_ENDIAN ++ DEPENDS:=@PCI_SUPPORT +kmod-crypto-core +kmod-crypto-arc4 +kmod-crypto-michael-mic +kmod-lib80211 +kmod-cfg80211 +@DRIVER_WEXT_SUPPORT @!BIG_ENDIAN + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ipw2x00/libipw.ko + AUTOLOAD:=$(call AutoProbe,libipw) + endef +@@ -1602,6 +1614,8 @@ config-$(CONFIG_BRCMFMAC_PCIE) += BRCMFMAC_PCIE + config-$(CONFIG_PACKAGE_BRCM80211_DEBUG) += BRCMDBG + + config-$(call config_package,mac80211-hwsim) += MAC80211_HWSIM ++config-$(call config_package,mt7601u) += MT7601U ++config-y += WL_MEDIATEK + + config-$(call config_package,rt2x00-lib) += RT2X00 RT2X00_LIB + config-$(call config_package,rt2x00-pci) += RT2X00_LIB_PCI +@@ -1704,6 +1718,7 @@ define Build/Prepare + $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(ZD1211FW_NAME)-$(ZD1211FW_VERSION).tar.bz2 + $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_LINUX_FIRMWARE_SOURCE) + $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SOURCE) ++ $(TAR) -C $(PKG_BUILD_DIR) -xjf $(DL_DIR)/$(PKG_MT7601U_FW_SOURCE) + rm -rf \ + $(PKG_BUILD_DIR)/include/linux/ssb \ + $(PKG_BUILD_DIR)/include/linux/bcma \ +@@ -1866,21 +1881,24 @@ define KernelPackage/ath10k/install + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ +-ifeq ($(CONFIG_ATH10K_STA_FW),y) +- $(INSTALL_DATA) \ +- $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/main/firmware-2.bin_999.999.0.636 \ +- $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin +-else ifeq ($(CONFIG_ATH10K_API2_FW),y) ++ifeq ($(CONFIG_ATH10K_API2_FW),y) + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.1/firmware-2.bin_10.1.467.2-1 \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin + else + $(INSTALL_DATA) \ +- $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/firmware-4.bin_10.2.4.45 \ +- $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-4.bin ++ $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/untested/firmware-5.bin_10.2.4.70-2 \ ++ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-5.bin + endif + endef + ++define KernelPackage/mt7601u/install ++ $(INSTALL_DIR) $(1)/lib/firmware ++ $(INSTALL_DATA) \ ++ $(PKG_BUILD_DIR)/$(PKG_MT7601U_FW_NAME)_$(PKG_MT7601U_FW_VERSION)/mcu/bin/MT7601.bin \ ++ $(1)/lib/firmware/mt7601u.bin ++endef ++ + define KernelPackage/mwl8k/install + $(INSTALL_DIR) $(1)/lib/firmware/mwl8k + $(INSTALL_DATA) \ +@@ -2065,6 +2083,7 @@ $(eval $(call KernelPackage,rtl8192de)) + $(eval $(call KernelPackage,rtl8192cu)) + $(eval $(call KernelPackage,zd1211rw)) + $(eval $(call KernelPackage,mac80211-hwsim)) ++$(eval $(call KernelPackage,mt7601u)) + $(eval $(call KernelPackage,ath9k-common)) + $(eval $(call KernelPackage,ath9k)) + $(eval $(call KernelPackage,ath9k-htc)) +diff --git a/package/kernel/mac80211/files/regdb.txt b/package/kernel/mac80211/files/regdb.txt +index ba95fc6..84413fd 100644 +--- a/package/kernel/mac80211/files/regdb.txt ++++ b/package/kernel/mac80211/files/regdb.txt +@@ -6,7 +6,7 @@ country 00: + # Channel 14. Only JP enables this and for 802.11b only + (2474 - 2494 @ 20), (20), NO-IR, NO-OFDM + # Channel 36 - 48 +- (5170 - 5250 @ 80), (20) ++ (5170 - 5250 @ 80), (20), AUTO-BW + # Channel 52 - 64 + (5250 - 5330 @ 80), (20), NO-IR, DFS, AUTO-BW + # Channel 100 - 144 +@@ -54,8 +54,8 @@ country AL: DFS-ETSI + + country AM: DFS-ETSI + (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (18) +- (5250 - 5330 @ 80), (18), DFS ++ (5170 - 5250 @ 20), (18) ++ (5250 - 5330 @ 20), (18), DFS + + country AN: DFS-ETSI + (2402 - 2482 @ 40), (20) +@@ -85,7 +85,7 @@ country AT: DFS-ETSI + # 60 gHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +-country AU: ++country AU: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW +@@ -141,14 +141,20 @@ country BG: DFS-ETSI + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS ++ # 5 gHz Short Range Devices, ref: ++ # Etsi EN 300 440-1 ++ # Etsi EN 300 440-2 ++ # http://crc.bg/files/_bg/Spisak_2015.pdf ++ # http://crc.bg/files/_bg/Pravila_2015_resh24.pdf ++ (5725 - 5875 @ 80), (14) + # 60 gHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + + country BH: DFS-JP + (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (20) +- (5250 - 5330 @ 80), (20), DFS +- (5735 - 5835 @ 80), (20) ++ (5170 - 5250 @ 20), (20) ++ (5250 - 5330 @ 20), (20), DFS ++ (5735 - 5835 @ 20), (20) + + country BL: DFS-ETSI + (2402 - 2482 @ 40), (20) +@@ -263,10 +269,10 @@ country CO: DFS-FCC + + country CR: DFS-FCC + (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (17) +- (5250 - 5330 @ 80), (24), DFS +- (5490 - 5730 @ 80), (24), DFS +- (5735 - 5835 @ 80), (30) ++ (5170 - 5250 @ 20), (17) ++ (5250 - 5330 @ 20), (24), DFS ++ (5490 - 5730 @ 20), (24), DFS ++ (5735 - 5835 @ 20), (30) + + country CX: DFS-FCC + (2402 - 2482 @ 40), (20) +@@ -349,10 +355,10 @@ country DZ: DFS-JP + + country EC: DFS-FCC + (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (17) +- (5250 - 5330 @ 80), (24), DFS +- (5490 - 5730 @ 80), (24), DFS +- (5735 - 5835 @ 80), (30) ++ (5170 - 5250 @ 20), (17) ++ (5250 - 5330 @ 20), (24), DFS ++ (5490 - 5730 @ 20), (24), DFS ++ (5735 - 5835 @ 20), (30) + + country EE: DFS-ETSI + (2402 - 2482 @ 40), (20) +@@ -364,8 +370,8 @@ country EE: DFS-ETSI + + country EG: DFS-ETSI + (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (20) +- (5250 - 5330 @ 80), (20), DFS ++ (5170 - 5250 @ 40), (20) ++ (5250 - 5330 @ 40), (20), DFS + + # Orden IET/787/2013, de 25 de abril, por la que se aprueba + # el cuadro nacional de atribución de frecuencias. +@@ -474,10 +480,10 @@ country GT: DFS-FCC + + country GU: DFS-FCC + (2402 - 2472 @ 40), (30) +- (5170 - 5250 @ 80), (17) +- (5250 - 5330 @ 80), (24), DFS +- (5490 - 5730 @ 80), (24), DFS +- (5735 - 5835 @ 80), (30) ++ (5170 - 5250 @ 20), (17) ++ (5250 - 5330 @ 20), (24), DFS ++ (5490 - 5730 @ 20), (24), DFS ++ (5735 - 5835 @ 20), (30) + + country GY: + (2402 - 2482 @ 40), (30) +@@ -522,8 +528,8 @@ country HU: DFS-ETSI + + country ID: DFS-JP + # ref: http://www.postel.go.id/content/ID/regulasi/standardisasi/kepdir/bwa%205,8%20ghz.pdf +- (2402 - 2482 @ 40), (20) +- (5735 - 5815 @ 80), (23) ++ (2402 - 2482 @ 20), (20) ++ (5735 - 5815 @ 20), (23) + + country IE: DFS-ETSI + (2402 - 2482 @ 40), (20) +@@ -584,6 +590,9 @@ country JP: DFS-JP + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (23), DFS ++ # 60 GHz band channels 2-4 at 10mW, ++ # ref: http://www.arib.or.jp/english/html/overview/doc/1-STD-T74v1_1.pdf ++ (59000 - 66000 @ 2160), (10 mW) + + country KE: DFS-JP + (2402 - 2482 @ 40), (20) +@@ -607,11 +616,11 @@ country KN: DFS-ETSI + (5735 - 5815 @ 80), (30) + + country KP: DFS-JP +- (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (20), AUTO-BW +- (5250 - 5330 @ 80), (20), DFS, AUTO-BW +- (5490 - 5630 @ 80), (30), DFS +- (5735 - 5815 @ 80), (30) ++ (2402 - 2482 @ 20), (20) ++ (5170 - 5250 @ 20), (20) ++ (5250 - 5330 @ 20), (20), DFS ++ (5490 - 5630 @ 20), (30), DFS ++ (5735 - 5815 @ 20), (30) + + country KR: DFS-JP + (2402 - 2482 @ 40), (20) +@@ -659,10 +668,10 @@ country LI: DFS-ETSI + + country LK: DFS-FCC + (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (17) +- (5250 - 5330 @ 80), (24), DFS +- (5490 - 5730 @ 80), (24), DFS +- (5735 - 5835 @ 80), (30) ++ (5170 - 5250 @ 20), (17) ++ (5250 - 5330 @ 20), (24), DFS ++ (5490 - 5730 @ 20), (24), DFS ++ (5735 - 5835 @ 20), (30) + + # Source: + # http://lca.org.ls/images/documents/lesotho_national_frequency_allocation_plan.pdf +@@ -751,11 +760,12 @@ country MN: DFS-FCC + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +-country MO: +- (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 40), (23) +- (5250 - 5330 @ 40), (23), DFS +- (5735 - 5835 @ 40), (30) ++country MO: DFS-FCC ++ (2402 - 2482 @ 40), (23) ++ (5170 - 5250 @ 80), (23), AUTO-BW ++ (5250 - 5330 @ 80), (23), DFS, AUTO-BW ++ (5490 - 5730 @ 160), (30), DFS ++ (5735 - 5835 @ 80), (30) + + country MP: DFS-FCC + (2402 - 2472 @ 40), (30) +@@ -793,6 +803,14 @@ country MU: DFS-FCC + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + ++# Source: ++# http://www.cam.gov.mv/docs/tech_standards/TAM-TS-100-2004-WLAN.pdf ++country MV: DFS-ETSI ++ (2400 - 2483.5 @ 40), (100 mW) ++ (5150 - 5250 @ 80), (200 mW), AUTO-BW ++ (5250 - 5350 @ 80), (100 mW), DFS, AUTO-BW ++ (5725 - 5850 @ 80), (100 mW) ++ + country MW: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW +@@ -812,6 +830,11 @@ country MY: DFS-FCC + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5735 - 5835 @ 80), (30) + ++country NG: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5250 - 5330 @ 80), (30), DFS ++ (5735 - 5835 @ 80), (30) ++ + country NI: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW +@@ -848,7 +871,7 @@ country NP: DFS-JP + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5735 - 5835 @ 80), (20) + +-country NZ: DFS-FCC ++country NZ: DFS-ETSI + (2402 - 2482 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW +@@ -971,10 +994,12 @@ country RS: DFS-ETSI + + country RU: DFS-ETSI + (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (20) +- (5250 - 5330 @ 80), (20), DFS +- (5650 - 5730 @ 80), (30), DFS +- (5735 - 5835 @ 80), (30) ++ (5170 - 5250 @ 40), (20) ++ (5250 - 5330 @ 40), (20), DFS ++ (5650 - 5730 @ 40), (30), DFS ++ (5735 - 5835 @ 40), (30) ++ # 60 GHz band channels 1-4, ref: Changes to NLA 124_Order №129_22042015.pdf ++ (57000 - 66000 @ 2160), (40) + + country RW: DFS-FCC + (2402 - 2482 @ 40), (20) +@@ -1037,9 +1062,9 @@ country SR: DFS-ETSI + + country SV: DFS-FCC + (2402 - 2482 @ 40), (20) +- (5170 - 5250 @ 80), (17) +- (5250 - 5330 @ 80), (23), DFS +- (5735 - 5835 @ 80), (30) ++ (5170 - 5250 @ 20), (17) ++ (5250 - 5330 @ 20), (23), DFS ++ (5735 - 5835 @ 20), (30) + + country SY: + (2402 - 2482 @ 40), (20) +@@ -1099,6 +1124,10 @@ country TW: DFS-JP + (5650 - 5710 @ 40), (30), DFS + (5735 - 5835 @ 80), (30) + ++country TZ: ++ (2402 - 2482 @ 40), (20) ++ (5735 - 5835 @ 80), (30) ++ + # Source: + # #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874 + # #1174 / 23 Oct 2008: http://www.nkrz.gov.ua/uk/activities/ruling/1225269361 +@@ -1125,6 +1154,7 @@ country US: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW ++ (5490 - 5730 @ 160), (23), DFS + (5735 - 5835 @ 80), (30) + # 60g band + # reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255 +@@ -1192,6 +1222,12 @@ country WF: DFS-ETSI + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + ++country WS: DFS-ETSI ++ (2402 - 2482 @ 40), (20) ++ (5170 - 5250 @ 40), (20) ++ (5250 - 5330 @ 40), (20), DFS ++ (5490 - 5710 @ 40), (27), DFS ++ + country YE: + (2402 - 2482 @ 40), (20) + +diff --git a/package/kernel/mac80211/patches/001-fix_build.patch b/package/kernel/mac80211/patches/001-fix_build.patch +index 818983e..402649d 100644 +--- a/package/kernel/mac80211/patches/001-fix_build.patch ++++ b/package/kernel/mac80211/patches/001-fix_build.patch +@@ -27,7 +27,7 @@ + @set -e ; test -f .local-symbols || ( \ + echo "/--------------" ;\ + echo "| You shouldn't run make in the backports tree, but only in" ;\ +-@@ -60,56 +62,60 @@ mrproper: ++@@ -60,57 +62,61 @@ mrproper: + echo "| (that isn't currently running.)" ;\ + echo "\\--" ;\ + false) +@@ -56,11 +56,12 @@ + - done \ + - ) > Kconfig.kernel ;\ + - kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \ +-- sed 's/^\(\(3\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\ ++- sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\ + - test "$$kver" != "" || echo "Kernel version parse failed!" ;\ + - test "$$kver" != "" ;\ + - kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\ +-- kvers="$$kvers $$(seq 0 99 | sed 's/^/3./')" ;\ ++- kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\ ++- kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\ + - print=0 ;\ + - for v in $$kvers ; do \ + - if [ "$$print" = "1" ] ; then \ +@@ -111,11 +112,12 @@ + + + +Kconfig.versions: Kconfig.kernel + + @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \ +-+ sed 's/^\(\(3\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\ +++ sed 's/^\(\([3-4]\|2\.6\)\.[0-9]\+\).*/\1/;t;d') ;\ + + test "$$kver" != "" || echo "Kernel version parse failed!" ;\ + + test "$$kver" != "" ;\ + + kvers="$$(seq 14 39 | sed 's/^/2.6./')" ;\ +-+ kvers="$$kvers $$(seq 0 99 | sed 's/^/3./')" ;\ +++ kvers="$$kvers $$(seq 0 19 | sed 's/^/3./')" ;\ +++ kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\ + + print=0 ;\ + + for v in $$kvers ; do \ + + if [ "$$print" = "1" ] ; then \ +diff --git a/package/kernel/mac80211/patches/004-backports_debugfs_fix.patch b/package/kernel/mac80211/patches/004-backports_debugfs_fix.patch +deleted file mode 100644 +index d48a723..0000000 +--- a/package/kernel/mac80211/patches/004-backports_debugfs_fix.patch ++++ /dev/null +@@ -1,10 +0,0 @@ +---- a/backport-include/linux/debugfs.h +-+++ b/backport-include/linux/debugfs.h +-@@ -3,6 +3,7 @@ +- #include_next +- #include +- #include +-+#include +- +- #if defined(CONFIG_DEBUG_FS) +- struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name, +diff --git a/package/kernel/mac80211/patches/008-fix_netdev_unregister.patch b/package/kernel/mac80211/patches/008-fix_netdev_unregister.patch +deleted file mode 100644 +index e07f323..0000000 +--- a/package/kernel/mac80211/patches/008-fix_netdev_unregister.patch ++++ /dev/null +@@ -1,16 +0,0 @@ +---- a/net/mac80211/iface.c +-+++ b/net/mac80211/iface.c +-@@ -1858,6 +1858,13 @@ void ieee80211_remove_interfaces(struct +- } +- mutex_unlock(&local->iflist_mtx); +- unregister_netdevice_many(&unreg_list); +-+#if (!(LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,45) && \ +-+ LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)) && \ +-+ !(LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,9) && \ +-+ LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)) && \ +-+ (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0))) +-+ list_del(&unreg_list); +-+#endif +- +- list_for_each_entry_safe(sdata, tmp, &wdev_list, list) { +- list_del(&sdata->list); +diff --git a/package/kernel/mac80211/patches/020-add_mpls_h.patch b/package/kernel/mac80211/patches/020-add_mpls_h.patch +deleted file mode 100644 +index e5310bc..0000000 +--- a/package/kernel/mac80211/patches/020-add_mpls_h.patch ++++ /dev/null +@@ -1,37 +0,0 @@ +---- /dev/null +-+++ b/include/uapi/linux/mpls.h +-@@ -0,0 +1,34 @@ +-+#ifndef _UAPI_MPLS_H +-+#define _UAPI_MPLS_H +-+ +-+#include +-+#include +-+ +-+/* Reference: RFC 5462, RFC 3032 +-+ * +-+ * 0 1 2 3 +-+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+ * | Label | TC |S| TTL | +-+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+ * +-+ * Label: Label Value, 20 bits +-+ * TC: Traffic Class field, 3 bits +-+ * S: Bottom of Stack, 1 bit +-+ * TTL: Time to Live, 8 bits +-+ */ +-+ +-+struct mpls_label { +-+ __be32 entry; +-+}; +-+ +-+#define MPLS_LS_LABEL_MASK 0xFFFFF000 +-+#define MPLS_LS_LABEL_SHIFT 12 +-+#define MPLS_LS_TC_MASK 0x00000E00 +-+#define MPLS_LS_TC_SHIFT 9 +-+#define MPLS_LS_S_MASK 0x00000100 +-+#define MPLS_LS_S_SHIFT 8 +-+#define MPLS_LS_TTL_MASK 0x000000FF +-+#define MPLS_LS_TTL_SHIFT 0 +-+ +-+#endif /* _UAPI_MPLS_H */ +diff --git a/package/kernel/mac80211/patches/020-backports-do-not-add-debugfs_create_devm_seqfile-on-.patch b/package/kernel/mac80211/patches/020-backports-do-not-add-debugfs_create_devm_seqfile-on-.patch +new file mode 100644 +index 0000000..97f678c +--- /dev/null ++++ b/package/kernel/mac80211/patches/020-backports-do-not-add-debugfs_create_devm_seqfile-on-.patch +@@ -0,0 +1,33 @@ ++From e15e9231e7a9f81f5264d294fd3fd96a20d92516 Mon Sep 17 00:00:00 2001 ++From: Hauke Mehrtens ++Date: Sat, 25 Jul 2015 15:19:17 +0200 ++Subject: [PATCH 3/3] backports: do not add debugfs_create_devm_seqfile() on ++ recent kernel versions ++ ++An #ifdef for the kernel version was missing around the header of ++debugfs_create_devm_seqfile() and the LINUX_BACKPORT() was also not ++done. ++ ++Signed-off-by: Hauke Mehrtens ++--- ++ backport/backport-include/linux/debugfs.h | 3 +++ ++ 1 file changed, 3 insertions(+) ++ ++--- a/backport-include/linux/debugfs.h +++++ b/backport-include/linux/debugfs.h ++@@ -5,6 +5,8 @@ ++ #include ++ #include ++ +++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) +++#define debugfs_create_devm_seqfile LINUX_BACKPORT(debugfs_create_devm_seqfile) ++ #if defined(CONFIG_DEBUG_FS) ++ struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name, ++ struct dentry *parent, ++@@ -20,5 +22,6 @@ static inline struct dentry *debugfs_cre ++ return ERR_PTR(-ENODEV); ++ } ++ #endif /* CONFIG_DEBUG_FS */ +++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */ ++ ++ #endif /* __BACKPORT_DEBUGFS_H_ */ +diff --git a/package/kernel/mac80211/patches/045-bcma-from-4.1.patch b/package/kernel/mac80211/patches/045-bcma-from-4.1.patch +deleted file mode 100644 +index dce217f..0000000 +--- a/package/kernel/mac80211/patches/045-bcma-from-4.1.patch ++++ /dev/null +@@ -1,104 +0,0 @@ +---- a/drivers/bcma/driver_pci.c +-+++ b/drivers/bcma/driver_pci.c +-@@ -282,39 +282,6 @@ void bcma_core_pci_power_save(struct bcm +- } +- EXPORT_SYMBOL_GPL(bcma_core_pci_power_save); +- +--int bcma_core_pci_irq_ctl(struct bcma_bus *bus, struct bcma_device *core, +-- bool enable) +--{ +-- struct pci_dev *pdev; +-- u32 coremask, tmp; +-- int err = 0; +-- +-- if (bus->hosttype != BCMA_HOSTTYPE_PCI) { +-- /* This bcma device is not on a PCI host-bus. So the IRQs are +-- * not routed through the PCI core. +-- * So we must not enable routing through the PCI core. */ +-- goto out; +-- } +-- +-- pdev = bus->host_pci; +-- +-- err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); +-- if (err) +-- goto out; +-- +-- coremask = BIT(core->core_index) << 8; +-- if (enable) +-- tmp |= coremask; +-- else +-- tmp &= ~coremask; +-- +-- err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp); +-- +--out: +-- return err; +--} +--EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl); +-- +- static void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend) +- { +- u32 w; +---- a/drivers/bcma/host_pci.c +-+++ b/drivers/bcma/host_pci.c +-@@ -351,3 +351,37 @@ void bcma_host_pci_down(struct bcma_bus +- bcma_core_pci_down(&bus->drv_pci[0]); +- } +- EXPORT_SYMBOL_GPL(bcma_host_pci_down); +-+ +-+/* See also si_pci_setup */ +-+int bcma_host_pci_irq_ctl(struct bcma_bus *bus, struct bcma_device *core, +-+ bool enable) +-+{ +-+ struct pci_dev *pdev; +-+ u32 coremask, tmp; +-+ int err = 0; +-+ +-+ if (bus->hosttype != BCMA_HOSTTYPE_PCI) { +-+ /* This bcma device is not on a PCI host-bus. So the IRQs are +-+ * not routed through the PCI core. +-+ * So we must not enable routing through the PCI core. */ +-+ goto out; +-+ } +-+ +-+ pdev = bus->host_pci; +-+ +-+ err = pci_read_config_dword(pdev, BCMA_PCI_IRQMASK, &tmp); +-+ if (err) +-+ goto out; +-+ +-+ coremask = BIT(core->core_index) << 8; +-+ if (enable) +-+ tmp |= coremask; +-+ else +-+ tmp &= ~coremask; +-+ +-+ err = pci_write_config_dword(pdev, BCMA_PCI_IRQMASK, tmp); +-+ +-+out: +-+ return err; +-+} +-+EXPORT_SYMBOL_GPL(bcma_host_pci_irq_ctl); +---- a/drivers/net/wireless/b43/main.c +-+++ b/drivers/net/wireless/b43/main.c +-@@ -4866,7 +4866,7 @@ static int b43_wireless_core_init(struct +- switch (dev->dev->bus_type) { +- #ifdef CPTCFG_B43_BCMA +- case B43_BUS_BCMA: +-- bcma_core_pci_irq_ctl(dev->dev->bdev->bus, +-+ bcma_host_pci_irq_ctl(dev->dev->bdev->bus, +- dev->dev->bdev, true); +- bcma_host_pci_up(dev->dev->bdev->bus); +- break; +---- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +-+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c +-@@ -4959,7 +4959,7 @@ static int brcms_b_up_prep(struct brcms_ +- * Configure pci/pcmcia here instead of in brcms_c_attach() +- * to allow mfg hotswap: down, hotswap (chip power cycle), up. +- */ +-- bcma_core_pci_irq_ctl(wlc_hw->d11core->bus, wlc_hw->d11core, +-+ bcma_host_pci_irq_ctl(wlc_hw->d11core->bus, wlc_hw->d11core, +- true); +- +- /* +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 d307949..4fbab23 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 @@ + --- a/.local-symbols + +++ b/.local-symbols +-@@ -344,40 +344,3 @@ USB_CDC_PHONET= ++@@ -449,43 +449,6 @@ USB_CDC_PHONET= + USB_IPHETH= + USB_SIERRA_NET= + USB_VL600= +@@ -32,26 +32,18 @@ + -BCMA_BLOCKIO= + -BCMA_HOST_PCI_POSSIBLE= + -BCMA_HOST_PCI= +--BCMA_DRIVER_PCI_HOSTMODE= + -BCMA_HOST_SOC= + -BCMA_DRIVER_PCI= ++-BCMA_DRIVER_PCI_HOSTMODE= + -BCMA_DRIVER_MIPS= + -BCMA_SFLASH= + -BCMA_NFLASH= + -BCMA_DRIVER_GMAC_CMN= + -BCMA_DRIVER_GPIO= + -BCMA_DEBUG= +---- a/Makefile.kernel +-+++ b/Makefile.kernel +-@@ -38,8 +38,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/ +- obj-$(CPTCFG_WLAN) += drivers/net/wireless/ +- #obj-$(CPTCFG_BT) += net/bluetooth/ +- #obj-$(CPTCFG_BT) += drivers/bluetooth/ +--obj-$(CPTCFG_SSB) += drivers/ssb/ +--obj-$(CPTCFG_BCMA) += drivers/bcma/ +- #obj-$(CPTCFG_ETHERNET) += drivers/net/ethernet/ +- obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/ +- #obj-$(CPTCFG_NFC) += net/nfc/ ++ NFC= ++ NFC_DIGITAL= ++ NFC_NCI= + --- a/drivers/net/wireless/b43/main.c + +++ b/drivers/net/wireless/b43/main.c + @@ -2866,7 +2866,7 @@ static struct ssb_device *b43_ssb_gpio_d +@@ -63,7 +55,7 @@ + return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev); + #else + return bus->chipco.dev; +-@@ -4907,7 +4907,7 @@ static int b43_wireless_core_init(struct ++@@ -4903,7 +4903,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. */ +@@ -116,12 +108,23 @@ + --- a/Kconfig.sources + +++ b/Kconfig.sources + @@ -9,9 +9,6 @@ source "$BACKPORT_DIR/drivers/net/wirele +- #source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig" ++ source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig" + source "$BACKPORT_DIR/drivers/net/usb/Kconfig" + + -source "$BACKPORT_DIR/drivers/ssb/Kconfig" + -source "$BACKPORT_DIR/drivers/bcma/Kconfig" + - +- #source "$BACKPORT_DIR/net/nfc/Kconfig" ++ source "$BACKPORT_DIR/net/nfc/Kconfig" + +- #source "$BACKPORT_DIR/drivers/media/Kconfig" ++ source "$BACKPORT_DIR/drivers/media/Kconfig" ++--- a/Makefile.kernel +++++ b/Makefile.kernel ++@@ -38,8 +38,6 @@ obj-$(CPTCFG_MAC80211) += net/mac80211/ ++ obj-$(CPTCFG_WLAN) += drivers/net/wireless/ ++ obj-$(CPTCFG_BT) += net/bluetooth/ ++ obj-$(CPTCFG_BT) += drivers/bluetooth/ ++-obj-$(CPTCFG_SSB) += drivers/ssb/ ++-obj-$(CPTCFG_BCMA) += drivers/bcma/ ++ obj-$(CPTCFG_ETHERNET) += drivers/net/ethernet/ ++ obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/ ++ obj-$(CPTCFG_NFC) += net/nfc/ +diff --git a/package/kernel/mac80211/patches/090-linux_3_18_12_compat.patch b/package/kernel/mac80211/patches/090-linux_3_18_12_compat.patch +deleted file mode 100644 +index 85c5280..0000000 +--- a/package/kernel/mac80211/patches/090-linux_3_18_12_compat.patch ++++ /dev/null +@@ -1,29 +0,0 @@ +---- a/backport-include/linux/wait.h +-+++ b/backport-include/linux/wait.h +-@@ -23,7 +23,7 @@ backport_wait_on_bit_io(void *word, int +- +- #endif +- +--#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) +-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,12) +- #define WQ_FLAG_WOKEN 0x02 +- +- #define wait_woken LINUX_BACKPORT(wait_woken) +---- a/compat/backport-3.19.c +-+++ b/compat/backport-3.19.c +-@@ -15,6 +15,7 @@ +- #include +- #include +- +-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,12) +- static inline bool is_kthread_should_stop(void) +- { +- return (current->flags & PF_KTHREAD) && kthread_should_stop(); +-@@ -79,6 +80,7 @@ int woken_wake_function(wait_queue_t *wa +- return default_wake_function(wait, mode, sync, key); +- } +- EXPORT_SYMBOL(woken_wake_function); +-+#endif +- +- #ifdef __BACKPORT_NETDEV_RSS_KEY_FILL +- u8 netdev_rss_key[NETDEV_RSS_KEY_LEN]; +diff --git a/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch +new file mode 100644 +index 0000000..07dde54 +--- /dev/null ++++ b/package/kernel/mac80211/patches/100-remove-cryptoapi-dependencies.patch +@@ -0,0 +1,376 @@ ++--- a/net/mac80211/Kconfig +++++ b/net/mac80211/Kconfig ++@@ -5,8 +5,6 @@ config MAC80211 ++ depends on CRYPTO ++ depends on CRYPTO_ARC4 ++ depends on CRYPTO_AES ++- select BPAUTO_CRYPTO_CCM ++- depends on CRYPTO_GCM ++ depends on CRC32 ++ select BPAUTO_AVERAGE ++ ---help--- ++--- a/net/mac80211/Makefile +++++ b/net/mac80211/Makefile ++@@ -15,9 +15,7 @@ mac80211-y := \ ++ michael.o \ ++ tkip.o \ ++ aes_ccm.o \ ++- aes_gcm.o \ ++ aes_cmac.o \ ++- aes_gmac.o \ ++ cfg.o \ ++ ethtool.o \ ++ rx.o \ ++--- a/net/mac80211/aes_ccm.c +++++ b/net/mac80211/aes_ccm.c ++@@ -13,89 +13,132 @@ ++ #include ++ #include ++ #include +++#include ++ ++ #include ++ #include "key.h" ++ #include "aes_ccm.h" ++ ++-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, ++- u8 *data, size_t data_len, u8 *mic, ++- 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); +++ +++ /* Extra Authenticate-only data (always two AES blocks) */ +++ for (i = 0; i < AES_BLOCK_SIZE; i++) +++ aad[i] ^= b[i]; +++ crypto_cipher_encrypt_one(tfm, b, aad); +++ +++ aad += AES_BLOCK_SIZE; +++ +++ for (i = 0; i < AES_BLOCK_SIZE; i++) +++ aad[i] ^= b[i]; +++ crypto_cipher_encrypt_one(tfm, a, aad); ++ ++- 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) +++{ +++ 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; +++ +++ 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); +++ +++ /* 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; +++ +++ /* Authentication followed by encryption */ +++ for (i = 0; i < blen; i++) +++ b[i] ^= pos[i]; +++ crypto_cipher_encrypt_one(tfm, b, b); +++ +++ b_0[14] = (j >> 8) & 0xff; +++ b_0[15] = j & 0xff; +++ crypto_cipher_encrypt_one(tfm, e, b_0); +++ for (i = 0; i < blen; i++) +++ *cpos++ = *pos++ ^ e[i]; +++ } ++ ++- crypto_aead_encrypt(aead_req); +++ for (i = 0; i < mic_len; i++) +++ mic[i] = b[i] ^ s_0[i]; ++ } ++ ++-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len) ++ { ++- struct scatterlist sg[3]; ++- 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; ++- ++- 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]; +++ +++ 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); +++ +++ /* 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; +++ +++ /* Decryption followed by authentication */ +++ b_0[14] = (j >> 8) & 0xff; +++ b_0[15] = j & 0xff; +++ crypto_cipher_encrypt_one(tfm, b, b_0); +++ for (i = 0; i < blen; i++) { +++ *pos = *cpos++ ^ b[i]; +++ a[i] ^= *pos++; +++ } +++ crypto_cipher_encrypt_one(tfm, a, a); +++ } +++ +++ for (i = 0; i < mic_len; i++) { +++ if ((mic[i] ^ s_0[i]) != a[i]) +++ return -1; +++ } ++ ++- return crypto_aead_decrypt(aead_req); +++ return 0; ++ } ++ ++-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], ++- size_t key_len, ++- size_t mic_len) +++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], +++ size_t key_len, +++ size_t mic_len) ++ { ++- 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; ++- ++- err = crypto_aead_setkey(tfm, key, key_len); ++- if (err) ++- goto free_aead; ++- err = crypto_aead_setauthsize(tfm, mic_len); ++- if (err) ++- goto free_aead; +++ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); +++ if (!IS_ERR(tfm)) +++ crypto_cipher_setkey(tfm, key, key_len); ++ ++ return tfm; ++- ++-free_aead: ++- crypto_free_aead(tfm); ++- return ERR_PTR(err); ++ } ++ ++-void ieee80211_aes_key_free(struct crypto_aead *tfm) +++ +++void ieee80211_aes_key_free(struct crypto_cipher *tfm) ++ { ++- crypto_free_aead(tfm); +++ crypto_free_cipher(tfm); ++ } ++--- a/net/mac80211/aes_ccm.h +++++ b/net/mac80211/aes_ccm.h ++@@ -12,15 +12,15 @@ ++ ++ #include ++ ++-struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], ++- size_t key_len, ++- size_t mic_len); ++-void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[], +++ size_t key_len, +++ size_t mic_len); +++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); ++-int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +++int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, ++ u8 *data, size_t data_len, u8 *mic, ++ size_t mic_len); ++-void ieee80211_aes_key_free(struct crypto_aead *tfm); +++void ieee80211_aes_key_free(struct crypto_cipher *tfm); ++ ++ #endif /* AES_CCM_H */ ++--- a/net/mac80211/aes_gcm.h +++++ b/net/mac80211/aes_gcm.h ++@@ -11,12 +11,28 @@ ++ ++ #include ++ ++-void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++- u8 *data, size_t data_len, u8 *mic); ++-int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, ++- u8 *data, size_t data_len, u8 *mic); ++-struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], ++- size_t key_len); ++-void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm); +++static inline void +++ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, +++ u8 *data, size_t data_len, u8 *mic) +++{ +++} +++ +++static inline int +++ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, +++ u8 *data, size_t data_len, u8 *mic) +++{ +++ return -EOPNOTSUPP; +++} +++ +++static inline struct crypto_aead * +++ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len) +++{ +++ return NULL; +++} +++ +++static inline void +++ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) +++{ +++} ++ ++ #endif /* AES_GCM_H */ ++--- a/net/mac80211/aes_gmac.h +++++ b/net/mac80211/aes_gmac.h ++@@ -11,10 +11,22 @@ ++ ++ #include ++ ++-struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], ++- size_t key_len); ++-int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, ++- const u8 *data, size_t data_len, u8 *mic); ++-void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm); +++static inline struct crypto_aead * +++ieee80211_aes_gmac_key_setup(const u8 key[], size_t key_len) +++{ +++ return NULL; +++} +++ +++static inline int +++ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, +++ const u8 *data, size_t data_len, u8 *mic) +++{ +++ return -EOPNOTSUPP; +++} +++ +++static inline void +++ieee80211_aes_gmac_key_free(struct crypto_aead *tfm) +++{ +++} ++ ++ #endif /* AES_GMAC_H */ ++--- a/net/mac80211/key.h +++++ b/net/mac80211/key.h ++@@ -84,7 +84,7 @@ struct ieee80211_key { ++ * Management frames. ++ */ ++ u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; ++- struct crypto_aead *tfm; +++ struct crypto_cipher *tfm; ++ u32 replays; /* dot11RSNAStatsCCMPReplays */ ++ } ccmp; ++ struct { ++--- a/net/mac80211/wpa.c +++++ b/net/mac80211/wpa.c ++@@ -304,7 +304,8 @@ ieee80211_crypto_tkip_decrypt(struct iee ++ } ++ ++ ++-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) +++static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, +++ u16 data_len) ++ { ++ __le16 mask_fc; ++ int a4_included, mgmt; ++@@ -334,14 +335,8 @@ static void ccmp_special_blocks(struct s ++ else ++ qos_tid = 0; ++ ++- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC ++- * mode authentication are not allowed to collide, yet both are derived ++- * from this vector b_0. We only set L := 1 here to indicate that the ++- * data size can be represented in (L+1) bytes. The CCM layer will take ++- * care of storing the data length in the top (L+1) bytes and setting ++- * and clearing the other bits as is required to derive the two IVs. ++- */ ++- b_0[0] = 0x1; +++ /* First block, b_0 */ +++ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ ++ ++ /* Nonce: Nonce Flags | A2 | PN ++ * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) ++@@ -349,6 +344,8 @@ static void ccmp_special_blocks(struct s ++ b_0[1] = qos_tid | (mgmt << 4); ++ memcpy(&b_0[2], hdr->addr2, ETH_ALEN); ++ memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); +++ /* l(m) */ +++ put_unaligned_be16(data_len, &b_0[14]); ++ ++ /* AAD (extra authenticate-only data) / masked 802.11 header ++ * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ ++@@ -460,7 +457,7 @@ static int ccmp_encrypt_skb(struct ieee8 ++ return 0; ++ ++ pos += IEEE80211_CCMP_HDR_LEN; ++- ccmp_special_blocks(skb, pn, b_0, aad); +++ ccmp_special_blocks(skb, pn, b_0, aad, len); ++ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, ++ skb_put(skb, mic_len), mic_len); ++ ++@@ -531,7 +528,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee ++ u8 aad[2 * AES_BLOCK_SIZE]; ++ u8 b_0[AES_BLOCK_SIZE]; ++ /* hardware didn't decrypt/verify MIC */ ++- ccmp_special_blocks(skb, pn, b_0, aad); +++ ccmp_special_blocks(skb, pn, b_0, aad, data_len); ++ ++ if (ieee80211_aes_ccm_decrypt( ++ key->u.ccmp.tfm, b_0, aad, +diff --git a/package/kernel/mac80211/patches/100-revert-cryptoapi-ports.patch b/package/kernel/mac80211/patches/100-revert-cryptoapi-ports.patch +deleted file mode 100644 +index ceca952..0000000 +--- a/package/kernel/mac80211/patches/100-revert-cryptoapi-ports.patch ++++ /dev/null +@@ -1,2055 +0,0 @@ +-This patch reverts the following commits from wireless-testing: +- +-8ade538bf39b1ee53418528fdacd36b8e65621b9 +-56c52da2d554f081e8fce58ecbcf6a40c605b95b +-2b2ba0db1c820d04d5143452d70012cd44d7b578 +-00b9cfa3ff38401bd70c34b250ca13e5ea347b4a +-4f031fa9f188b2b0641ac20087d9e16bcfb4e49d +-6e1ee5d2e9e411892b5d84e3ea93e3fc88ac786c +-30ef7ef9672d92ab2cac37f60a31955c118321e7 +-f359d3fe832e49eeec2232b2af5a9e3aee6b4862 (only the changes in aes_cmac.{c,h}) +-7ec7c4a9a686c608315739ab6a2b0527a240883c +---- +- +---- a/include/linux/ieee80211.h +-+++ b/include/linux/ieee80211.h +-@@ -1017,15 +1017,6 @@ struct ieee80211_mmie { +- u8 mic[8]; +- } __packed; +- +--/* Management MIC information element (IEEE 802.11w) for GMAC and CMAC-256 */ +--struct ieee80211_mmie_16 { +-- u8 element_id; +-- u8 length; +-- __le16 key_id; +-- u8 sequence_number[6]; +-- u8 mic[16]; +--} __packed; +-- +- struct ieee80211_vendor_ie { +- u8 element_id; +- u8 len; +---- a/include/net/mac80211.h +-+++ b/include/net/mac80211.h +-@@ -1306,8 +1306,8 @@ struct ieee80211_vif *wdev_to_ieee80211_ +- * @IEEE80211_KEY_FLAG_PAIRWISE: Set by mac80211, this flag indicates +- * that the key is pairwise rather then a shared key. +- * @IEEE80211_KEY_FLAG_SW_MGMT_TX: This flag should be set by the driver for a +-- * CCMP/GCMP key if it requires CCMP/GCMP encryption of management frames +-- * (MFP) to be done in software. +-+ * CCMP key if it requires CCMP encryption of management frames (MFP) to +-+ * be done in software. +- * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver +- * if space should be prepared for the IV, but the IV +- * itself should not be generated. Do not set together with +-@@ -1322,7 +1322,7 @@ struct ieee80211_vif *wdev_to_ieee80211_ +- * RX, if your crypto engine can't deal with TX you can also set the +- * %IEEE80211_KEY_FLAG_SW_MGMT_TX flag to encrypt such frames in SW. +- * @IEEE80211_KEY_FLAG_GENERATE_IV_MGMT: This flag should be set by the +-- * driver for a CCMP/GCMP key to indicate that is requires IV generation +-+ * driver for a CCMP key to indicate that is requires IV generation +- * only for managment frames (MFP). +- * @IEEE80211_KEY_FLAG_RESERVE_TAILROOM: This flag should be set by the +- * driver for a key to indicate that sufficient tailroom must always +-@@ -4112,10 +4112,6 @@ void ieee80211_aes_cmac_calculate_k1_k2( +- * reverse order than in packet) +- * @aes_cmac: PN data, most significant byte first (big endian, +- * reverse order than in packet) +-- * @aes_gmac: PN data, most significant byte first (big endian, +-- * reverse order than in packet) +-- * @gcmp: PN data, most significant byte first (big endian, +-- * reverse order than in packet) +- */ +- struct ieee80211_key_seq { +- union { +-@@ -4129,12 +4125,6 @@ struct ieee80211_key_seq { +- struct { +- u8 pn[6]; +- } aes_cmac; +-- struct { +-- u8 pn[6]; +-- } aes_gmac; +-- struct { +-- u8 pn[6]; +-- } gcmp; +- }; +- }; +- +-@@ -4159,7 +4149,7 @@ void ieee80211_get_key_tx_seq(struct iee +- * ieee80211_get_key_rx_seq - get key RX sequence counter +- * +- * @keyconf: the parameter passed with the set key +-- * @tid: The TID, or -1 for the management frame value (CCMP/GCMP only); +-+ * @tid: The TID, or -1 for the management frame value (CCMP only); +- * the value on TID 0 is also used for non-QoS frames. For +- * CMAC, only TID 0 is valid. +- * @seq: buffer to receive the sequence data +-@@ -4195,7 +4185,7 @@ void ieee80211_set_key_tx_seq(struct iee +- * ieee80211_set_key_rx_seq - set key RX sequence counter +- * +- * @keyconf: the parameter passed with the set key +-- * @tid: The TID, or -1 for the management frame value (CCMP/GCMP only); +-+ * @tid: The TID, or -1 for the management frame value (CCMP only); +- * the value on TID 0 is also used for non-QoS frames. For +- * CMAC, only TID 0 is valid. +- * @seq: new sequence data +---- a/net/mac80211/Kconfig +-+++ b/net/mac80211/Kconfig +-@@ -5,8 +5,6 @@ config MAC80211 +- depends on CRYPTO +- depends on CRYPTO_ARC4 +- depends on CRYPTO_AES +-- select BPAUTO_CRYPTO_CCM +-- depends on CRYPTO_GCM +- depends on CRC32 +- select BPAUTO_AVERAGE +- ---help--- +---- a/net/mac80211/Makefile +-+++ b/net/mac80211/Makefile +-@@ -15,9 +15,7 @@ mac80211-y := \ +- michael.o \ +- tkip.o \ +- aes_ccm.o \ +-- aes_gcm.o \ +- aes_cmac.o \ +-- aes_gmac.o \ +- cfg.o \ +- ethtool.o \ +- rx.o \ +---- a/net/mac80211/aes_ccm.c +-+++ b/net/mac80211/aes_ccm.c +-@@ -2,8 +2,6 @@ +- * Copyright 2003-2004, Instant802 Networks, Inc. +- * Copyright 2005-2006, Devicescape Software, Inc. +- * +-- * Rewrite: Copyright (C) 2013 Linaro Ltd +-- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License version 2 as +- * published by the Free Software Foundation. +-@@ -19,82 +17,134 @@ +- #include "key.h" +- #include "aes_ccm.h" +- +--void ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +-- u8 *data, size_t data_len, u8 *mic, +-- size_t mic_len) +-+static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a) +-+{ +-+ int i; +-+ u8 *b_0, *aad, *b, *s_0; +-+ +-+ b_0 = scratch + 3 * AES_BLOCK_SIZE; +-+ aad = scratch + 4 * AES_BLOCK_SIZE; +-+ b = scratch; +-+ s_0 = scratch + AES_BLOCK_SIZE; +-+ +-+ crypto_cipher_encrypt_one(tfm, b, b_0); +-+ +-+ /* Extra Authenticate-only data (always two AES blocks) */ +-+ for (i = 0; i < AES_BLOCK_SIZE; i++) +-+ aad[i] ^= b[i]; +-+ crypto_cipher_encrypt_one(tfm, b, aad); +-+ +-+ aad += AES_BLOCK_SIZE; +-+ +-+ for (i = 0; i < AES_BLOCK_SIZE; i++) +-+ aad[i] ^= b[i]; +-+ crypto_cipher_encrypt_one(tfm, a, aad); +-+ +-+ /* Mask out bits from auth-only-b_0 */ +-+ b_0[0] &= 0x07; +-+ +-+ /* S_0 is used to encrypt T (= MIC) */ +-+ b_0[14] = 0; +-+ b_0[15] = 0; +-+ crypto_cipher_encrypt_one(tfm, s_0, b_0); +-+} +-+ +-+ +-+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, +-+ u8 *data, size_t data_len, +-+ u8 *cdata, u8 *mic) +- { +-- struct scatterlist assoc, pt, ct[2]; +-+ int i, j, last_len, num_blocks; +-+ u8 *pos, *cpos, *b, *s_0, *e, *b_0; +- +-- 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; +-- +-- memset(aead_req, 0, sizeof(aead_req_data)); +-- +-- sg_init_one(&pt, data, data_len); +-- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); +-- sg_init_table(ct, 2); +-- sg_set_buf(&ct[0], data, data_len); +-- sg_set_buf(&ct[1], mic, mic_len); +-- +-- aead_request_set_tfm(aead_req, tfm); +-- aead_request_set_assoc(aead_req, &assoc, assoc.length); +-- aead_request_set_crypt(aead_req, &pt, ct, data_len, b_0); +-+ b = scratch; +-+ s_0 = scratch + AES_BLOCK_SIZE; +-+ e = scratch + 2 * AES_BLOCK_SIZE; +-+ b_0 = scratch + 3 * AES_BLOCK_SIZE; +-+ +-+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); +-+ last_len = data_len % AES_BLOCK_SIZE; +-+ aes_ccm_prepare(tfm, scratch, b); +-+ +-+ /* Process payload blocks */ +-+ pos = data; +-+ cpos = cdata; +-+ for (j = 1; j <= num_blocks; j++) { +-+ int blen = (j == num_blocks && last_len) ? +-+ last_len : AES_BLOCK_SIZE; +-+ +-+ /* Authentication followed by encryption */ +-+ for (i = 0; i < blen; i++) +-+ b[i] ^= pos[i]; +-+ crypto_cipher_encrypt_one(tfm, b, b); +-+ +-+ b_0[14] = (j >> 8) & 0xff; +-+ b_0[15] = j & 0xff; +-+ crypto_cipher_encrypt_one(tfm, e, b_0); +-+ for (i = 0; i < blen; i++) +-+ *cpos++ = *pos++ ^ e[i]; +-+ } +- +-- crypto_aead_encrypt(aead_req); +-+ for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) +-+ mic[i] = b[i] ^ s_0[i]; +- } +- +--int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +-- u8 *data, size_t data_len, u8 *mic, +-- size_t mic_len) +-+ +-+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, +-+ u8 *cdata, size_t data_len, u8 *mic, u8 *data) +- { +-- struct scatterlist assoc, pt, ct[2]; +-- 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; +-- +-- if (data_len == 0) +-- return -EINVAL; +-- +-- memset(aead_req, 0, sizeof(aead_req_data)); +-- +-- sg_init_one(&pt, data, data_len); +-- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); +-- sg_init_table(ct, 2); +-- sg_set_buf(&ct[0], data, data_len); +-- sg_set_buf(&ct[1], mic, mic_len); +-- +-- aead_request_set_tfm(aead_req, tfm); +-- aead_request_set_assoc(aead_req, &assoc, assoc.length); +-- aead_request_set_crypt(aead_req, ct, &pt, data_len + mic_len, b_0); +-+ int i, j, last_len, num_blocks; +-+ u8 *pos, *cpos, *b, *s_0, *a, *b_0; +-+ +-+ b = scratch; +-+ s_0 = scratch + AES_BLOCK_SIZE; +-+ a = scratch + 2 * AES_BLOCK_SIZE; +-+ b_0 = scratch + 3 * AES_BLOCK_SIZE; +-+ +-+ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_SIZE); +-+ last_len = data_len % AES_BLOCK_SIZE; +-+ aes_ccm_prepare(tfm, scratch, a); +-+ +-+ /* Process payload blocks */ +-+ cpos = cdata; +-+ pos = data; +-+ for (j = 1; j <= num_blocks; j++) { +-+ int blen = (j == num_blocks && last_len) ? +-+ last_len : AES_BLOCK_SIZE; +-+ +-+ /* Decryption followed by authentication */ +-+ b_0[14] = (j >> 8) & 0xff; +-+ b_0[15] = j & 0xff; +-+ crypto_cipher_encrypt_one(tfm, b, b_0); +-+ for (i = 0; i < blen; i++) { +-+ *pos = *cpos++ ^ b[i]; +-+ a[i] ^= *pos++; +-+ } +-+ crypto_cipher_encrypt_one(tfm, a, a); +-+ } +-+ +-+ for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) { +-+ if ((mic[i] ^ s_0[i]) != a[i]) +-+ return -1; +-+ } +- +-- return crypto_aead_decrypt(aead_req); +-+ return 0; +- } +- +--struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], +-- size_t key_len, +-- size_t mic_len) +-+ +-+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) +- { +-- 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; +-- +-- err = crypto_aead_setkey(tfm, key, key_len); +-- if (!err) +-- err = crypto_aead_setauthsize(tfm, mic_len); +-- if (!err) +-- return tfm; +-+ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); +-+ if (!IS_ERR(tfm)) +-+ crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP); +- +-- crypto_free_aead(tfm); +-- return ERR_PTR(err); +-+ return tfm; +- } +- +--void ieee80211_aes_key_free(struct crypto_aead *tfm) +-+ +-+void ieee80211_aes_key_free(struct crypto_cipher *tfm) +- { +-- crypto_free_aead(tfm); +-+ crypto_free_cipher(tfm); +- } +---- a/net/mac80211/aes_ccm.h +-+++ b/net/mac80211/aes_ccm.h +-@@ -12,15 +12,13 @@ +- +- #include +- +--struct crypto_aead *ieee80211_aes_key_setup_encrypt(const u8 key[], +-- size_t key_len, +-- size_t mic_len); +--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); +--int ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, +-- u8 *data, size_t data_len, u8 *mic, +-- size_t mic_len); +--void ieee80211_aes_key_free(struct crypto_aead *tfm); +-+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); +-+void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, +-+ u8 *data, size_t data_len, +-+ u8 *cdata, u8 *mic); +-+int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, +-+ u8 *cdata, size_t data_len, +-+ u8 *mic, u8 *data); +-+void ieee80211_aes_key_free(struct crypto_cipher *tfm); +- +- #endif /* AES_CCM_H */ +---- a/net/mac80211/aes_cmac.c +-+++ b/net/mac80211/aes_cmac.c +-@@ -18,8 +18,8 @@ +- #include "key.h" +- #include "aes_cmac.h" +- +-+#define AES_CMAC_KEY_LEN 16 +- #define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */ +--#define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */ +- #define AAD_LEN 20 +- +- +-@@ -35,9 +35,9 @@ static void gf_mulx(u8 *pad) +- pad[AES_BLOCK_SIZE - 1] ^= 0x87; +- } +- +--static void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, +-- const u8 *addr[], const size_t *len, u8 *mac, +-- size_t mac_len) +-+ +-+static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, +-+ const u8 *addr[], const size_t *len, u8 *mac) +- { +- u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; +- const u8 *pos, *end; +-@@ -88,7 +88,7 @@ static void aes_cmac_vector(struct crypt +- for (i = 0; i < AES_BLOCK_SIZE; i++) +- pad[i] ^= cbc[i]; +- crypto_cipher_encrypt_one(tfm, pad, pad); +-- memcpy(mac, pad, mac_len); +-+ memcpy(mac, pad, CMAC_TLEN); +- } +- +- +-@@ -107,35 +107,17 @@ void ieee80211_aes_cmac(struct crypto_ci +- addr[2] = zero; +- len[2] = CMAC_TLEN; +- +-- aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN); +-+ aes_128_cmac_vector(tfm, 3, addr, len, mic); +- } +- +--void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, +-- const u8 *data, size_t data_len, u8 *mic) +--{ +-- const u8 *addr[3]; +-- size_t len[3]; +-- u8 zero[CMAC_TLEN_256]; +-- +-- memset(zero, 0, CMAC_TLEN_256); +-- addr[0] = aad; +-- len[0] = AAD_LEN; +-- addr[1] = data; +-- len[1] = data_len - CMAC_TLEN_256; +-- addr[2] = zero; +-- len[2] = CMAC_TLEN_256; +-- +-- aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256); +--} +- +--struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], +-- size_t key_len) +-+struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]) +- { +- struct crypto_cipher *tfm; +- +- tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); +- if (!IS_ERR(tfm)) +-- crypto_cipher_setkey(tfm, key, key_len); +-+ crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN); +- +- return tfm; +- } +---- a/net/mac80211/aes_cmac.h +-+++ b/net/mac80211/aes_cmac.h +-@@ -11,12 +11,9 @@ +- +- #include +- +--struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[], +-- size_t key_len); +-+struct crypto_cipher * ieee80211_aes_cmac_key_setup(const u8 key[]); +- void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad, +- const u8 *data, size_t data_len, u8 *mic); +--void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad, +-- const u8 *data, size_t data_len, u8 *mic); +- void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm); +- +- #endif /* AES_CMAC_H */ +---- a/net/mac80211/aes_gcm.c +-+++ /dev/null +-@@ -1,95 +0,0 @@ +--/* +-- * Copyright 2014-2015, Qualcomm Atheros, Inc. +-- * +-- * This program is free software; you can redistribute it and/or modify +-- * it under the terms of the GNU General Public License version 2 as +-- * published by the Free Software Foundation. +-- */ +-- +--#include +--#include +--#include +--#include +--#include +-- +--#include +--#include "key.h" +--#include "aes_gcm.h" +-- +--void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, +-- u8 *data, size_t data_len, u8 *mic) +--{ +-- struct scatterlist assoc, pt, ct[2]; +-- +-- 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; +-- +-- memset(aead_req, 0, sizeof(aead_req_data)); +-- +-- sg_init_one(&pt, data, data_len); +-- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); +-- sg_init_table(ct, 2); +-- sg_set_buf(&ct[0], data, data_len); +-- sg_set_buf(&ct[1], mic, IEEE80211_GCMP_MIC_LEN); +-- +-- aead_request_set_tfm(aead_req, tfm); +-- aead_request_set_assoc(aead_req, &assoc, assoc.length); +-- aead_request_set_crypt(aead_req, &pt, ct, data_len, j_0); +-- +-- crypto_aead_encrypt(aead_req); +--} +-- +--int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, +-- u8 *data, size_t data_len, u8 *mic) +--{ +-- struct scatterlist assoc, pt, ct[2]; +-- 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; +-- +-- if (data_len == 0) +-- return -EINVAL; +-- +-- memset(aead_req, 0, sizeof(aead_req_data)); +-- +-- sg_init_one(&pt, data, data_len); +-- sg_init_one(&assoc, &aad[2], be16_to_cpup((__be16 *)aad)); +-- sg_init_table(ct, 2); +-- sg_set_buf(&ct[0], data, data_len); +-- sg_set_buf(&ct[1], mic, IEEE80211_GCMP_MIC_LEN); +-- +-- aead_request_set_tfm(aead_req, tfm); +-- aead_request_set_assoc(aead_req, &assoc, assoc.length); +-- aead_request_set_crypt(aead_req, ct, &pt, +-- data_len + IEEE80211_GCMP_MIC_LEN, j_0); +-- +-- return crypto_aead_decrypt(aead_req); +--} +-- +--struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], +-- size_t key_len) +--{ +-- struct crypto_aead *tfm; +-- int err; +-- +-- tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); +-- if (IS_ERR(tfm)) +-- return tfm; +-- +-- err = crypto_aead_setkey(tfm, key, key_len); +-- if (!err) +-- err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN); +-- if (!err) +-- return tfm; +-- +-- crypto_free_aead(tfm); +-- return ERR_PTR(err); +--} +-- +--void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm) +--{ +-- crypto_free_aead(tfm); +--} +---- a/net/mac80211/aes_gcm.h +-+++ /dev/null +-@@ -1,22 +0,0 @@ +--/* +-- * Copyright 2014-2015, Qualcomm Atheros, Inc. +-- * +-- * This program is free software; you can redistribute it and/or modify +-- * it under the terms of the GNU General Public License version 2 as +-- * published by the Free Software Foundation. +-- */ +-- +--#ifndef AES_GCM_H +--#define AES_GCM_H +-- +--#include +-- +--void ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, +-- u8 *data, size_t data_len, u8 *mic); +--int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad, +-- u8 *data, size_t data_len, u8 *mic); +--struct crypto_aead *ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], +-- size_t key_len); +--void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm); +-- +--#endif /* AES_GCM_H */ +---- a/net/mac80211/aes_gmac.c +-+++ /dev/null +-@@ -1,84 +0,0 @@ +--/* +-- * AES-GMAC for IEEE 802.11 BIP-GMAC-128 and BIP-GMAC-256 +-- * Copyright 2015, Qualcomm Atheros, Inc. +-- * +-- * This program is free software; you can redistribute it and/or modify +-- * it under the terms of the GNU General Public License version 2 as +-- * published by the Free Software Foundation. +-- */ +-- +--#include +--#include +--#include +--#include +--#include +-- +--#include +--#include "key.h" +--#include "aes_gmac.h" +-- +--#define GMAC_MIC_LEN 16 +--#define GMAC_NONCE_LEN 12 +--#define AAD_LEN 20 +-- +--int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, +-- const u8 *data, size_t data_len, u8 *mic) +--{ +-- struct scatterlist sg[3], ct[1]; +-- 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; +-- u8 zero[GMAC_MIC_LEN], iv[AES_BLOCK_SIZE]; +-- +-- if (data_len < GMAC_MIC_LEN) +-- return -EINVAL; +-- +-- memset(aead_req, 0, sizeof(aead_req_data)); +-- +-- memset(zero, 0, GMAC_MIC_LEN); +-- sg_init_table(sg, 3); +-- sg_set_buf(&sg[0], aad, AAD_LEN); +-- sg_set_buf(&sg[1], data, data_len - GMAC_MIC_LEN); +-- sg_set_buf(&sg[2], zero, GMAC_MIC_LEN); +-- +-- memcpy(iv, nonce, GMAC_NONCE_LEN); +-- memset(iv + GMAC_NONCE_LEN, 0, sizeof(iv) - GMAC_NONCE_LEN); +-- iv[AES_BLOCK_SIZE - 1] = 0x01; +-- +-- sg_init_table(ct, 1); +-- sg_set_buf(&ct[0], mic, GMAC_MIC_LEN); +-- +-- aead_request_set_tfm(aead_req, tfm); +-- aead_request_set_assoc(aead_req, sg, AAD_LEN + data_len); +-- aead_request_set_crypt(aead_req, NULL, ct, 0, iv); +-- +-- crypto_aead_encrypt(aead_req); +-- +-- return 0; +--} +-- +--struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], +-- size_t key_len) +--{ +-- struct crypto_aead *tfm; +-- int err; +-- +-- tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); +-- if (IS_ERR(tfm)) +-- return tfm; +-- +-- err = crypto_aead_setkey(tfm, key, key_len); +-- if (!err) +-- return tfm; +-- if (!err) +-- err = crypto_aead_setauthsize(tfm, GMAC_MIC_LEN); +-- +-- crypto_free_aead(tfm); +-- return ERR_PTR(err); +--} +-- +--void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm) +--{ +-- crypto_free_aead(tfm); +--} +---- a/net/mac80211/aes_gmac.h +-+++ /dev/null +-@@ -1,20 +0,0 @@ +--/* +-- * Copyright 2015, Qualcomm Atheros, Inc. +-- * +-- * This program is free software; you can redistribute it and/or modify +-- * it under the terms of the GNU General Public License version 2 as +-- * published by the Free Software Foundation. +-- */ +-- +--#ifndef AES_GMAC_H +--#define AES_GMAC_H +-- +--#include +-- +--struct crypto_aead *ieee80211_aes_gmac_key_setup(const u8 key[], +-- size_t key_len); +--int ieee80211_aes_gmac(struct crypto_aead *tfm, const u8 *aad, u8 *nonce, +-- const u8 *data, size_t data_len, u8 *mic); +--void ieee80211_aes_gmac_key_free(struct crypto_aead *tfm); +-- +--#endif /* AES_GMAC_H */ +---- a/net/mac80211/cfg.c +-+++ b/net/mac80211/cfg.c +-@@ -162,13 +162,8 @@ static int ieee80211_add_key(struct wiph +- return -EINVAL; +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +- break; +- default: +- cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type); +-@@ -353,7 +348,6 @@ static int ieee80211_get_key(struct wiph +- params.seq_len = 6; +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- pn64 = atomic64_read(&key->u.ccmp.tx_pn); +- seq[0] = pn64; +- seq[1] = pn64 >> 8; +-@@ -365,35 +359,10 @@ static int ieee80211_get_key(struct wiph +- params.seq_len = 6; +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); +- seq[0] = pn64; +- seq[1] = pn64 >> 8; +- seq[2] = pn64 >> 16; +-- seq[3] = pn64 >> 24; +-- seq[4] = pn64 >> 32; +-- seq[5] = pn64 >> 40; +-- params.seq = seq; +-- params.seq_len = 6; +-- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- pn64 = atomic64_read(&key->u.aes_gmac.tx_pn); +-- seq[0] = pn64; +-- seq[1] = pn64 >> 8; +-- seq[2] = pn64 >> 16; +-- seq[3] = pn64 >> 24; +-- seq[4] = pn64 >> 32; +-- seq[5] = pn64 >> 40; +-- params.seq = seq; +-- params.seq_len = 6; +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- pn64 = atomic64_read(&key->u.gcmp.tx_pn); +-- seq[0] = pn64; +-- seq[1] = pn64 >> 8; +-- seq[2] = pn64 >> 16; +- seq[3] = pn64 >> 24; +- seq[4] = pn64 >> 32; +- seq[5] = pn64 >> 40; +---- a/net/mac80211/debugfs_key.c +-+++ b/net/mac80211/debugfs_key.c +-@@ -94,33 +94,17 @@ static ssize_t key_tx_spec_read(struct f +- key->u.tkip.tx.iv16); +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- pn = atomic64_read(&key->u.ccmp.tx_pn); +- len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", +- (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), +- (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- pn = atomic64_read(&key->u.aes_cmac.tx_pn); +- len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", +- (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), +- (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); +- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- pn = atomic64_read(&key->u.aes_gmac.tx_pn); +-- len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", +-- (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), +-- (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- pn = atomic64_read(&key->u.gcmp.tx_pn); +-- len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n", +-- (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24), +-- (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn); +-- break; +- default: +- return 0; +- } +-@@ -150,7 +134,6 @@ static ssize_t key_rx_spec_read(struct f +- len = p - buf; +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { +- rpn = key->u.ccmp.rx_pn[i]; +- p += scnprintf(p, sizeof(buf)+buf-p, +-@@ -161,7 +144,6 @@ static ssize_t key_rx_spec_read(struct f +- len = p - buf; +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- rpn = key->u.aes_cmac.rx_pn; +- p += scnprintf(p, sizeof(buf)+buf-p, +- "%02x%02x%02x%02x%02x%02x\n", +-@@ -169,26 +151,6 @@ static ssize_t key_rx_spec_read(struct f +- rpn[3], rpn[4], rpn[5]); +- len = p - buf; +- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- rpn = key->u.aes_gmac.rx_pn; +-- p += scnprintf(p, sizeof(buf)+buf-p, +-- "%02x%02x%02x%02x%02x%02x\n", +-- rpn[0], rpn[1], rpn[2], +-- rpn[3], rpn[4], rpn[5]); +-- len = p - buf; +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { +-- rpn = key->u.gcmp.rx_pn[i]; +-- p += scnprintf(p, sizeof(buf)+buf-p, +-- "%02x%02x%02x%02x%02x%02x\n", +-- rpn[0], rpn[1], rpn[2], +-- rpn[3], rpn[4], rpn[5]); +-- } +-- len = p - buf; +-- break; +- default: +- return 0; +- } +-@@ -205,23 +167,12 @@ static ssize_t key_replays_read(struct f +- +- switch (key->conf.cipher) { +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays); +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- len = scnprintf(buf, sizeof(buf), "%u\n", +- key->u.aes_cmac.replays); +- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- len = scnprintf(buf, sizeof(buf), "%u\n", +-- key->u.aes_gmac.replays); +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- len = scnprintf(buf, sizeof(buf), "%u\n", key->u.gcmp.replays); +-- break; +- default: +- return 0; +- } +-@@ -238,15 +189,9 @@ static ssize_t key_icverrors_read(struct +- +- switch (key->conf.cipher) { +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- len = scnprintf(buf, sizeof(buf), "%u\n", +- key->u.aes_cmac.icverrors); +- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- len = scnprintf(buf, sizeof(buf), "%u\n", +-- key->u.aes_gmac.icverrors); +-- break; +- default: +- return 0; +- } +---- a/net/mac80211/key.c +-+++ b/net/mac80211/key.c +-@@ -24,8 +24,6 @@ +- #include "debugfs_key.h" +- #include "aes_ccm.h" +- #include "aes_cmac.h" +--#include "aes_gmac.h" +--#include "aes_gcm.h" +- +- +- /** +-@@ -164,13 +162,7 @@ static int ieee80211_key_enable_hw_accel +- case WLAN_CIPHER_SUITE_WEP104: +- case WLAN_CIPHER_SUITE_TKIP: +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +- /* all of these we can do in software - if driver can */ +- if (ret == 1) +- return 0; +-@@ -394,26 +386,7 @@ ieee80211_key_alloc(u32 cipher, int idx, +- * Initialize AES key state here as an optimization so that +- * it does not need to be initialized for every packet. +- */ +-- key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt( +-- key_data, key_len, IEEE80211_CCMP_MIC_LEN); +-- if (IS_ERR(key->u.ccmp.tfm)) { +-- err = PTR_ERR(key->u.ccmp.tfm); +-- kfree(key); +-- return ERR_PTR(err); +-- } +-- break; +-- case WLAN_CIPHER_SUITE_CCMP_256: +-- key->conf.iv_len = IEEE80211_CCMP_256_HDR_LEN; +-- key->conf.icv_len = IEEE80211_CCMP_256_MIC_LEN; +-- for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++) +-- for (j = 0; j < IEEE80211_CCMP_256_PN_LEN; j++) +-- key->u.ccmp.rx_pn[i][j] = +-- seq[IEEE80211_CCMP_256_PN_LEN - j - 1]; +-- /* Initialize AES key state here as an optimization so that +-- * it does not need to be initialized for every packet. +-- */ +-- key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt( +-- key_data, key_len, IEEE80211_CCMP_256_MIC_LEN); +-+ key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data); +- if (IS_ERR(key->u.ccmp.tfm)) { +- err = PTR_ERR(key->u.ccmp.tfm); +- kfree(key); +-@@ -421,12 +394,8 @@ ieee80211_key_alloc(u32 cipher, int idx, +- } +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- key->conf.iv_len = 0; +-- if (cipher == WLAN_CIPHER_SUITE_AES_CMAC) +-- key->conf.icv_len = sizeof(struct ieee80211_mmie); +-- else +-- key->conf.icv_len = sizeof(struct ieee80211_mmie_16); +-+ key->conf.icv_len = sizeof(struct ieee80211_mmie); +- if (seq) +- for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++) +- key->u.aes_cmac.rx_pn[j] = +-@@ -436,51 +405,13 @@ ieee80211_key_alloc(u32 cipher, int idx, +- * it does not need to be initialized for every packet. +- */ +- key->u.aes_cmac.tfm = +-- ieee80211_aes_cmac_key_setup(key_data, key_len); +-+ ieee80211_aes_cmac_key_setup(key_data); +- if (IS_ERR(key->u.aes_cmac.tfm)) { +- err = PTR_ERR(key->u.aes_cmac.tfm); +- kfree(key); +- return ERR_PTR(err); +- } +- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- key->conf.iv_len = 0; +-- key->conf.icv_len = sizeof(struct ieee80211_mmie_16); +-- if (seq) +-- for (j = 0; j < IEEE80211_GMAC_PN_LEN; j++) +-- key->u.aes_gmac.rx_pn[j] = +-- seq[IEEE80211_GMAC_PN_LEN - j - 1]; +-- /* Initialize AES key state here as an optimization so that +-- * it does not need to be initialized for every packet. +-- */ +-- key->u.aes_gmac.tfm = +-- ieee80211_aes_gmac_key_setup(key_data, key_len); +-- if (IS_ERR(key->u.aes_gmac.tfm)) { +-- err = PTR_ERR(key->u.aes_gmac.tfm); +-- kfree(key); +-- return ERR_PTR(err); +-- } +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- key->conf.iv_len = IEEE80211_GCMP_HDR_LEN; +-- key->conf.icv_len = IEEE80211_GCMP_MIC_LEN; +-- for (i = 0; seq && i < IEEE80211_NUM_TIDS + 1; i++) +-- for (j = 0; j < IEEE80211_GCMP_PN_LEN; j++) +-- key->u.gcmp.rx_pn[i][j] = +-- seq[IEEE80211_GCMP_PN_LEN - j - 1]; +-- /* Initialize AES key state here as an optimization so that +-- * it does not need to be initialized for every packet. +-- */ +-- key->u.gcmp.tfm = ieee80211_aes_gcm_key_setup_encrypt(key_data, +-- key_len); +-- if (IS_ERR(key->u.gcmp.tfm)) { +-- err = PTR_ERR(key->u.gcmp.tfm); +-- kfree(key); +-- return ERR_PTR(err); +-- } +-- break; +- default: +- if (cs) { +- size_t len = (seq_len > MAX_PN_LEN) ? +-@@ -502,24 +433,10 @@ ieee80211_key_alloc(u32 cipher, int idx, +- +- static void ieee80211_key_free_common(struct ieee80211_key *key) +- { +-- switch (key->conf.cipher) { +-- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +-+ if (key->conf.cipher == WLAN_CIPHER_SUITE_CCMP) +- ieee80211_aes_key_free(key->u.ccmp.tfm); +-- break; +-- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +-+ if (key->conf.cipher == WLAN_CIPHER_SUITE_AES_CMAC) +- ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm); +-- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- ieee80211_aes_gmac_key_free(key->u.aes_gmac.tfm); +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- ieee80211_aes_gcm_key_free(key->u.gcmp.tfm); +-- break; +-- } +- kzfree(key); +- } +- +-@@ -826,7 +743,6 @@ void ieee80211_get_key_tx_seq(struct iee +- seq->tkip.iv16 = key->u.tkip.tx.iv16; +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- pn64 = atomic64_read(&key->u.ccmp.tx_pn); +- seq->ccmp.pn[5] = pn64; +- seq->ccmp.pn[4] = pn64 >> 8; +-@@ -836,7 +752,6 @@ void ieee80211_get_key_tx_seq(struct iee +- seq->ccmp.pn[0] = pn64 >> 40; +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- pn64 = atomic64_read(&key->u.aes_cmac.tx_pn); +- seq->ccmp.pn[5] = pn64; +- seq->ccmp.pn[4] = pn64 >> 8; +-@@ -845,26 +760,6 @@ void ieee80211_get_key_tx_seq(struct iee +- seq->ccmp.pn[1] = pn64 >> 32; +- seq->ccmp.pn[0] = pn64 >> 40; +- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- pn64 = atomic64_read(&key->u.aes_gmac.tx_pn); +-- seq->ccmp.pn[5] = pn64; +-- seq->ccmp.pn[4] = pn64 >> 8; +-- seq->ccmp.pn[3] = pn64 >> 16; +-- seq->ccmp.pn[2] = pn64 >> 24; +-- seq->ccmp.pn[1] = pn64 >> 32; +-- seq->ccmp.pn[0] = pn64 >> 40; +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- pn64 = atomic64_read(&key->u.gcmp.tx_pn); +-- seq->gcmp.pn[5] = pn64; +-- seq->gcmp.pn[4] = pn64 >> 8; +-- seq->gcmp.pn[3] = pn64 >> 16; +-- seq->gcmp.pn[2] = pn64 >> 24; +-- seq->gcmp.pn[1] = pn64 >> 32; +-- seq->gcmp.pn[0] = pn64 >> 40; +-- break; +- default: +- WARN_ON(1); +- } +-@@ -887,7 +782,6 @@ void ieee80211_get_key_rx_seq(struct iee +- seq->tkip.iv16 = key->u.tkip.rx[tid].iv16; +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) +- return; +- if (tid < 0) +-@@ -897,29 +791,11 @@ void ieee80211_get_key_rx_seq(struct iee +- memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN); +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- if (WARN_ON(tid != 0)) +- return; +- pn = key->u.aes_cmac.rx_pn; +- memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN); +- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- if (WARN_ON(tid != 0)) +-- return; +-- pn = key->u.aes_gmac.rx_pn; +-- memcpy(seq->aes_gmac.pn, pn, IEEE80211_GMAC_PN_LEN); +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) +-- return; +-- if (tid < 0) +-- pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS]; +-- else +-- pn = key->u.gcmp.rx_pn[tid]; +-- memcpy(seq->gcmp.pn, pn, IEEE80211_GCMP_PN_LEN); +-- break; +- } +- } +- EXPORT_SYMBOL(ieee80211_get_key_rx_seq); +-@@ -938,7 +814,6 @@ void ieee80211_set_key_tx_seq(struct iee +- key->u.tkip.tx.iv16 = seq->tkip.iv16; +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- pn64 = (u64)seq->ccmp.pn[5] | +- ((u64)seq->ccmp.pn[4] << 8) | +- ((u64)seq->ccmp.pn[3] << 16) | +-@@ -948,7 +823,6 @@ void ieee80211_set_key_tx_seq(struct iee +- atomic64_set(&key->u.ccmp.tx_pn, pn64); +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- pn64 = (u64)seq->aes_cmac.pn[5] | +- ((u64)seq->aes_cmac.pn[4] << 8) | +- ((u64)seq->aes_cmac.pn[3] << 16) | +-@@ -957,26 +831,6 @@ void ieee80211_set_key_tx_seq(struct iee +- ((u64)seq->aes_cmac.pn[0] << 40); +- atomic64_set(&key->u.aes_cmac.tx_pn, pn64); +- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- pn64 = (u64)seq->aes_gmac.pn[5] | +-- ((u64)seq->aes_gmac.pn[4] << 8) | +-- ((u64)seq->aes_gmac.pn[3] << 16) | +-- ((u64)seq->aes_gmac.pn[2] << 24) | +-- ((u64)seq->aes_gmac.pn[1] << 32) | +-- ((u64)seq->aes_gmac.pn[0] << 40); +-- atomic64_set(&key->u.aes_gmac.tx_pn, pn64); +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- pn64 = (u64)seq->gcmp.pn[5] | +-- ((u64)seq->gcmp.pn[4] << 8) | +-- ((u64)seq->gcmp.pn[3] << 16) | +-- ((u64)seq->gcmp.pn[2] << 24) | +-- ((u64)seq->gcmp.pn[1] << 32) | +-- ((u64)seq->gcmp.pn[0] << 40); +-- atomic64_set(&key->u.gcmp.tx_pn, pn64); +-- break; +- default: +- WARN_ON(1); +- break; +-@@ -1000,7 +854,6 @@ void ieee80211_set_key_rx_seq(struct iee +- key->u.tkip.rx[tid].iv16 = seq->tkip.iv16; +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +- if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) +- return; +- if (tid < 0) +-@@ -1010,29 +863,11 @@ void ieee80211_set_key_rx_seq(struct iee +- memcpy(pn, seq->ccmp.pn, IEEE80211_CCMP_PN_LEN); +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +- if (WARN_ON(tid != 0)) +- return; +- pn = key->u.aes_cmac.rx_pn; +- memcpy(pn, seq->aes_cmac.pn, IEEE80211_CMAC_PN_LEN); +- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- if (WARN_ON(tid != 0)) +-- return; +-- pn = key->u.aes_gmac.rx_pn; +-- memcpy(pn, seq->aes_gmac.pn, IEEE80211_GMAC_PN_LEN); +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- if (WARN_ON(tid < -1 || tid >= IEEE80211_NUM_TIDS)) +-- return; +-- if (tid < 0) +-- pn = key->u.gcmp.rx_pn[IEEE80211_NUM_TIDS]; +-- else +-- pn = key->u.gcmp.rx_pn[tid]; +-- memcpy(pn, seq->gcmp.pn, IEEE80211_GCMP_PN_LEN); +-- break; +- default: +- WARN_ON(1); +- break; +---- a/net/mac80211/key.h +-+++ b/net/mac80211/key.h +-@@ -84,7 +84,7 @@ struct ieee80211_key { +- * Management frames. +- */ +- u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN]; +-- struct crypto_aead *tfm; +-+ struct crypto_cipher *tfm; +- u32 replays; /* dot11RSNAStatsCCMPReplays */ +- } ccmp; +- struct { +-@@ -95,24 +95,6 @@ struct ieee80211_key { +- u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ +- } aes_cmac; +- struct { +-- atomic64_t tx_pn; +-- u8 rx_pn[IEEE80211_GMAC_PN_LEN]; +-- struct crypto_aead *tfm; +-- u32 replays; /* dot11RSNAStatsCMACReplays */ +-- u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ +-- } aes_gmac; +-- struct { +-- atomic64_t tx_pn; +-- /* Last received packet number. The first +-- * IEEE80211_NUM_TIDS counters are used with Data +-- * frames and the last counter is used with Robust +-- * Management frames. +-- */ +-- u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_GCMP_PN_LEN]; +-- struct crypto_aead *tfm; +-- u32 replays; /* dot11RSNAStatsGCMPReplays */ +-- } gcmp; +-- struct { +- /* generic cipher scheme */ +- u8 rx_pn[IEEE80211_NUM_TIDS + 1][MAX_PN_LEN]; +- } gen; +---- a/net/mac80211/main.c +-+++ b/net/mac80211/main.c +-@@ -666,15 +666,9 @@ static int ieee80211_init_cipher_suites( +- WLAN_CIPHER_SUITE_WEP104, +- WLAN_CIPHER_SUITE_TKIP, +- WLAN_CIPHER_SUITE_CCMP, +-- WLAN_CIPHER_SUITE_CCMP_256, +-- WLAN_CIPHER_SUITE_GCMP, +-- WLAN_CIPHER_SUITE_GCMP_256, +- +- /* keep last -- depends on hw flags! */ +-- WLAN_CIPHER_SUITE_AES_CMAC, +-- WLAN_CIPHER_SUITE_BIP_CMAC_256, +-- WLAN_CIPHER_SUITE_BIP_GMAC_128, +-- WLAN_CIPHER_SUITE_BIP_GMAC_256, +-+ WLAN_CIPHER_SUITE_AES_CMAC +- }; +- +- if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL || +-@@ -713,7 +707,7 @@ static int ieee80211_init_cipher_suites( +- local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); +- +- if (!have_mfp) +-- local->hw.wiphy->n_cipher_suites -= 4; +-+ local->hw.wiphy->n_cipher_suites--; +- +- if (!have_wep) { +- local->hw.wiphy->cipher_suites += 2; +-@@ -730,42 +724,32 @@ static int ieee80211_init_cipher_suites( +- /* Driver specifies cipher schemes only (but not cipher suites +- * including the schemes) +- * +-- * We start counting ciphers defined by schemes, TKIP, CCMP, +-- * CCMP-256, GCMP, and GCMP-256 +-+ * We start counting ciphers defined by schemes, TKIP and CCMP +- */ +-- n_suites = local->hw.n_cipher_schemes + 5; +-+ n_suites = local->hw.n_cipher_schemes + 2; +- +- /* check if we have WEP40 and WEP104 */ +- if (have_wep) +- n_suites += 2; +- +-- /* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128, +-- * BIP-GMAC-256 +-- */ +-+ /* check if we have AES_CMAC */ +- if (have_mfp) +-- n_suites += 4; +-+ n_suites++; +- +- suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL); +- if (!suites) +- return -ENOMEM; +- +- suites[w++] = WLAN_CIPHER_SUITE_CCMP; +-- suites[w++] = WLAN_CIPHER_SUITE_CCMP_256; +- suites[w++] = WLAN_CIPHER_SUITE_TKIP; +-- suites[w++] = WLAN_CIPHER_SUITE_GCMP; +-- suites[w++] = WLAN_CIPHER_SUITE_GCMP_256; +- +- if (have_wep) { +- suites[w++] = WLAN_CIPHER_SUITE_WEP40; +- suites[w++] = WLAN_CIPHER_SUITE_WEP104; +- } +- +-- if (have_mfp) { +-+ if (have_mfp) +- suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC; +-- suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256; +-- suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128; +-- suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256; +-- } +- +- for (r = 0; r < local->hw.n_cipher_schemes; r++) +- suites[w++] = cs[r].cipher; +---- a/net/mac80211/rx.c +-+++ b/net/mac80211/rx.c +-@@ -647,7 +647,6 @@ static int ieee80211_get_mmie_keyidx(str +- { +- struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; +- struct ieee80211_mmie *mmie; +-- struct ieee80211_mmie_16 *mmie16; +- +- if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) +- return -1; +-@@ -657,18 +656,11 @@ static int ieee80211_get_mmie_keyidx(str +- +- mmie = (struct ieee80211_mmie *) +- (skb->data + skb->len - sizeof(*mmie)); +-- if (mmie->element_id == WLAN_EID_MMIE && +-- mmie->length == sizeof(*mmie) - 2) +-- return le16_to_cpu(mmie->key_id); +-- +-- mmie16 = (struct ieee80211_mmie_16 *) +-- (skb->data + skb->len - sizeof(*mmie16)); +-- if (skb->len >= 24 + sizeof(*mmie16) && +-- mmie16->element_id == WLAN_EID_MMIE && +-- mmie16->length == sizeof(*mmie16) - 2) +-- return le16_to_cpu(mmie16->key_id); +-+ if (mmie->element_id != WLAN_EID_MMIE || +-+ mmie->length != sizeof(*mmie) - 2) +-+ return -1; +- +-- return -1; +-+ return le16_to_cpu(mmie->key_id); +- } +- +- static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs, +-@@ -1658,27 +1650,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_ +- result = ieee80211_crypto_tkip_decrypt(rx); +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- result = ieee80211_crypto_ccmp_decrypt( +-- rx, IEEE80211_CCMP_MIC_LEN); +-- break; +-- case WLAN_CIPHER_SUITE_CCMP_256: +-- result = ieee80211_crypto_ccmp_decrypt( +-- rx, IEEE80211_CCMP_256_MIC_LEN); +-+ result = ieee80211_crypto_ccmp_decrypt(rx); +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +- result = ieee80211_crypto_aes_cmac_decrypt(rx); +- break; +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +-- result = ieee80211_crypto_aes_cmac_256_decrypt(rx); +-- break; +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- result = ieee80211_crypto_aes_gmac_decrypt(rx); +-- break; +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- result = ieee80211_crypto_gcmp_decrypt(rx); +-- break; +- default: +- result = ieee80211_crypto_hw_decrypt(rx); +- } +-@@ -1805,9 +1781,7 @@ ieee80211_rx_h_defragment(struct ieee802 +- /* This is the first fragment of a new frame. */ +- entry = ieee80211_reassemble_add(rx->sdata, frag, seq, +- rx->seqno_idx, &(rx->skb)); +-- if (rx->key && +-- (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP || +-- rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) && +-+ if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && +- ieee80211_has_protected(fc)) { +- int queue = rx->security_idx; +- /* Store CCMP PN so that we can verify that the next +-@@ -1836,9 +1810,7 @@ ieee80211_rx_h_defragment(struct ieee802 +- int i; +- u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; +- int queue; +-- if (!rx->key || +-- (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP && +-- rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256)) +-+ if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) +- return RX_DROP_UNUSABLE; +- memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); +- for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) { +---- a/net/mac80211/tx.c +-+++ b/net/mac80211/tx.c +-@@ -626,9 +626,6 @@ ieee80211_tx_h_select_key(struct ieee802 +- tx->key = NULL; +- break; +- case WLAN_CIPHER_SUITE_CCMP: +-- case WLAN_CIPHER_SUITE_CCMP_256: +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +- if (!ieee80211_is_data_present(hdr->frame_control) && +- !ieee80211_use_mfp(hdr->frame_control, tx->sta, +- tx->skb)) +-@@ -639,9 +636,6 @@ ieee80211_tx_h_select_key(struct ieee802 +- ieee80211_is_mgmt(hdr->frame_control); +- break; +- case WLAN_CIPHER_SUITE_AES_CMAC: +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +- if (!ieee80211_is_mgmt(hdr->frame_control)) +- tx->key = NULL; +- break; +-@@ -1017,21 +1011,9 @@ ieee80211_tx_h_encrypt(struct ieee80211_ +- case WLAN_CIPHER_SUITE_TKIP: +- return ieee80211_crypto_tkip_encrypt(tx); +- case WLAN_CIPHER_SUITE_CCMP: +-- return ieee80211_crypto_ccmp_encrypt( +-- tx, IEEE80211_CCMP_MIC_LEN); +-- case WLAN_CIPHER_SUITE_CCMP_256: +-- return ieee80211_crypto_ccmp_encrypt( +-- tx, IEEE80211_CCMP_256_MIC_LEN); +-+ return ieee80211_crypto_ccmp_encrypt(tx); +- case WLAN_CIPHER_SUITE_AES_CMAC: +- return ieee80211_crypto_aes_cmac_encrypt(tx); +-- case WLAN_CIPHER_SUITE_BIP_CMAC_256: +-- return ieee80211_crypto_aes_cmac_256_encrypt(tx); +-- case WLAN_CIPHER_SUITE_BIP_GMAC_128: +-- case WLAN_CIPHER_SUITE_BIP_GMAC_256: +-- return ieee80211_crypto_aes_gmac_encrypt(tx); +-- case WLAN_CIPHER_SUITE_GCMP: +-- case WLAN_CIPHER_SUITE_GCMP_256: +-- return ieee80211_crypto_gcmp_encrypt(tx); +- default: +- return ieee80211_crypto_hw_encrypt(tx); +- } +---- a/net/mac80211/wpa.c +-+++ b/net/mac80211/wpa.c +-@@ -22,8 +22,6 @@ +- #include "tkip.h" +- #include "aes_ccm.h" +- #include "aes_cmac.h" +--#include "aes_gmac.h" +--#include "aes_gcm.h" +- #include "wpa.h" +- +- ieee80211_tx_result +-@@ -304,15 +302,22 @@ ieee80211_crypto_tkip_decrypt(struct iee +- } +- +- +--static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) +-+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, +-+ int encrypted) +- { +- __le16 mask_fc; +- int a4_included, mgmt; +- u8 qos_tid; +-- u16 len_a; +-+ u8 *b_0, *aad; +-+ u16 data_len, len_a; +- unsigned int hdrlen; +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +- +-+ memset(scratch, 0, 6 * AES_BLOCK_SIZE); +-+ +-+ b_0 = scratch + 3 * AES_BLOCK_SIZE; +-+ aad = scratch + 4 * AES_BLOCK_SIZE; +-+ +- /* +- * Mask FC: zero subtype b4 b5 b6 (if not mgmt) +- * Retry, PwrMgt, MoreData; set Protected +-@@ -334,21 +339,20 @@ static void ccmp_special_blocks(struct s +- else +- qos_tid = 0; +- +-- /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC +-- * mode authentication are not allowed to collide, yet both are derived +-- * from this vector b_0. We only set L := 1 here to indicate that the +-- * data size can be represented in (L+1) bytes. The CCM layer will take +-- * care of storing the data length in the top (L+1) bytes and setting +-- * and clearing the other bits as is required to derive the two IVs. +-- */ +-- b_0[0] = 0x1; +-+ data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN; +-+ if (encrypted) +-+ data_len -= IEEE80211_CCMP_MIC_LEN; +- +-+ /* First block, b_0 */ +-+ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ +- /* Nonce: Nonce Flags | A2 | PN +- * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7) +- */ +- b_0[1] = qos_tid | (mgmt << 4); +- memcpy(&b_0[2], hdr->addr2, ETH_ALEN); +- memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN); +-+ /* l(m) */ +-+ put_unaligned_be16(data_len, &b_0[14]); +- +- /* AAD (extra authenticate-only data) / masked 802.11 header +- * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ +-@@ -395,8 +399,7 @@ static inline void ccmp_hdr2pn(u8 *pn, u +- } +- +- +--static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb, +-- unsigned int mic_len) +-+static int ccmp_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; +-@@ -405,8 +408,7 @@ static int ccmp_encrypt_skb(struct ieee8 +- u8 *pos; +- u8 pn[6]; +- u64 pn64; +-- u8 aad[2 * AES_BLOCK_SIZE]; +-- u8 b_0[AES_BLOCK_SIZE]; +-+ u8 scratch[6 * AES_BLOCK_SIZE]; +- +- if (info->control.hw_key && +- !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && +-@@ -427,7 +429,7 @@ static int ccmp_encrypt_skb(struct ieee8 +- if (info->control.hw_key) +- tail = 0; +- else +-- tail = mic_len; +-+ tail = IEEE80211_CCMP_MIC_LEN; +- +- if (WARN_ON(skb_tailroom(skb) < tail || +- skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN)) +-@@ -460,24 +462,23 @@ static int ccmp_encrypt_skb(struct ieee8 +- return 0; +- +- pos += IEEE80211_CCMP_HDR_LEN; +-- ccmp_special_blocks(skb, pn, b_0, aad); +-- ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, +-- skb_put(skb, mic_len), mic_len); +-+ ccmp_special_blocks(skb, pn, scratch, 0); +-+ ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, +-+ pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN)); +- +- return 0; +- } +- +- +- ieee80211_tx_result +--ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx, +-- unsigned int mic_len) +-+ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) +- { +- struct sk_buff *skb; +- +- ieee80211_tx_set_protected(tx); +- +- skb_queue_walk(&tx->skbs, skb) { +-- if (ccmp_encrypt_skb(tx, skb, mic_len) < 0) +-+ if (ccmp_encrypt_skb(tx, skb) < 0) +- return TX_DROP; +- } +- +-@@ -486,8 +487,7 @@ ieee80211_crypto_ccmp_encrypt(struct iee +- +- +- ieee80211_rx_result +--ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, +-- unsigned int mic_len) +-+ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) +- { +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; +- int hdrlen; +-@@ -504,7 +504,8 @@ ieee80211_crypto_ccmp_decrypt(struct iee +- !ieee80211_is_robust_mgmt_frame(skb)) +- return RX_CONTINUE; +- +-- data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - mic_len; +-+ data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - +-+ IEEE80211_CCMP_MIC_LEN; +- if (!rx->sta || data_len < 0) +- return RX_DROP_UNUSABLE; +- +-@@ -526,23 +527,23 @@ ieee80211_crypto_ccmp_decrypt(struct iee +- } +- +- if (!(status->flag & RX_FLAG_DECRYPTED)) { +-- u8 aad[2 * AES_BLOCK_SIZE]; +-- u8 b_0[AES_BLOCK_SIZE]; +-+ u8 scratch[6 * AES_BLOCK_SIZE]; +- /* hardware didn't decrypt/verify MIC */ +-- ccmp_special_blocks(skb, pn, b_0, aad); +-+ ccmp_special_blocks(skb, pn, scratch, 1); +- +- if (ieee80211_aes_ccm_decrypt( +-- key->u.ccmp.tfm, b_0, aad, +-+ key->u.ccmp.tfm, scratch, +- skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN, +- data_len, +-- skb->data + skb->len - mic_len, mic_len)) +-+ skb->data + skb->len - IEEE80211_CCMP_MIC_LEN, +-+ skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN)) +- return RX_DROP_UNUSABLE; +- } +- +- memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN); +- +- /* Remove CCMP header and MIC */ +-- if (pskb_trim(skb, skb->len - mic_len)) +-+ if (pskb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN)) +- return RX_DROP_UNUSABLE; +- memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen); +- skb_pull(skb, IEEE80211_CCMP_HDR_LEN); +-@@ -550,229 +551,6 @@ ieee80211_crypto_ccmp_decrypt(struct iee +- return RX_CONTINUE; +- } +- +--static void gcmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *j_0, u8 *aad) +--{ +-- __le16 mask_fc; +-- u8 qos_tid; +-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +-- +-- memcpy(j_0, hdr->addr2, ETH_ALEN); +-- memcpy(&j_0[ETH_ALEN], pn, IEEE80211_GCMP_PN_LEN); +-- j_0[13] = 0; +-- j_0[14] = 0; +-- j_0[AES_BLOCK_SIZE - 1] = 0x01; +-- +-- /* AAD (extra authenticate-only data) / masked 802.11 header +-- * FC | A1 | A2 | A3 | SC | [A4] | [QC] +-- */ +-- put_unaligned_be16(ieee80211_hdrlen(hdr->frame_control) - 2, &aad[0]); +-- /* Mask FC: zero subtype b4 b5 b6 (if not mgmt) +-- * Retry, PwrMgt, MoreData; set Protected +-- */ +-- mask_fc = hdr->frame_control; +-- mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | +-- IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); +-- if (!ieee80211_is_mgmt(hdr->frame_control)) +-- mask_fc &= ~cpu_to_le16(0x0070); +-- mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); +-- +-- put_unaligned(mask_fc, (__le16 *)&aad[2]); +-- memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN); +-- +-- /* Mask Seq#, leave Frag# */ +-- aad[22] = *((u8 *)&hdr->seq_ctrl) & 0x0f; +-- aad[23] = 0; +-- +-- if (ieee80211_is_data_qos(hdr->frame_control)) +-- qos_tid = *ieee80211_get_qos_ctl(hdr) & +-- IEEE80211_QOS_CTL_TID_MASK; +-- else +-- qos_tid = 0; +-- +-- if (ieee80211_has_a4(hdr->frame_control)) { +-- memcpy(&aad[24], hdr->addr4, ETH_ALEN); +-- aad[30] = qos_tid; +-- aad[31] = 0; +-- } else { +-- memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); +-- aad[24] = qos_tid; +-- } +--} +-- +--static inline void gcmp_pn2hdr(u8 *hdr, const u8 *pn, int key_id) +--{ +-- hdr[0] = pn[5]; +-- hdr[1] = pn[4]; +-- hdr[2] = 0; +-- hdr[3] = 0x20 | (key_id << 6); +-- hdr[4] = pn[3]; +-- hdr[5] = pn[2]; +-- hdr[6] = pn[1]; +-- hdr[7] = pn[0]; +--} +-- +--static inline void gcmp_hdr2pn(u8 *pn, const u8 *hdr) +--{ +-- pn[0] = hdr[7]; +-- pn[1] = hdr[6]; +-- pn[2] = hdr[5]; +-- pn[3] = hdr[4]; +-- pn[4] = hdr[1]; +-- pn[5] = hdr[0]; +--} +-- +--static int gcmp_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); +-- int hdrlen, len, tail; +-- u8 *pos; +-- u8 pn[6]; +-- u64 pn64; +-- u8 aad[2 * AES_BLOCK_SIZE]; +-- u8 j_0[AES_BLOCK_SIZE]; +-- +-- if (info->control.hw_key && +-- !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) && +-- !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) && +-- !((info->control.hw_key->flags & +-- IEEE80211_KEY_FLAG_GENERATE_IV_MGMT) && +-- ieee80211_is_mgmt(hdr->frame_control))) { +-- /* hwaccel has no need for preallocated room for GCMP +-- * header or MIC fields +-- */ +-- return 0; +-- } +-- +-- hdrlen = ieee80211_hdrlen(hdr->frame_control); +-- len = skb->len - hdrlen; +-- +-- if (info->control.hw_key) +-- tail = 0; +-- else +-- tail = IEEE80211_GCMP_MIC_LEN; +-- +-- if (WARN_ON(skb_tailroom(skb) < tail || +-- skb_headroom(skb) < IEEE80211_GCMP_HDR_LEN)) +-- return -1; +-- +-- pos = skb_push(skb, IEEE80211_GCMP_HDR_LEN); +-- memmove(pos, pos + IEEE80211_GCMP_HDR_LEN, hdrlen); +-- skb_set_network_header(skb, skb_network_offset(skb) + +-- IEEE80211_GCMP_HDR_LEN); +-- +-- /* the HW only needs room for the IV, but not the actual IV */ +-- if (info->control.hw_key && +-- (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) +-- return 0; +-- +-- hdr = (struct ieee80211_hdr *)pos; +-- pos += hdrlen; +-- +-- pn64 = atomic64_inc_return(&key->u.gcmp.tx_pn); +-- +-- pn[5] = pn64; +-- pn[4] = pn64 >> 8; +-- pn[3] = pn64 >> 16; +-- pn[2] = pn64 >> 24; +-- pn[1] = pn64 >> 32; +-- pn[0] = pn64 >> 40; +-- +-- gcmp_pn2hdr(pos, pn, key->conf.keyidx); +-- +-- /* hwaccel - with software GCMP header */ +-- if (info->control.hw_key) +-- return 0; +-- +-- pos += IEEE80211_GCMP_HDR_LEN; +-- gcmp_special_blocks(skb, pn, j_0, aad); +-- ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len, +-- skb_put(skb, IEEE80211_GCMP_MIC_LEN)); +-- +-- return 0; +--} +-- +--ieee80211_tx_result +--ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx) +--{ +-- struct sk_buff *skb; +-- +-- ieee80211_tx_set_protected(tx); +-- +-- skb_queue_walk(&tx->skbs, skb) { +-- if (gcmp_encrypt_skb(tx, skb) < 0) +-- return TX_DROP; +-- } +-- +-- return TX_CONTINUE; +--} +-- +--ieee80211_rx_result +--ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx) +--{ +-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; +-- int hdrlen; +-- struct ieee80211_key *key = rx->key; +-- struct sk_buff *skb = rx->skb; +-- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); +-- u8 pn[IEEE80211_GCMP_PN_LEN]; +-- int data_len; +-- int queue; +-- +-- hdrlen = ieee80211_hdrlen(hdr->frame_control); +-- +-- if (!ieee80211_is_data(hdr->frame_control) && +-- !ieee80211_is_robust_mgmt_frame(skb)) +-- return RX_CONTINUE; +-- +-- data_len = skb->len - hdrlen - IEEE80211_GCMP_HDR_LEN - +-- IEEE80211_GCMP_MIC_LEN; +-- if (!rx->sta || data_len < 0) +-- return RX_DROP_UNUSABLE; +-- +-- if (status->flag & RX_FLAG_DECRYPTED) { +-- if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_GCMP_HDR_LEN)) +-- return RX_DROP_UNUSABLE; +-- } else { +-- if (skb_linearize(rx->skb)) +-- return RX_DROP_UNUSABLE; +-- } +-- +-- gcmp_hdr2pn(pn, skb->data + hdrlen); +-- +-- queue = rx->security_idx; +-- +-- if (memcmp(pn, key->u.gcmp.rx_pn[queue], IEEE80211_GCMP_PN_LEN) <= 0) { +-- key->u.gcmp.replays++; +-- return RX_DROP_UNUSABLE; +-- } +-- +-- if (!(status->flag & RX_FLAG_DECRYPTED)) { +-- u8 aad[2 * AES_BLOCK_SIZE]; +-- u8 j_0[AES_BLOCK_SIZE]; +-- /* hardware didn't decrypt/verify MIC */ +-- gcmp_special_blocks(skb, pn, j_0, aad); +-- +-- if (ieee80211_aes_gcm_decrypt( +-- key->u.gcmp.tfm, j_0, aad, +-- skb->data + hdrlen + IEEE80211_GCMP_HDR_LEN, +-- data_len, +-- skb->data + skb->len - IEEE80211_GCMP_MIC_LEN)) +-- return RX_DROP_UNUSABLE; +-- } +-- +-- memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN); +-- +-- /* Remove GCMP header and MIC */ +-- if (pskb_trim(skb, skb->len - IEEE80211_GCMP_MIC_LEN)) +-- return RX_DROP_UNUSABLE; +-- memmove(skb->data + IEEE80211_GCMP_HDR_LEN, skb->data, hdrlen); +-- skb_pull(skb, IEEE80211_GCMP_HDR_LEN); +-- +-- return RX_CONTINUE; +--} +-- +- static ieee80211_tx_result +- ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx, +- struct sk_buff *skb) +-@@ -956,48 +734,6 @@ ieee80211_crypto_aes_cmac_encrypt(struct +- return TX_CONTINUE; +- } +- +--ieee80211_tx_result +--ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx) +--{ +-- struct sk_buff *skb; +-- struct ieee80211_tx_info *info; +-- struct ieee80211_key *key = tx->key; +-- struct ieee80211_mmie_16 *mmie; +-- u8 aad[20]; +-- u64 pn64; +-- +-- if (WARN_ON(skb_queue_len(&tx->skbs) != 1)) +-- return TX_DROP; +-- +-- skb = skb_peek(&tx->skbs); +-- +-- info = IEEE80211_SKB_CB(skb); +-- +-- if (info->control.hw_key) +-- return TX_CONTINUE; +-- +-- if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) +-- return TX_DROP; +-- +-- mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie)); +-- mmie->element_id = WLAN_EID_MMIE; +-- mmie->length = sizeof(*mmie) - 2; +-- mmie->key_id = cpu_to_le16(key->conf.keyidx); +-- +-- /* PN = PN + 1 */ +-- pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn); +-- +-- bip_ipn_set64(mmie->sequence_number, pn64); +-- +-- bip_aad(skb, aad); +-- +-- /* MIC = AES-256-CMAC(IGTK, AAD || Management Frame Body || MMIE, 128) +-- */ +-- ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, +-- skb->data + 24, skb->len - 24, mmie->mic); +-- +-- return TX_CONTINUE; +--} +- +- ieee80211_rx_result +- ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) +-@@ -1045,160 +781,6 @@ ieee80211_crypto_aes_cmac_decrypt(struct +- +- /* Remove MMIE */ +- skb_trim(skb, skb->len - sizeof(*mmie)); +-- +-- return RX_CONTINUE; +--} +-- +--ieee80211_rx_result +--ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx) +--{ +-- struct sk_buff *skb = rx->skb; +-- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); +-- struct ieee80211_key *key = rx->key; +-- struct ieee80211_mmie_16 *mmie; +-- u8 aad[20], mic[16], ipn[6]; +-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +-- +-- if (!ieee80211_is_mgmt(hdr->frame_control)) +-- return RX_CONTINUE; +-- +-- /* management frames are already linear */ +-- +-- if (skb->len < 24 + sizeof(*mmie)) +-- return RX_DROP_UNUSABLE; +-- +-- mmie = (struct ieee80211_mmie_16 *) +-- (skb->data + skb->len - sizeof(*mmie)); +-- if (mmie->element_id != WLAN_EID_MMIE || +-- mmie->length != sizeof(*mmie) - 2) +-- return RX_DROP_UNUSABLE; /* Invalid MMIE */ +-- +-- bip_ipn_swap(ipn, mmie->sequence_number); +-- +-- if (memcmp(ipn, key->u.aes_cmac.rx_pn, 6) <= 0) { +-- key->u.aes_cmac.replays++; +-- return RX_DROP_UNUSABLE; +-- } +-- +-- if (!(status->flag & RX_FLAG_DECRYPTED)) { +-- /* hardware didn't decrypt/verify MIC */ +-- bip_aad(skb, aad); +-- ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad, +-- skb->data + 24, skb->len - 24, mic); +-- if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { +-- key->u.aes_cmac.icverrors++; +-- return RX_DROP_UNUSABLE; +-- } +-- } +-- +-- memcpy(key->u.aes_cmac.rx_pn, ipn, 6); +-- +-- /* Remove MMIE */ +-- skb_trim(skb, skb->len - sizeof(*mmie)); +-- +-- return RX_CONTINUE; +--} +-- +--ieee80211_tx_result +--ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx) +--{ +-- struct sk_buff *skb; +-- struct ieee80211_tx_info *info; +-- struct ieee80211_key *key = tx->key; +-- struct ieee80211_mmie_16 *mmie; +-- struct ieee80211_hdr *hdr; +-- u8 aad[20]; +-- u64 pn64; +-- u8 nonce[12]; +-- +-- if (WARN_ON(skb_queue_len(&tx->skbs) != 1)) +-- return TX_DROP; +-- +-- skb = skb_peek(&tx->skbs); +-- +-- info = IEEE80211_SKB_CB(skb); +-- +-- if (info->control.hw_key) +-- return TX_CONTINUE; +-- +-- if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie))) +-- return TX_DROP; +-- +-- mmie = (struct ieee80211_mmie_16 *)skb_put(skb, sizeof(*mmie)); +-- mmie->element_id = WLAN_EID_MMIE; +-- mmie->length = sizeof(*mmie) - 2; +-- mmie->key_id = cpu_to_le16(key->conf.keyidx); +-- +-- /* PN = PN + 1 */ +-- pn64 = atomic64_inc_return(&key->u.aes_gmac.tx_pn); +-- +-- bip_ipn_set64(mmie->sequence_number, pn64); +-- +-- bip_aad(skb, aad); +-- +-- hdr = (struct ieee80211_hdr *)skb->data; +-- memcpy(nonce, hdr->addr2, ETH_ALEN); +-- bip_ipn_swap(nonce + ETH_ALEN, mmie->sequence_number); +-- +-- /* MIC = AES-GMAC(IGTK, AAD || Management Frame Body || MMIE, 128) */ +-- if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, +-- skb->data + 24, skb->len - 24, mmie->mic) < 0) +-- return TX_DROP; +-- +-- return TX_CONTINUE; +--} +-- +--ieee80211_rx_result +--ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) +--{ +-- struct sk_buff *skb = rx->skb; +-- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); +-- struct ieee80211_key *key = rx->key; +-- struct ieee80211_mmie_16 *mmie; +-- u8 aad[20], mic[16], ipn[6], nonce[12]; +-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +-- +-- if (!ieee80211_is_mgmt(hdr->frame_control)) +-- return RX_CONTINUE; +-- +-- /* management frames are already linear */ +-- +-- if (skb->len < 24 + sizeof(*mmie)) +-- return RX_DROP_UNUSABLE; +-- +-- mmie = (struct ieee80211_mmie_16 *) +-- (skb->data + skb->len - sizeof(*mmie)); +-- if (mmie->element_id != WLAN_EID_MMIE || +-- mmie->length != sizeof(*mmie) - 2) +-- return RX_DROP_UNUSABLE; /* Invalid MMIE */ +-- +-- bip_ipn_swap(ipn, mmie->sequence_number); +-- +-- if (memcmp(ipn, key->u.aes_gmac.rx_pn, 6) <= 0) { +-- key->u.aes_gmac.replays++; +-- return RX_DROP_UNUSABLE; +-- } +-- +-- if (!(status->flag & RX_FLAG_DECRYPTED)) { +-- /* hardware didn't decrypt/verify MIC */ +-- bip_aad(skb, aad); +-- +-- memcpy(nonce, hdr->addr2, ETH_ALEN); +-- memcpy(nonce + ETH_ALEN, ipn, 6); +-- +-- if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, +-- skb->data + 24, skb->len - 24, +-- mic) < 0 || +-- memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) { +-- key->u.aes_gmac.icverrors++; +-- return RX_DROP_UNUSABLE; +-- } +-- } +-- +-- memcpy(key->u.aes_gmac.rx_pn, ipn, 6); +-- +-- /* Remove MMIE */ +-- skb_trim(skb, skb->len - sizeof(*mmie)); +- +- return RX_CONTINUE; +- } +---- a/net/mac80211/wpa.h +-+++ b/net/mac80211/wpa.h +-@@ -24,32 +24,17 @@ ieee80211_rx_result +- ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx); +- +- ieee80211_tx_result +--ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx, +-- unsigned int mic_len); +-+ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx); +- ieee80211_rx_result +--ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx, +-- unsigned int mic_len); +-+ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx); +- +- ieee80211_tx_result +- ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx); +--ieee80211_tx_result +--ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx); +- ieee80211_rx_result +- ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx); +--ieee80211_rx_result +--ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx); +--ieee80211_tx_result +--ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx); +--ieee80211_rx_result +--ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx); +- ieee80211_tx_result +- ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx); +- ieee80211_rx_result +- ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx); +- +--ieee80211_tx_result +--ieee80211_crypto_gcmp_encrypt(struct ieee80211_tx_data *tx); +--ieee80211_rx_result +--ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx); +-- +- #endif /* WPA_H */ +diff --git a/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch b/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch +index 41a3c4f..cff6d89 100644 +--- a/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch ++++ b/package/kernel/mac80211/patches/110-mac80211_keep_keys_on_stop_ap.patch +@@ -2,7 +2,7 @@ Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects + + --- a/net/mac80211/cfg.c + +++ b/net/mac80211/cfg.c +-@@ -856,7 +856,6 @@ static int ieee80211_stop_ap(struct wiph ++@@ -886,7 +886,6 @@ static int ieee80211_stop_ap(struct wiph + sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; + + __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 de79bd2..5fc9454 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 @@ + static int ieee80211_ifa6_changed(struct notifier_block *nb, + unsigned long data, void *arg) + { +-@@ -1057,14 +1057,14 @@ int ieee80211_register_hw(struct ieee802 ++@@ -1086,14 +1086,14 @@ int ieee80211_register_hw(struct ieee802 + if (result) + goto fail_pm_qos; + +@@ -35,7 +35,7 @@ + local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed; + result = register_inet6addr_notifier(&local->ifa6_notifier); + if (result) +-@@ -1073,13 +1073,13 @@ int ieee80211_register_hw(struct ieee802 ++@@ -1102,13 +1102,13 @@ int ieee80211_register_hw(struct ieee802 + + return 0; + +@@ -52,7 +52,7 @@ + fail_ifa: + pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, + &local->network_latency_notifier); +-@@ -1124,10 +1124,10 @@ void ieee80211_unregister_hw(struct ieee ++@@ -1141,10 +1141,10 @@ void ieee80211_unregister_hw(struct ieee + + pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, + &local->network_latency_notifier); +diff --git a/package/kernel/mac80211/patches/210-ap_scan.patch b/package/kernel/mac80211/patches/210-ap_scan.patch +index 47dcec3..29f05c4 100644 +--- a/package/kernel/mac80211/patches/210-ap_scan.patch ++++ b/package/kernel/mac80211/patches/210-ap_scan.patch +@@ -1,6 +1,6 @@ + --- a/net/mac80211/cfg.c + +++ b/net/mac80211/cfg.c +-@@ -1963,7 +1963,7 @@ static int ieee80211_scan(struct wiphy * ++@@ -2008,7 +2008,7 @@ static int ieee80211_scan(struct wiphy * + * the frames sent while scanning on other channel will be + * lost) + */ +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 +new file mode 100644 +index 0000000..bddb15a +--- /dev/null ++++ b/package/kernel/mac80211/patches/300-ath9k-force-rx_clear-when-disabling-rx.patch +@@ -0,0 +1,31 @@ ++From: Felix Fietkau ++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 ++Rx related DMA stop warnings ++ ++Cc: stable@vger.kernel.org ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/mac.c +++++ b/drivers/net/wireless/ath/ath9k/mac.c ++@@ -677,13 +677,15 @@ void ath9k_hw_startpcureceive(struct ath ++ ++ ath9k_ani_reset(ah, is_scanning); ++ ++- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); +++ REG_CLR_BIT(ah, AR_DIAG_SW, +++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); ++ } ++ EXPORT_SYMBOL(ath9k_hw_startpcureceive); ++ ++ void ath9k_hw_abortpcurecv(struct ath_hw *ah) ++ { ++- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); +++ REG_SET_BIT(ah, AR_DIAG_SW, +++ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); ++ ++ ath9k_hw_disable_mib_counters(ah); ++ } +diff --git a/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch b/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch +deleted file mode 100644 +index 237121b..0000000 +--- a/package/kernel/mac80211/patches/300-mac80211-add-an-intermediate-software-queue-implemen.patch ++++ /dev/null +@@ -1,882 +0,0 @@ +-From: Felix Fietkau +-Date: Tue, 18 Nov 2014 23:58:51 +0100 +-Subject: [PATCH] mac80211: add an intermediate software queue implementation +- +-This allows drivers to request per-vif and per-sta-tid queues from which +-they can pull frames. This makes it easier to keep the hardware queues +-short, and to improve fairness between clients and vifs. +- +-The task of scheduling packet transmission is left up to the driver - +-queueing is controlled by mac80211. Drivers can only dequeue packets by +-calling ieee80211_tx_dequeue. This makes it possible to add active queue +-management later without changing drivers using this code. +- +-This can also be used as a starting point to implement A-MSDU +-aggregation in a way that does not add artificially induced latency. +- +-Signed-off-by: Felix Fietkau +---- +- +---- a/include/net/mac80211.h +-+++ b/include/net/mac80211.h +-@@ -84,6 +84,39 @@ +- * +- */ +- +-+/** +-+ * DOC: mac80211 software tx queueing +-+ * +-+ * mac80211 provides an optional intermediate queueing implementation designed +-+ * to allow the driver to keep hardware queues short and provide some fairness +-+ * between different stations/interfaces. +-+ * In this model, the driver pulls data frames from the mac80211 queue instead +-+ * of letting mac80211 push them via drv_tx(). +-+ * Other frames (e.g. control or management) are still pushed using drv_tx(). +-+ * +-+ * Drivers indicate that they use this model by implementing the .wake_tx_queue +-+ * driver operation. +-+ * +-+ * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a +-+ * single per-vif queue for multicast data frames. +-+ * +-+ * The driver is expected to initialize its private per-queue data for stations +-+ * and interfaces in the .add_interface and .sta_add ops. +-+ * +-+ * The driver can't access the queue directly. To dequeue a frame, it calls +-+ * ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a queue, it +-+ * calls the .wake_tx_queue driver op. +-+ * +-+ * For AP powersave TIM handling, the driver only needs to indicate if it has +-+ * buffered packets in the driver specific data structures by calling +-+ * ieee80211_sta_set_buffered(). For frames buffered in the ieee80211_txq +-+ * struct, mac80211 sets the appropriate TIM PVB bits and calls +-+ * .release_buffered_frames(). +-+ * In that callback the driver is therefore expected to release its own +-+ * buffered frames and afterwards also frames from the ieee80211_txq (obtained +-+ * via the usual ieee80211_tx_dequeue). +-+ */ +-+ +- struct device; +- +- /** +-@@ -1246,6 +1279,7 @@ enum ieee80211_vif_flags { +- * monitor interface (if that is requested.) +- * @drv_priv: data area for driver use, will always be aligned to +- * sizeof(void *). +-+ * @txq: the multicast data TX queue (if driver uses the TXQ abstraction) +- */ +- struct ieee80211_vif { +- enum nl80211_iftype type; +-@@ -1257,6 +1291,8 @@ struct ieee80211_vif { +- u8 cab_queue; +- u8 hw_queue[IEEE80211_NUM_ACS]; +- +-+ struct ieee80211_txq *txq; +-+ +- struct ieee80211_chanctx_conf __rcu *chanctx_conf; +- +- u32 driver_flags; +-@@ -1501,6 +1537,7 @@ struct ieee80211_sta_rates { +- * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only +- * valid if the STA is a TDLS peer in the first place. +- * @mfp: indicates whether the STA uses management frame protection or not. +-+ * @txq: per-TID data TX queues (if driver uses the TXQ abstraction) +- */ +- struct ieee80211_sta { +- u32 supp_rates[IEEE80211_NUM_BANDS]; +-@@ -1519,6 +1556,8 @@ struct ieee80211_sta { +- bool tdls_initiator; +- bool mfp; +- +-+ struct ieee80211_txq *txq[IEEE80211_NUM_TIDS]; +-+ +- /* must be last */ +- u8 drv_priv[0] __aligned(sizeof(void *)); +- }; +-@@ -1547,6 +1586,27 @@ struct ieee80211_tx_control { +- }; +- +- /** +-+ * struct ieee80211_txq - Software intermediate tx queue +-+ * +-+ * @vif: &struct ieee80211_vif pointer from the add_interface callback. +-+ * @sta: station table entry, %NULL for per-vif queue +-+ * @tid: the TID for this queue (unused for per-vif queue) +-+ * @ac: the AC for this queue +-+ * +-+ * The driver can obtain packets from this queue by calling +-+ * ieee80211_tx_dequeue(). +-+ */ +-+struct ieee80211_txq { +-+ struct ieee80211_vif *vif; +-+ struct ieee80211_sta *sta; +-+ u8 tid; +-+ u8 ac; +-+ +-+ /* must be last */ +-+ u8 drv_priv[0] __aligned(sizeof(void *)); +-+}; +-+ +-+/** +- * enum ieee80211_hw_flags - hardware flags +- * +- * These flags are used to indicate hardware capabilities to +-@@ -1770,6 +1830,8 @@ enum ieee80211_hw_flags { +- * within &struct ieee80211_sta. +- * @chanctx_data_size: size (in bytes) of the drv_priv data area +- * within &struct ieee80211_chanctx_conf. +-+ * @txq_data_size: size (in bytes) of the drv_priv data area +-+ * within @struct ieee80211_txq. +- * +- * @max_rates: maximum number of alternate rate retry stages the hw +- * can handle. +-@@ -1818,6 +1880,9 @@ enum ieee80211_hw_flags { +- * @n_cipher_schemes: a size of an array of cipher schemes definitions. +- * @cipher_schemes: a pointer to an array of cipher scheme definitions +- * supported by HW. +-+ * +-+ * @txq_ac_max_pending: maximum number of frames per AC pending in all txq +-+ * entries for a vif. +- */ +- struct ieee80211_hw { +- struct ieee80211_conf conf; +-@@ -1830,6 +1895,7 @@ struct ieee80211_hw { +- int vif_data_size; +- int sta_data_size; +- int chanctx_data_size; +-+ int txq_data_size; +- u16 queues; +- u16 max_listen_interval; +- s8 max_signal; +-@@ -1846,6 +1912,7 @@ struct ieee80211_hw { +- u8 uapsd_max_sp_len; +- u8 n_cipher_schemes; +- const struct ieee80211_cipher_scheme *cipher_schemes; +-+ int txq_ac_max_pending; +- }; +- +- /** +-@@ -3007,6 +3074,8 @@ enum ieee80211_reconfig_type { +- * response template is provided, together with the location of the +- * switch-timing IE within the template. The skb can only be used within +- * the function call. +-+ * +-+ * @wake_tx_queue: Called when new packets have been added to the queue. +- */ +- struct ieee80211_ops { +- void (*tx)(struct ieee80211_hw *hw, +-@@ -3238,6 +3307,9 @@ struct ieee80211_ops { +- void (*tdls_recv_channel_switch)(struct ieee80211_hw *hw, +- struct ieee80211_vif *vif, +- struct ieee80211_tdls_ch_sw_params *params); +-+ +-+ void (*wake_tx_queue)(struct ieee80211_hw *hw, +-+ struct ieee80211_txq *txq); +- }; +- +- /** +-@@ -5249,4 +5321,15 @@ void ieee80211_unreserve_tid(struct ieee +- */ +- size_t ieee80211_ie_split(const u8 *ies, size_t ielen, +- const u8 *ids, int n_ids, size_t offset); +-+ +-+/** +-+ * ieee80211_tx_dequeue - dequeue a packet from a software tx queue +-+ * +-+ * @hw: pointer as obtained from ieee80211_alloc_hw() +-+ * @txq: pointer obtained from station or virtual interface +-+ * +-+ * Returns the skb if successful, %NULL if no frame was available. +-+ */ +-+struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, +-+ struct ieee80211_txq *txq); +- #endif /* MAC80211_H */ +---- a/net/mac80211/driver-ops.h +-+++ b/net/mac80211/driver-ops.h +-@@ -1367,4 +1367,16 @@ drv_tdls_recv_channel_switch(struct ieee +- trace_drv_return_void(local); +- } +- +-+static inline void drv_wake_tx_queue(struct ieee80211_local *local, +-+ struct txq_info *txq) +-+{ +-+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif); +-+ +-+ if (!check_sdata_in_driver(sdata)) +-+ return; +-+ +-+ trace_drv_wake_tx_queue(local, sdata, txq); +-+ local->ops->wake_tx_queue(&local->hw, &txq->txq); +-+} +-+ +- #endif /* __MAC80211_DRIVER_OPS */ +---- a/net/mac80211/ieee80211_i.h +-+++ b/net/mac80211/ieee80211_i.h +-@@ -809,6 +809,19 @@ struct mac80211_qos_map { +- struct rcu_head rcu_head; +- }; +- +-+enum txq_info_flags { +-+ IEEE80211_TXQ_STOP, +-+ IEEE80211_TXQ_AMPDU, +-+}; +-+ +-+struct txq_info { +-+ struct sk_buff_head queue; +-+ unsigned long flags; +-+ +-+ /* keep last! */ +-+ struct ieee80211_txq txq; +-+}; +-+ +- struct ieee80211_sub_if_data { +- struct list_head list; +- +-@@ -853,6 +866,7 @@ struct ieee80211_sub_if_data { +- bool control_port_no_encrypt; +- int encrypt_headroom; +- +-+ atomic_t txqs_len[IEEE80211_NUM_ACS]; +- struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; +- struct mac80211_qos_map __rcu *qos_map; +- +-@@ -1453,6 +1467,10 @@ static inline struct ieee80211_local *hw +- return container_of(hw, struct ieee80211_local, hw); +- } +- +-+static inline struct txq_info *to_txq_info(struct ieee80211_txq *txq) +-+{ +-+ return container_of(txq, struct txq_info, txq); +-+} +- +- static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) +- { +-@@ -1905,6 +1923,9 @@ static inline bool ieee80211_can_run_wor +- return true; +- } +- +-+void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata, +-+ struct sta_info *sta, +-+ struct txq_info *txq, int tid); +- void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, +- u16 transaction, u16 auth_alg, u16 status, +- const u8 *extra, size_t extra_len, const u8 *bssid, +---- a/net/mac80211/iface.c +-+++ b/net/mac80211/iface.c +-@@ -969,6 +969,13 @@ static void ieee80211_do_stop(struct iee +- } +- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); +- +-+ if (sdata->vif.txq) { +-+ struct txq_info *txqi = to_txq_info(sdata->vif.txq); +-+ +-+ ieee80211_purge_tx_queue(&local->hw, &txqi->queue); +-+ atomic_set(&sdata->txqs_len[txqi->txq.ac], 0); +-+ } +-+ +- if (local->open_count == 0) +- ieee80211_clear_tx_pending(local); +- +-@@ -1674,6 +1681,7 @@ int ieee80211_if_add(struct ieee80211_lo +- { +- struct net_device *ndev = NULL; +- struct ieee80211_sub_if_data *sdata = NULL; +-+ struct txq_info *txqi; +- int ret, i; +- int txqs = 1; +- +-@@ -1693,10 +1701,18 @@ int ieee80211_if_add(struct ieee80211_lo +- ieee80211_assign_perm_addr(local, wdev->address, type); +- memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); +- } else { +-+ int size = ALIGN(sizeof(*sdata) + local->hw.vif_data_size, +-+ sizeof(void *)); +-+ int txq_size = 0; +-+ +-+ if (local->ops->wake_tx_queue) +-+ txq_size += sizeof(struct txq_info) + +-+ local->hw.txq_data_size; +-+ +- if (local->hw.queues >= IEEE80211_NUM_ACS) +- txqs = IEEE80211_NUM_ACS; +- +-- ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, +-+ ndev = alloc_netdev_mqs(size + txq_size, +- name, NET_NAME_UNKNOWN, +- ieee80211_if_setup, txqs, 1); +- if (!ndev) +-@@ -1731,6 +1747,11 @@ int ieee80211_if_add(struct ieee80211_lo +- memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); +- memcpy(sdata->name, ndev->name, IFNAMSIZ); +- +-+ if (txq_size) { +-+ txqi = netdev_priv(ndev) + size; +-+ ieee80211_init_tx_queue(sdata, NULL, txqi, 0); +-+ } +-+ +- sdata->dev = ndev; +- } +- +---- a/net/mac80211/main.c +-+++ b/net/mac80211/main.c +-@@ -1019,6 +1019,9 @@ int ieee80211_register_hw(struct ieee802 +- +- local->dynamic_ps_forced_timeout = -1; +- +-+ if (!local->hw.txq_ac_max_pending) +-+ local->hw.txq_ac_max_pending = 64; +-+ +- result = ieee80211_wep_init(local); +- if (result < 0) +- wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", +---- a/net/mac80211/sta_info.c +-+++ b/net/mac80211/sta_info.c +-@@ -118,6 +118,16 @@ static void __cleanup_single_sta(struct +- atomic_dec(&ps->num_sta_ps); +- } +- +-+ if (sta->sta.txq[0]) { +-+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { +-+ struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); +-+ int n = skb_queue_len(&txqi->queue); +-+ +-+ ieee80211_purge_tx_queue(&local->hw, &txqi->queue); +-+ atomic_sub(n, &sdata->txqs_len[txqi->txq.ac]); +-+ } +-+ } +-+ +- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { +- local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); +- ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); +-@@ -234,6 +244,8 @@ void sta_info_free(struct ieee80211_loca +- +- sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr); +- +-+ if (sta->sta.txq[0]) +-+ kfree(to_txq_info(sta->sta.txq[0])); +- kfree(rcu_dereference_raw(sta->sta.rates)); +- kfree(sta); +- } +-@@ -285,11 +297,12 @@ struct sta_info *sta_info_alloc(struct i +- const u8 *addr, gfp_t gfp) +- { +- struct ieee80211_local *local = sdata->local; +-+ struct ieee80211_hw *hw = &local->hw; +- struct sta_info *sta; +- struct timespec uptime; +- int i; +- +-- sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); +-+ sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp); +- if (!sta) +- return NULL; +- +-@@ -321,11 +334,25 @@ struct sta_info *sta_info_alloc(struct i +- for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) +- ewma_init(&sta->chain_signal_avg[i], 1024, 8); +- +-- if (sta_prepare_rate_control(local, sta, gfp)) { +-- kfree(sta); +-- return NULL; +-+ if (local->ops->wake_tx_queue) { +-+ void *txq_data; +-+ int size = sizeof(struct txq_info) + +-+ ALIGN(hw->txq_data_size, sizeof(void *)); +-+ +-+ txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp); +-+ if (!txq_data) +-+ goto free; +-+ +-+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { +-+ struct txq_info *txq = txq_data + i * size; +-+ +-+ ieee80211_init_tx_queue(sdata, sta, txq, i); +-+ } +- } +- +-+ if (sta_prepare_rate_control(local, sta, gfp)) +-+ goto free_txq; +-+ +- for (i = 0; i < IEEE80211_NUM_TIDS; i++) { +- /* +- * timer_to_tid must be initialized with identity mapping +-@@ -346,7 +373,7 @@ struct sta_info *sta_info_alloc(struct i +- if (sdata->vif.type == NL80211_IFTYPE_AP || +- sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +- struct ieee80211_supported_band *sband = +-- local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; +-+ hw->wiphy->bands[ieee80211_get_sdata_band(sdata)]; +- u8 smps = (sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> +- IEEE80211_HT_CAP_SM_PS_SHIFT; +- /* +-@@ -371,6 +398,13 @@ struct sta_info *sta_info_alloc(struct i +- sta_dbg(sdata, "Allocated STA %pM\n", sta->sta.addr); +- +- return sta; +-+ +-+free_txq: +-+ if (sta->sta.txq[0]) +-+ kfree(to_txq_info(sta->sta.txq[0])); +-+free: +-+ kfree(sta); +-+ return NULL; +- } +- +- static int sta_info_insert_check(struct sta_info *sta) +-@@ -640,6 +674,8 @@ static void __sta_info_recalc_tim(struct +- +- indicate_tim |= +- sta->driver_buffered_tids & tids; +-+ indicate_tim |= +-+ sta->txq_buffered_tids & tids; +- } +- +- done: +-@@ -1071,7 +1107,7 @@ void ieee80211_sta_ps_deliver_wakeup(str +- struct ieee80211_sub_if_data *sdata = sta->sdata; +- struct ieee80211_local *local = sdata->local; +- struct sk_buff_head pending; +-- int filtered = 0, buffered = 0, ac; +-+ int filtered = 0, buffered = 0, ac, i; +- unsigned long flags; +- struct ps_data *ps; +- +-@@ -1090,10 +1126,22 @@ void ieee80211_sta_ps_deliver_wakeup(str +- +- BUILD_BUG_ON(BITS_TO_LONGS(IEEE80211_NUM_TIDS) > 1); +- sta->driver_buffered_tids = 0; +-+ sta->txq_buffered_tids = 0; +- +- if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) +- drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); +- +-+ if (sta->sta.txq[0]) { +-+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) { +-+ struct txq_info *txqi = to_txq_info(sta->sta.txq[i]); +-+ +-+ if (!skb_queue_len(&txqi->queue)) +-+ continue; +-+ +-+ drv_wake_tx_queue(local, txqi); +-+ } +-+ } +-+ +- skb_queue_head_init(&pending); +- +- /* sync with ieee80211_tx_h_unicast_ps_buf */ +-@@ -1275,8 +1323,10 @@ ieee80211_sta_ps_deliver_response(struct +- /* if we already have frames from software, then we can't also +- * release from hardware queues +- */ +-- if (skb_queue_empty(&frames)) +-+ if (skb_queue_empty(&frames)) { +- driver_release_tids |= sta->driver_buffered_tids & tids; +-+ driver_release_tids |= sta->txq_buffered_tids & tids; +-+ } +- +- if (driver_release_tids) { +- /* If the driver has data on more than one TID then +-@@ -1447,6 +1497,9 @@ ieee80211_sta_ps_deliver_response(struct +- +- sta_info_recalc_tim(sta); +- } else { +-+ unsigned long tids = sta->txq_buffered_tids & driver_release_tids; +-+ int tid; +-+ +- /* +- * We need to release a frame that is buffered somewhere in the +- * driver ... it'll have to handle that. +-@@ -1466,8 +1519,22 @@ ieee80211_sta_ps_deliver_response(struct +- * that the TID(s) became empty before returning here from the +- * release function. +- * Either way, however, when the driver tells us that the TID(s) +-- * became empty we'll do the TIM recalculation. +-+ * became empty or we find that a txq became empty, we'll do the +-+ * TIM recalculation. +- */ +-+ +-+ if (!sta->sta.txq[0]) +-+ return; +-+ +-+ for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { +-+ struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]); +-+ +-+ if (!(tids & BIT(tid)) || skb_queue_len(&txqi->queue)) +-+ continue; +-+ +-+ sta_info_recalc_tim(sta); +-+ break; +-+ } +- } +- } +- +---- a/net/mac80211/sta_info.h +-+++ b/net/mac80211/sta_info.h +-@@ -274,6 +274,7 @@ struct sta_ampdu_mlme { +- * entered power saving state, these are also delivered to +- * the station when it leaves powersave or polls for frames +- * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on +-+ * @txq_buffered_tids: bitmap of TIDs that mac80211 has txq data buffered on +- * @rx_packets: Number of MSDUs received from this STA +- * @rx_bytes: Number of bytes received from this STA +- * @last_rx: time (in jiffies) when last frame was received from this STA +-@@ -368,6 +369,7 @@ struct sta_info { +- struct sk_buff_head ps_tx_buf[IEEE80211_NUM_ACS]; +- struct sk_buff_head tx_filtered[IEEE80211_NUM_ACS]; +- unsigned long driver_buffered_tids; +-+ unsigned long txq_buffered_tids; +- +- /* Updated from RX path only, no locking requirements */ +- unsigned long rx_packets; +---- a/net/mac80211/trace.h +-+++ b/net/mac80211/trace.h +-@@ -2312,6 +2312,37 @@ TRACE_EVENT(drv_tdls_recv_channel_switch +- ) +- ); +- +-+TRACE_EVENT(drv_wake_tx_queue, +-+ TP_PROTO(struct ieee80211_local *local, +-+ struct ieee80211_sub_if_data *sdata, +-+ struct txq_info *txq), +-+ +-+ TP_ARGS(local, sdata, txq), +-+ +-+ TP_STRUCT__entry( +-+ LOCAL_ENTRY +-+ VIF_ENTRY +-+ STA_ENTRY +-+ __field(u8, ac) +-+ __field(u8, tid) +-+ ), +-+ +-+ TP_fast_assign( +-+ struct ieee80211_sta *sta = txq->txq.sta; +-+ +-+ LOCAL_ASSIGN; +-+ VIF_ASSIGN; +-+ STA_ASSIGN; +-+ __entry->ac = txq->txq.ac; +-+ __entry->tid = txq->txq.tid; +-+ ), +-+ +-+ TP_printk( +-+ LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " ac:%d tid:%d", +-+ LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->ac, __entry->tid +-+ ) +-+); +-+ +- #ifdef CPTCFG_MAC80211_MESSAGE_TRACING +- #undef TRACE_SYSTEM +- #define TRACE_SYSTEM mac80211_msg +---- a/net/mac80211/tx.c +-+++ b/net/mac80211/tx.c +-@@ -776,12 +776,22 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021 +- return TX_CONTINUE; +- } +- +-+static __le16 ieee80211_tx_next_seq(struct sta_info *sta, int tid) +-+{ +-+ u16 *seq = &sta->tid_seq[tid]; +-+ __le16 ret = cpu_to_le16(*seq); +-+ +-+ /* Increase the sequence number. */ +-+ *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ; +-+ +-+ return ret; +-+} +-+ +- static ieee80211_tx_result debug_noinline +- ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) +- { +- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); +- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; +-- u16 *seq; +- u8 *qc; +- int tid; +- +-@@ -832,13 +842,10 @@ ieee80211_tx_h_sequence(struct ieee80211 +- +- qc = ieee80211_get_qos_ctl(hdr); +- tid = *qc & IEEE80211_QOS_CTL_TID_MASK; +-- seq = &tx->sta->tid_seq[tid]; +- tx->sta->tx_msdu[tid]++; +- +-- hdr->seq_ctrl = cpu_to_le16(*seq); +-- +-- /* Increase the sequence number. */ +-- *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ; +-+ if (!tx->sta->sta.txq[0]) +-+ hdr->seq_ctrl = ieee80211_tx_next_seq(tx->sta, tid); +- +- return TX_CONTINUE; +- } +-@@ -1067,7 +1074,7 @@ static bool ieee80211_tx_prep_agg(struct +- * nothing -- this aggregation session is being started +- * but that might still fail with the driver +- */ +-- } else { +-+ } else if (!tx->sta->sta.txq[tid]) { +- spin_lock(&tx->sta->lock); +- /* +- * Need to re-check now, because we may get here +-@@ -1201,13 +1208,102 @@ ieee80211_tx_prepare(struct ieee80211_su +- return TX_CONTINUE; +- } +- +-+static void ieee80211_drv_tx(struct ieee80211_local *local, +-+ struct ieee80211_vif *vif, +-+ struct ieee80211_sta *pubsta, +-+ struct sk_buff *skb) +-+{ +-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; +-+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); +-+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +-+ struct ieee80211_tx_control control = { +-+ .sta = pubsta, +-+ }; +-+ struct ieee80211_txq *txq = NULL; +-+ struct txq_info *txqi; +-+ u8 ac; +-+ +-+ if (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE) +-+ goto tx_normal; +-+ +-+ if (!ieee80211_is_data(hdr->frame_control)) +-+ goto tx_normal; +-+ +-+ if (pubsta) { +-+ u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; +-+ +-+ txq = pubsta->txq[tid]; +-+ } else if (vif) { +-+ txq = vif->txq; +-+ } +-+ +-+ if (!txq) +-+ goto tx_normal; +-+ +-+ ac = txq->ac; +-+ txqi = to_txq_info(txq); +-+ atomic_inc(&sdata->txqs_len[ac]); +-+ if (atomic_read(&sdata->txqs_len[ac]) >= local->hw.txq_ac_max_pending) +-+ netif_stop_subqueue(sdata->dev, ac); +-+ +-+ skb_queue_tail(&txqi->queue, skb); +-+ drv_wake_tx_queue(local, txqi); +-+ +-+ return; +-+ +-+tx_normal: +-+ drv_tx(local, &control, skb); +-+} +-+ +-+struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, +-+ struct ieee80211_txq *txq) +-+{ +-+ struct ieee80211_local *local = hw_to_local(hw); +-+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif); +-+ struct txq_info *txqi = container_of(txq, struct txq_info, txq); +-+ struct ieee80211_hdr *hdr; +-+ struct sk_buff *skb = NULL; +-+ u8 ac = txq->ac; +-+ +-+ spin_lock_bh(&txqi->queue.lock); +-+ +-+ if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags)) +-+ goto out; +-+ +-+ skb = __skb_dequeue(&txqi->queue); +-+ if (!skb) +-+ goto out; +-+ +-+ atomic_dec(&sdata->txqs_len[ac]); +-+ if (__netif_subqueue_stopped(sdata->dev, ac)) +-+ ieee80211_propagate_queue_wake(local, sdata->vif.hw_queue[ac]); +-+ +-+ hdr = (struct ieee80211_hdr *)skb->data; +-+ if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) { +-+ struct sta_info *sta = container_of(txq->sta, struct sta_info, +-+ sta); +-+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +-+ +-+ hdr->seq_ctrl = ieee80211_tx_next_seq(sta, txq->tid); +-+ if (test_bit(IEEE80211_TXQ_AMPDU, &txqi->flags)) +-+ info->flags |= IEEE80211_TX_CTL_AMPDU; +-+ else +-+ info->flags &= ~IEEE80211_TX_CTL_AMPDU; +-+ } +-+ +-+out: +-+ spin_unlock_bh(&txqi->queue.lock); +-+ +-+ return skb; +-+} +-+EXPORT_SYMBOL(ieee80211_tx_dequeue); +-+ +- static bool ieee80211_tx_frags(struct ieee80211_local *local, +- struct ieee80211_vif *vif, +- struct ieee80211_sta *sta, +- struct sk_buff_head *skbs, +- bool txpending) +- { +-- struct ieee80211_tx_control control; +- struct sk_buff *skb, *tmp; +- unsigned long flags; +- +-@@ -1265,10 +1361,9 @@ static bool ieee80211_tx_frags(struct ie +- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); +- +- info->control.vif = vif; +-- control.sta = sta; +- +- __skb_unlink(skb, skbs); +-- drv_tx(local, &control, skb); +-+ ieee80211_drv_tx(local, vif, sta, skb); +- } +- +- return true; +---- a/net/mac80211/util.c +-+++ b/net/mac80211/util.c +-@@ -308,6 +308,11 @@ void ieee80211_propagate_queue_wake(stru +- for (ac = 0; ac < n_acs; ac++) { +- int ac_queue = sdata->vif.hw_queue[ac]; +- +-+ if (local->ops->wake_tx_queue && +-+ (atomic_read(&sdata->txqs_len[ac]) > +-+ local->hw.txq_ac_max_pending)) +-+ continue; +-+ +- if (ac_queue == queue || +- (sdata->vif.cab_queue == queue && +- local->queue_stop_reasons[ac_queue] == 0 && +-@@ -3307,3 +3312,20 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u +- +- return buf; +- } +-+ +-+void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata, +-+ struct sta_info *sta, +-+ struct txq_info *txqi, int tid) +-+{ +-+ skb_queue_head_init(&txqi->queue); +-+ txqi->txq.vif = &sdata->vif; +-+ +-+ if (sta) { +-+ txqi->txq.sta = &sta->sta; +-+ sta->sta.txq[tid] = &txqi->txq; +-+ txqi->txq.ac = ieee802_1d_to_ac[tid & 7]; +-+ } else { +-+ sdata->vif.txq = &txqi->txq; +-+ txqi->txq.ac = IEEE80211_AC_BE; +-+ } +-+} +---- a/net/mac80211/rx.c +-+++ b/net/mac80211/rx.c +-@@ -1176,6 +1176,7 @@ static void sta_ps_start(struct sta_info +- struct ieee80211_sub_if_data *sdata = sta->sdata; +- struct ieee80211_local *local = sdata->local; +- struct ps_data *ps; +-+ int tid; +- +- if (sta->sdata->vif.type == NL80211_IFTYPE_AP || +- sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +-@@ -1189,6 +1190,18 @@ static void sta_ps_start(struct sta_info +- drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); +- ps_dbg(sdata, "STA %pM aid %d enters power save mode\n", +- sta->sta.addr, sta->sta.aid); +-+ +-+ if (!sta->sta.txq[0]) +-+ return; +-+ +-+ for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) { +-+ struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]); +-+ +-+ if (!skb_queue_len(&txqi->queue)) +-+ set_bit(tid, &sta->txq_buffered_tids); +-+ else +-+ clear_bit(tid, &sta->txq_buffered_tids); +-+ } +- } +- +- static void sta_ps_end(struct sta_info *sta) +---- a/net/mac80211/agg-tx.c +-+++ b/net/mac80211/agg-tx.c +-@@ -188,6 +188,43 @@ ieee80211_wake_queue_agg(struct ieee8021 +- __release(agg_queue); +- } +- +-+static void +-+ieee80211_agg_stop_txq(struct sta_info *sta, int tid) +-+{ +-+ struct ieee80211_txq *txq = sta->sta.txq[tid]; +-+ struct txq_info *txqi; +-+ +-+ if (!txq) +-+ return; +-+ +-+ txqi = to_txq_info(txq); +-+ +-+ /* Lock here to protect against further seqno updates on dequeue */ +-+ spin_lock_bh(&txqi->queue.lock); +-+ set_bit(IEEE80211_TXQ_STOP, &txqi->flags); +-+ spin_unlock_bh(&txqi->queue.lock); +-+} +-+ +-+static void +-+ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable) +-+{ +-+ struct ieee80211_txq *txq = sta->sta.txq[tid]; +-+ struct txq_info *txqi; +-+ +-+ if (!txq) +-+ return; +-+ +-+ txqi = to_txq_info(txq); +-+ +-+ if (enable) +-+ set_bit(IEEE80211_TXQ_AMPDU, &txqi->flags); +-+ else +-+ clear_bit(IEEE80211_TXQ_AMPDU, &txqi->flags); +-+ +-+ clear_bit(IEEE80211_TXQ_STOP, &txqi->flags); +-+ drv_wake_tx_queue(sta->sdata->local, txqi); +-+} +-+ +- /* +- * splice packets from the STA's pending to the local pending, +- * requires a call to ieee80211_agg_splice_finish later +-@@ -247,6 +284,7 @@ static void ieee80211_remove_tid_tx(stru +- ieee80211_assign_tid_tx(sta, tid, NULL); +- +- ieee80211_agg_splice_finish(sta->sdata, tid); +-+ ieee80211_agg_start_txq(sta, tid, false); +- +- kfree_rcu(tid_tx, rcu_head); +- } +-@@ -418,6 +456,8 @@ void ieee80211_tx_ba_session_handle_star +- */ +- clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); +- +-+ ieee80211_agg_stop_txq(sta, tid); +-+ +- /* +- * Make sure no packets are being processed. This ensures that +- * we have a valid starting sequence number and that in-flight +-@@ -440,6 +480,8 @@ void ieee80211_tx_ba_session_handle_star +- ieee80211_agg_splice_finish(sdata, tid); +- spin_unlock_bh(&sta->lock); +- +-+ ieee80211_agg_start_txq(sta, tid, false); +-+ +- kfree_rcu(tid_tx, rcu_head); +- return; +- } +-@@ -666,6 +708,8 @@ static void ieee80211_agg_tx_operational +- ieee80211_agg_splice_finish(sta->sdata, tid); +- +- spin_unlock_bh(&sta->lock); +-+ +-+ ieee80211_agg_start_txq(sta, tid, true); +- } +- +- void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) +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 +new file mode 100644 +index 0000000..4faac0d +--- /dev/null ++++ b/package/kernel/mac80211/patches/301-ath9k-limit-retries-for-powersave-response-frames.patch +@@ -0,0 +1,121 @@ ++From: Felix Fietkau ++Date: Thu, 2 Jul 2015 15:20:56 +0200 ++Subject: [PATCH] ath9k: limit retries for powersave response frames ++ ++In some cases, the channel might be busy enough that an ath9k AP's ++response to PS-Poll frames might be too slow and the station has already ++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 ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/xmit.c +++++ b/drivers/net/wireless/ath/ath9k/xmit.c ++@@ -147,10 +147,25 @@ static void ath_send_bar(struct ath_atx_ ++ } ++ ++ static void ath_set_rates(struct ieee80211_vif *vif, struct ieee80211_sta *sta, ++- struct ath_buf *bf) +++ struct ath_buf *bf, bool ps) ++ { +++ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu); +++ +++ if (ps) { +++ /* Clear the first rate to avoid using a sample rate for PS frames */ +++ info->control.rates[0].idx = -1; +++ info->control.rates[0].count = 0; +++ } +++ ++ ieee80211_get_tx_rates(vif, sta, bf->bf_mpdu, bf->rates, ++ ARRAY_SIZE(bf->rates)); +++ if (!ps) +++ return; +++ +++ if (bf->rates[0].count > 2) +++ bf->rates[0].count = 2; +++ +++ bf->rates[1].idx = -1; ++ } ++ ++ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, ++@@ -1430,7 +1445,7 @@ ath_tx_form_burst(struct ath_softc *sc, ++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) ++ break; ++ ++- ath_set_rates(tid->an->vif, tid->an->sta, bf); +++ ath_set_rates(tid->an->vif, tid->an->sta, bf, false); ++ } while (1); ++ } ++ ++@@ -1461,7 +1476,7 @@ static bool ath_tx_sched_aggr(struct ath ++ return false; ++ } ++ ++- ath_set_rates(tid->an->vif, tid->an->sta, bf); +++ 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); ++@@ -1653,7 +1668,7 @@ void ath9k_release_buffered_frames(struc ++ ++ __skb_unlink(bf->bf_mpdu, tid_q); ++ list_add_tail(&bf->list, &bf_q); ++- ath_set_rates(tid->an->vif, tid->an->sta, bf); +++ ath_set_rates(tid->an->vif, tid->an->sta, bf, true); ++ if (bf_isampdu(bf)) { ++ ath_tx_addto_baw(sc, tid, bf); ++ bf->bf_state.bf_type &= ~BUF_AGGR; ++@@ -2318,7 +2333,7 @@ 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, skip_uapsd = false, ps_resp; +++ bool queue, ps_resp; ++ int q, ret; ++ ++ if (vif) ++@@ -2365,13 +2380,13 @@ int ath_tx_start(struct ieee80211_hw *hw ++ if (!txctl->an) ++ txctl->an = &avp->mcast_node; ++ queue = true; ++- skip_uapsd = true; +++ ps_resp = false; ++ } ++ ++ if (txctl->an && queue) ++ tid = ath_get_skb_tid(sc, txctl->an, skb); ++ ++- if (!skip_uapsd && ps_resp) { +++ if (ps_resp) { ++ ath_txq_unlock(sc, txq); ++ txq = sc->tx.uapsdq; ++ ath_txq_lock(sc, txq); ++@@ -2409,7 +2424,7 @@ int ath_tx_start(struct ieee80211_hw *hw ++ if (txctl->paprd) ++ bf->bf_state.bfs_paprd_timestamp = jiffies; ++ ++- ath_set_rates(vif, sta, bf); +++ ath_set_rates(vif, sta, bf, ps_resp); ++ ath_tx_send_normal(sc, txq, tid, skb); ++ ++ out: ++@@ -2448,7 +2463,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw ++ break; ++ ++ bf->bf_lastbf = bf; ++- ath_set_rates(vif, NULL, bf); +++ ath_set_rates(vif, NULL, bf, false); ++ ath_buf_set_rate(sc, bf, &info, fi->framelen, false); ++ duration += info.rates[0].PktDuration; ++ if (bf_tail) ++@@ -2968,7 +2983,7 @@ int ath9k_tx99_send(struct ath_softc *sc ++ return -EINVAL; ++ } ++ ++- ath_set_rates(sc->tx99_vif, NULL, bf); +++ ath_set_rates(sc->tx99_vif, NULL, bf, false); ++ ++ ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, bf->bf_daddr); ++ ath9k_hw_tx99_start(sc->sc_ah, txctl->txq->axq_qnum); +diff --git a/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch b/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch +deleted file mode 100644 +index 465d943..0000000 +--- a/package/kernel/mac80211/patches/301-mac80211-lock-rate-control.patch ++++ /dev/null +@@ -1,125 +0,0 @@ +-From: Johannes Berg +-Date: Wed, 11 Mar 2015 09:14:15 +0100 +-Subject: [PATCH] mac80211: lock rate control +- +-Both minstrel (reported by Sven Eckelmann) and the iwlwifi rate +-control aren't properly taking concurrency into account. It's +-likely that the same is true for other rate control algorithms. +- +-In the case of minstrel this manifests itself in crashes when an +-update and other data access are run concurrently, for example +-when the stations change bandwidth or similar. In iwlwifi, this +-can cause firmware crashes. +- +-Since fixing all rate control algorithms will be very difficult, +-just provide locking for invocations. This protects the internal +-data structures the algorithms maintain. +- +-I've manipulated hostapd to test this, by having it change its +-advertised bandwidth roughly ever 150ms. At the same time, I'm +-running a flood ping between the client and the AP, which causes +-this race of update vs. get_rate/status to easily happen on the +-client. With this change, the system survives this test. +- +-Reported-by: Sven Eckelmann +-Signed-off-by: Johannes Berg +---- +- +---- a/net/mac80211/rate.c +-+++ b/net/mac80211/rate.c +-@@ -683,7 +683,13 @@ void rate_control_get_rate(struct ieee80 +- if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) +- return; +- +-- ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); +-+ if (ista) { +-+ spin_lock_bh(&sta->rate_ctrl_lock); +-+ ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); +-+ spin_unlock_bh(&sta->rate_ctrl_lock); +-+ } else { +-+ ref->ops->get_rate(ref->priv, NULL, NULL, txrc); +-+ } +- +- if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_RC_TABLE) +- return; +---- a/net/mac80211/rate.h +-+++ b/net/mac80211/rate.h +-@@ -42,10 +42,12 @@ static inline void rate_control_tx_statu +- if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) +- return; +- +-+ spin_lock_bh(&sta->rate_ctrl_lock); +- if (ref->ops->tx_status) +- ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); +- else +- ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); +-+ spin_unlock_bh(&sta->rate_ctrl_lock); +- } +- +- static inline void +-@@ -64,7 +66,9 @@ rate_control_tx_status_noskb(struct ieee +- if (WARN_ON_ONCE(!ref->ops->tx_status_noskb)) +- return; +- +-+ spin_lock_bh(&sta->rate_ctrl_lock); +- ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); +-+ spin_unlock_bh(&sta->rate_ctrl_lock); +- } +- +- static inline void rate_control_rate_init(struct sta_info *sta) +-@@ -91,8 +95,10 @@ static inline void rate_control_rate_ini +- +- sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; +- +-+ spin_lock_bh(&sta->rate_ctrl_lock); +- ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista, +- priv_sta); +-+ spin_unlock_bh(&sta->rate_ctrl_lock); +- rcu_read_unlock(); +- set_sta_flag(sta, WLAN_STA_RATE_CONTROL); +- } +-@@ -115,18 +121,20 @@ static inline void rate_control_rate_upd +- return; +- } +- +-+ spin_lock_bh(&sta->rate_ctrl_lock); +- ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def, +- ista, priv_sta, changed); +-+ spin_unlock_bh(&sta->rate_ctrl_lock); +- rcu_read_unlock(); +- } +- drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); +- } +- +- static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, +-- struct ieee80211_sta *sta, +-- gfp_t gfp) +-+ struct sta_info *sta, gfp_t gfp) +- { +-- return ref->ops->alloc_sta(ref->priv, sta, gfp); +-+ spin_lock_init(&sta->rate_ctrl_lock); +-+ return ref->ops->alloc_sta(ref->priv, &sta->sta, gfp); +- } +- +- static inline void rate_control_free_sta(struct sta_info *sta) +---- a/net/mac80211/sta_info.c +-+++ b/net/mac80211/sta_info.c +-@@ -286,7 +286,7 @@ static int sta_prepare_rate_control(stru +- +- sta->rate_ctrl = local->rate_ctrl; +- sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, +-- &sta->sta, gfp); +-+ sta, gfp); +- if (!sta->rate_ctrl_priv) +- return -ENOMEM; +- +---- a/net/mac80211/sta_info.h +-+++ b/net/mac80211/sta_info.h +-@@ -349,6 +349,7 @@ struct sta_info { +- u8 ptk_idx; +- struct rate_control_ref *rate_ctrl; +- void *rate_ctrl_priv; +-+ spinlock_t rate_ctrl_lock; +- spinlock_t lock; +- +- struct work_struct drv_deliver_wk; +diff --git a/package/kernel/mac80211/patches/302-ath10k-Delay-device-access-after-cold-reset.patch b/package/kernel/mac80211/patches/302-ath10k-Delay-device-access-after-cold-reset.patch +new file mode 100644 +index 0000000..820aa9a +--- /dev/null ++++ b/package/kernel/mac80211/patches/302-ath10k-Delay-device-access-after-cold-reset.patch +@@ -0,0 +1,56 @@ ++From: Vasanthakumar Thiagarajan ++Date: Fri, 3 Jul 2015 11:45:42 +0530 ++Subject: [PATCH] ath10k: Delay device access after cold reset ++ ++It is observed that during cold reset pcie access right ++after a write operation to SOC_GLOBAL_RESET_ADDRESS causes ++Data Bus Error and system hard lockup. The reason ++for bus error is that pcie needs some time to get ++back to stable state for any transaction during cold reset. Add ++delay of 20 msecs after write of SOC_GLOBAL_RESET_ADDRESS ++to fix this issue. ++ ++Signed-off-by: Vasanthakumar Thiagarajan ++--- ++ ++--- a/drivers/net/wireless/ath/ath10k/pci.c +++++ b/drivers/net/wireless/ath/ath10k/pci.c ++@@ -2761,7 +2761,6 @@ static int ath10k_pci_wait_for_target_in ++ ++ static int ath10k_pci_cold_reset(struct ath10k *ar) ++ { ++- int i; ++ u32 val; ++ ++ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n"); ++@@ -2777,23 +2776,18 @@ static int ath10k_pci_cold_reset(struct ++ val |= 1; ++ ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val); ++ ++- for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { ++- if (ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) & ++- RTC_STATE_COLD_RESET_MASK) ++- break; ++- msleep(1); ++- } +++ /* After writing into SOC_GLOBAL_RESET to put device into +++ * reset and pulling out of reset pcie may not be stable +++ * for any immediate pcie register access and cause bus error, +++ * add delay before any pcie access request to fix this issue. +++ */ +++ msleep(20); ++ ++ /* Pull Target, including PCIe, out of RESET. */ ++ val &= ~1; ++ ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val); ++ ++- for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) { ++- if (!(ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) & ++- RTC_STATE_COLD_RESET_MASK)) ++- break; ++- msleep(1); ++- } +++ msleep(20); ++ ++ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset complete\n"); ++ +diff --git a/package/kernel/mac80211/patches/302-ath9k-restart-only-triggering-DFS-detector-line.patch b/package/kernel/mac80211/patches/302-ath9k-restart-only-triggering-DFS-detector-line.patch +deleted file mode 100644 +index e54e16e..0000000 +--- a/package/kernel/mac80211/patches/302-ath9k-restart-only-triggering-DFS-detector-line.patch ++++ /dev/null +@@ -1,21 +0,0 @@ +-From: Zefir Kurtisi +-Date: Tue, 10 Mar 2015 17:49:29 +0100 +-Subject: [PATCH] ath9k: restart only triggering DFS detector line +- +-To support HT40 DFS mode, a triggering detector must +-reset only itself but not other detector lines. +- +-Signed-off-by: Zefir Kurtisi +---- +- +---- a/drivers/net/wireless/ath/dfs_pattern_detector.c +-+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c +-@@ -289,7 +289,7 @@ dpd_add_pulse(struct dfs_pattern_detecto +- "count=%d, count_false=%d\n", +- event->freq, pd->rs->type_id, +- ps->pri, ps->count, ps->count_falses); +-- channel_detector_reset(dpd, cd); +-+ pd->reset(pd, dpd->last_pulse_ts); +- return true; +- } +- } +diff --git a/package/kernel/mac80211/patches/303-ath9k-add-DFS-support-for-extension-channel.patch b/package/kernel/mac80211/patches/303-ath9k-add-DFS-support-for-extension-channel.patch +deleted file mode 100644 +index ed268ea..0000000 +--- a/package/kernel/mac80211/patches/303-ath9k-add-DFS-support-for-extension-channel.patch ++++ /dev/null +@@ -1,76 +0,0 @@ +-From: Zefir Kurtisi +-Date: Tue, 10 Mar 2015 17:49:30 +0100 +-Subject: [PATCH] ath9k: add DFS support for extension channel +- +-In HT40 modes, pulse events on primary and extension +-channel are processed individually. If valid, a pulse +-event will be fed into the detector +-* for primary frequency, or +-* for extension frequency (+/-20MHz based on HT40-mode) +-* or both +- +-With that, a 40MHz radar will result in two individual +-radar events. +- +-Signed-off-by: Zefir Kurtisi +---- +- +---- a/drivers/net/wireless/ath/ath9k/dfs.c +-+++ b/drivers/net/wireless/ath/ath9k/dfs.c +-@@ -126,8 +126,19 @@ ath9k_postprocess_radar_event(struct ath +- DFS_STAT_INC(sc, pulses_detected); +- return true; +- } +--#undef PRI_CH_RADAR_FOUND +--#undef EXT_CH_RADAR_FOUND +-+ +-+static void +-+ath9k_dfs_process_radar_pulse(struct ath_softc *sc, struct pulse_event *pe) +-+{ +-+ struct dfs_pattern_detector *pd = sc->dfs_detector; +-+ DFS_STAT_INC(sc, pulses_processed); +-+ if (pd == NULL) +-+ return; +-+ if (!pd->add_pulse(pd, pe)) +-+ return; +-+ DFS_STAT_INC(sc, radar_detected); +-+ ieee80211_radar_detected(sc->hw); +-+} +- +- /* +- * DFS: check PHY-error for radar pulse and feed the detector +-@@ -176,18 +187,21 @@ void ath9k_dfs_process_phyerr(struct ath +- ard.pulse_length_pri = vdata_end[-3]; +- pe.freq = ah->curchan->channel; +- pe.ts = mactime; +-- if (ath9k_postprocess_radar_event(sc, &ard, &pe)) { +-- struct dfs_pattern_detector *pd = sc->dfs_detector; +-- ath_dbg(common, DFS, +-- "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " +-- "width=%d, rssi=%d, delta_ts=%llu\n", +-- pe.freq, pe.ts, pe.width, pe.rssi, +-- pe.ts - sc->dfs_prev_pulse_ts); +-- sc->dfs_prev_pulse_ts = pe.ts; +-- DFS_STAT_INC(sc, pulses_processed); +-- if (pd != NULL && pd->add_pulse(pd, &pe)) { +-- DFS_STAT_INC(sc, radar_detected); +-- ieee80211_radar_detected(sc->hw); +-- } +-+ if (!ath9k_postprocess_radar_event(sc, &ard, &pe)) +-+ return; +-+ +-+ ath_dbg(common, DFS, +-+ "ath9k_dfs_process_phyerr: type=%d, freq=%d, ts=%llu, " +-+ "width=%d, rssi=%d, delta_ts=%llu\n", +-+ ard.pulse_bw_info, pe.freq, pe.ts, pe.width, pe.rssi, +-+ pe.ts - sc->dfs_prev_pulse_ts); +-+ sc->dfs_prev_pulse_ts = pe.ts; +-+ if (ard.pulse_bw_info & PRI_CH_RADAR_FOUND) +-+ ath9k_dfs_process_radar_pulse(sc, &pe); +-+ if (ard.pulse_bw_info & EXT_CH_RADAR_FOUND) { +-+ pe.freq += IS_CHAN_HT40PLUS(ah->curchan) ? 20 : -20; +-+ ath9k_dfs_process_radar_pulse(sc, &pe); +- } +- } +-+#undef PRI_CH_RADAR_FOUND +-+#undef EXT_CH_RADAR_FOUND +diff --git a/package/kernel/mac80211/patches/303-ath9k-add-fast-xmit-support.patch b/package/kernel/mac80211/patches/303-ath9k-add-fast-xmit-support.patch +new file mode 100644 +index 0000000..139015c +--- /dev/null ++++ b/package/kernel/mac80211/patches/303-ath9k-add-fast-xmit-support.patch +@@ -0,0 +1,17 @@ ++From: Felix Fietkau ++Date: Mon, 11 May 2015 18:35:20 +0200 ++Subject: [PATCH] ath9k: add fast-xmit support ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/init.c +++++ b/drivers/net/wireless/ath/ath9k/init.c ++@@ -826,6 +826,7 @@ static void ath9k_set_hw_capab(struct at ++ ieee80211_hw_set(hw, SIGNAL_DBM); ++ ieee80211_hw_set(hw, RX_INCLUDES_FCS); ++ ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING); +++ ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); ++ ++ if (ath9k_ps_enable) ++ ieee80211_hw_set(hw, SUPPORTS_PS); +diff --git a/package/kernel/mac80211/patches/304-ath9k-allow-40MHz-radar-detection-width.patch b/package/kernel/mac80211/patches/304-ath9k-allow-40MHz-radar-detection-width.patch +deleted file mode 100644 +index e1eab64..0000000 +--- a/package/kernel/mac80211/patches/304-ath9k-allow-40MHz-radar-detection-width.patch ++++ /dev/null +@@ -1,19 +0,0 @@ +-From: Zefir Kurtisi +-Date: Tue, 10 Mar 2015 17:49:31 +0100 +-Subject: [PATCH] ath9k: allow 40MHz radar detection width +- +-Signed-off-by: Zefir Kurtisi +---- +- +---- a/drivers/net/wireless/ath/ath9k/init.c +-+++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -763,7 +763,8 @@ static const struct ieee80211_iface_comb +- .num_different_channels = 1, +- .beacon_int_infra_match = true, +- .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | +-- BIT(NL80211_CHAN_WIDTH_20), +-+ BIT(NL80211_CHAN_WIDTH_20) | +-+ BIT(NL80211_CHAN_WIDTH_40), +- } +- #endif +- }; +diff --git a/package/kernel/mac80211/patches/304-ath9k-remove-struct-ath_atx_ac.patch b/package/kernel/mac80211/patches/304-ath9k-remove-struct-ath_atx_ac.patch +new file mode 100644 +index 0000000..9f04276 +--- /dev/null ++++ b/package/kernel/mac80211/patches/304-ath9k-remove-struct-ath_atx_ac.patch +@@ -0,0 +1,385 @@ ++From: Felix Fietkau ++Date: Sat, 4 Apr 2015 18:39:06 +0200 ++Subject: [PATCH] ath9k: remove struct ath_atx_ac ++ ++struct ath_atx_ac contains a list of active TIDs belonging to one WMM AC. ++This patch changes the code to track active station TIDs in the txq directly. ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ath9k.h +++++ b/drivers/net/wireless/ath/ath9k/ath9k.h ++@@ -173,14 +173,6 @@ struct ath_txq { ++ struct sk_buff_head complete_q; ++ }; ++ ++-struct ath_atx_ac { ++- struct ath_txq *txq; ++- struct list_head list; ++- struct list_head tid_q; ++- bool clear_ps_filter; ++- bool sched; ++-}; ++- ++ struct ath_frame_info { ++ struct ath_buf *bf; ++ u16 framelen; ++@@ -243,7 +235,7 @@ struct ath_atx_tid { ++ struct sk_buff_head buf_q; ++ struct sk_buff_head retry_q; ++ struct ath_node *an; ++- struct ath_atx_ac *ac; +++ struct ath_txq *txq; ++ unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; ++ u16 seq_start; ++ u16 seq_next; ++@@ -255,6 +247,7 @@ struct ath_atx_tid { ++ s8 bar_index; ++ bool sched; ++ bool active; +++ bool clear_ps_filter; ++ }; ++ ++ struct ath_node { ++@@ -262,7 +255,6 @@ struct ath_node { ++ 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]; ++- struct ath_atx_ac ac[IEEE80211_NUM_ACS]; ++ ++ u16 maxampdu; ++ u8 mpdudensity; ++--- a/drivers/net/wireless/ath/ath9k/xmit.c +++++ b/drivers/net/wireless/ath/ath9k/xmit.c ++@@ -106,7 +106,6 @@ void ath_txq_unlock_complete(struct ath_ ++ static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq, ++ struct ath_atx_tid *tid) ++ { ++- struct ath_atx_ac *ac = tid->ac; ++ struct list_head *list; ++ struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv; ++ struct ath_chanctx *ctx = avp->chanctx; ++@@ -118,15 +117,8 @@ static void ath_tx_queue_tid(struct ath_ ++ return; ++ ++ tid->sched = true; ++- list_add_tail(&tid->list, &ac->tid_q); ++- ++- if (ac->sched) ++- return; ++- ++- ac->sched = true; ++- ++ list = &ctx->acq[TID_TO_WME_AC(tid->tidno)]; ++- list_add_tail(&ac->list, list); +++ list_add_tail(&tid->list, list); ++ } ++ ++ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) ++@@ -223,7 +215,7 @@ static struct sk_buff *ath_tid_dequeue(s ++ static void ++ ath_tx_tid_change_state(struct ath_softc *sc, struct ath_atx_tid *tid) ++ { ++- struct ath_txq *txq = tid->ac->txq; +++ struct ath_txq *txq = tid->txq; ++ struct ieee80211_tx_info *tx_info; ++ struct sk_buff *skb, *tskb; ++ struct ath_buf *bf; ++@@ -252,7 +244,7 @@ ath_tx_tid_change_state(struct ath_softc ++ ++ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) ++ { ++- struct ath_txq *txq = tid->ac->txq; +++ struct ath_txq *txq = tid->txq; ++ struct sk_buff *skb; ++ struct ath_buf *bf; ++ struct list_head bf_head; ++@@ -659,7 +651,7 @@ static void ath_tx_complete_aggr(struct ++ ath_tx_queue_tid(sc, txq, tid); ++ ++ if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY)) ++- tid->ac->clear_ps_filter = true; +++ tid->clear_ps_filter = true; ++ } ++ } ++ ++@@ -749,7 +741,7 @@ static u32 ath_lookup_rate(struct ath_so ++ struct ieee80211_tx_rate *rates; ++ u32 max_4ms_framelen, frmlen; ++ u16 aggr_limit, bt_aggr_limit, legacy = 0; ++- int q = tid->ac->txq->mac80211_qnum; +++ int q = tid->txq->mac80211_qnum; ++ int i; ++ ++ skb = bf->bf_mpdu; ++@@ -1486,8 +1478,8 @@ static bool ath_tx_sched_aggr(struct ath ++ if (list_empty(&bf_q)) ++ return false; ++ ++- if (tid->ac->clear_ps_filter || tid->an->no_ps_filter) { ++- tid->ac->clear_ps_filter = false; +++ if (tid->clear_ps_filter || tid->an->no_ps_filter) { +++ tid->clear_ps_filter = false; ++ tx_info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; ++ } ++ ++@@ -1506,7 +1498,7 @@ int ath_tx_aggr_start(struct ath_softc * ++ ++ an = (struct ath_node *)sta->drv_priv; ++ txtid = ATH_AN_2_TID(an, tid); ++- txq = txtid->ac->txq; +++ txq = txtid->txq; ++ ++ ath_txq_lock(sc, txq); ++ ++@@ -1540,7 +1532,7 @@ void ath_tx_aggr_stop(struct ath_softc * ++ { ++ struct ath_node *an = (struct ath_node *)sta->drv_priv; ++ struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); ++- struct ath_txq *txq = txtid->ac->txq; +++ struct ath_txq *txq = txtid->txq; ++ ++ ath_txq_lock(sc, txq); ++ txtid->active = false; ++@@ -1553,7 +1545,6 @@ void ath_tx_aggr_sleep(struct ieee80211_ ++ struct ath_node *an) ++ { ++ struct ath_atx_tid *tid; ++- struct ath_atx_ac *ac; ++ struct ath_txq *txq; ++ bool buffered; ++ int tidno; ++@@ -1561,8 +1552,7 @@ void ath_tx_aggr_sleep(struct ieee80211_ ++ for (tidno = 0, tid = &an->tid[tidno]; ++ tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { ++ ++- ac = tid->ac; ++- txq = ac->txq; +++ txq = tid->txq; ++ ++ ath_txq_lock(sc, txq); ++ ++@@ -1576,11 +1566,6 @@ void ath_tx_aggr_sleep(struct ieee80211_ ++ tid->sched = false; ++ list_del(&tid->list); ++ ++- if (ac->sched) { ++- ac->sched = false; ++- list_del(&ac->list); ++- } ++- ++ ath_txq_unlock(sc, txq); ++ ++ ieee80211_sta_set_buffered(sta, tidno, buffered); ++@@ -1590,18 +1575,16 @@ void ath_tx_aggr_sleep(struct ieee80211_ ++ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) ++ { ++ struct ath_atx_tid *tid; ++- struct ath_atx_ac *ac; ++ struct ath_txq *txq; ++ int tidno; ++ ++ for (tidno = 0, tid = &an->tid[tidno]; ++ tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { ++ ++- ac = tid->ac; ++- txq = ac->txq; +++ txq = tid->txq; ++ ++ ath_txq_lock(sc, txq); ++- ac->clear_ps_filter = true; +++ tid->clear_ps_filter = true; ++ ++ if (ath_tid_has_buffered(tid)) { ++ ath_tx_queue_tid(sc, txq, tid); ++@@ -1621,7 +1604,7 @@ void ath_tx_aggr_resume(struct ath_softc ++ ++ an = (struct ath_node *)sta->drv_priv; ++ tid = ATH_AN_2_TID(an, tidno); ++- txq = tid->ac->txq; +++ txq = tid->txq; ++ ++ ath_txq_lock(sc, txq); ++ ++@@ -1660,7 +1643,7 @@ void ath9k_release_buffered_frames(struc ++ ++ tid = ATH_AN_2_TID(an, i); ++ ++- ath_txq_lock(sc, tid->ac->txq); +++ ath_txq_lock(sc, tid->txq); ++ while (nframes > 0) { ++ bf = ath_tx_get_tid_subframe(sc, sc->tx.uapsdq, tid, &tid_q); ++ if (!bf) ++@@ -1684,7 +1667,7 @@ void ath9k_release_buffered_frames(struc ++ if (an->sta && !ath_tid_has_buffered(tid)) ++ ieee80211_sta_set_buffered(an->sta, i, false); ++ } ++- ath_txq_unlock_complete(sc, tid->ac->txq); +++ ath_txq_unlock_complete(sc, tid->txq); ++ } ++ ++ if (list_empty(&bf_q)) ++@@ -1933,9 +1916,8 @@ void ath_tx_cleanupq(struct ath_softc *s ++ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) ++ { ++ struct ath_common *common = ath9k_hw_common(sc->sc_ah); ++- struct ath_atx_ac *ac, *last_ac; ++ struct ath_atx_tid *tid, *last_tid; ++- struct list_head *ac_list; +++ struct list_head *tid_list; ++ bool sent = false; ++ ++ if (txq->mac80211_qnum < 0) ++@@ -1945,63 +1927,46 @@ void ath_txq_schedule(struct ath_softc * ++ return; ++ ++ spin_lock_bh(&sc->chan_lock); ++- ac_list = &sc->cur_chan->acq[txq->mac80211_qnum]; +++ tid_list = &sc->cur_chan->acq[txq->mac80211_qnum]; ++ ++- if (list_empty(ac_list)) { +++ if (list_empty(tid_list)) { ++ spin_unlock_bh(&sc->chan_lock); ++ return; ++ } ++ ++ rcu_read_lock(); ++ ++- last_ac = list_entry(ac_list->prev, struct ath_atx_ac, list); ++- while (!list_empty(ac_list)) { +++ last_tid = list_entry(tid_list->prev, struct ath_atx_tid, list); +++ while (!list_empty(tid_list)) { ++ bool stop = false; ++ ++ if (sc->cur_chan->stopped) ++ break; ++ ++- ac = list_first_entry(ac_list, struct ath_atx_ac, list); ++- last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); ++- list_del(&ac->list); ++- ac->sched = false; ++- ++- while (!list_empty(&ac->tid_q)) { ++- ++- tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, ++- list); ++- list_del(&tid->list); ++- tid->sched = false; ++- ++- if (ath_tx_sched_aggr(sc, txq, tid, &stop)) ++- sent = true; ++- ++- /* ++- * add tid to round-robin queue if more frames ++- * are pending for the tid ++- */ ++- if (ath_tid_has_buffered(tid)) ++- ath_tx_queue_tid(sc, txq, tid); +++ tid = list_first_entry(tid_list, struct ath_atx_tid, list); +++ list_del(&tid->list); +++ tid->sched = false; ++ ++- if (stop || tid == last_tid) ++- break; ++- } +++ if (ath_tx_sched_aggr(sc, txq, tid, &stop)) +++ sent = true; ++ ++- if (!list_empty(&ac->tid_q) && !ac->sched) { ++- ac->sched = true; ++- list_add_tail(&ac->list, ac_list); ++- } +++ /* +++ * add tid to round-robin queue if more frames +++ * are pending for the tid +++ */ +++ if (ath_tid_has_buffered(tid)) +++ ath_tx_queue_tid(sc, txq, tid); ++ ++ if (stop) ++ break; ++ ++- if (ac == last_ac) { +++ if (tid == last_tid) { ++ if (!sent) ++ break; ++ ++ sent = false; ++- last_ac = list_entry(ac_list->prev, ++- struct ath_atx_ac, list); +++ last_tid = list_entry(tid_list->prev, +++ struct ath_atx_tid, list); ++ } ++ } ++ ++@@ -2391,10 +2356,10 @@ int ath_tx_start(struct ieee80211_hw *hw ++ txq = sc->tx.uapsdq; ++ ath_txq_lock(sc, txq); ++ } else if (txctl->an && queue) { ++- WARN_ON(tid->ac->txq != txctl->txq); +++ WARN_ON(tid->txq != txctl->txq); ++ ++ if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) ++- tid->ac->clear_ps_filter = true; +++ tid->clear_ps_filter = true; ++ ++ /* ++ * Add this frame to software queue for scheduling later ++@@ -2888,7 +2853,6 @@ int ath_tx_init(struct ath_softc *sc, in ++ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) ++ { ++ struct ath_atx_tid *tid; ++- struct ath_atx_ac *ac; ++ int tidno, acno; ++ ++ for (tidno = 0, tid = &an->tid[tidno]; ++@@ -2901,24 +2865,16 @@ void ath_tx_node_init(struct ath_softc * ++ tid->baw_head = tid->baw_tail = 0; ++ tid->sched = false; ++ tid->active = false; +++ tid->clear_ps_filter = true; ++ __skb_queue_head_init(&tid->buf_q); ++ __skb_queue_head_init(&tid->retry_q); ++ acno = TID_TO_WME_AC(tidno); ++- tid->ac = &an->ac[acno]; ++- } ++- ++- for (acno = 0, ac = &an->ac[acno]; ++- acno < IEEE80211_NUM_ACS; acno++, ac++) { ++- ac->sched = false; ++- ac->clear_ps_filter = true; ++- ac->txq = sc->tx.txq_map[acno]; ++- INIT_LIST_HEAD(&ac->tid_q); +++ tid->txq = sc->tx.txq_map[acno]; ++ } ++ } ++ ++ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) ++ { ++- struct ath_atx_ac *ac; ++ struct ath_atx_tid *tid; ++ struct ath_txq *txq; ++ int tidno; ++@@ -2926,8 +2882,7 @@ void ath_tx_node_cleanup(struct ath_soft ++ for (tidno = 0, tid = &an->tid[tidno]; ++ tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { ++ ++- ac = tid->ac; ++- txq = ac->txq; +++ txq = tid->txq; ++ ++ ath_txq_lock(sc, txq); ++ ++@@ -2936,11 +2891,6 @@ void ath_tx_node_cleanup(struct ath_soft ++ tid->sched = false; ++ } ++ ++- if (ac->sched) { ++- list_del(&ac->list); ++- tid->ac->sched = false; ++- } ++- ++ ath_tid_drain(sc, txq, tid); ++ tid->active = false; ++ +diff --git a/package/kernel/mac80211/patches/305-ath5k-channel-change-fix.patch b/package/kernel/mac80211/patches/305-ath5k-channel-change-fix.patch +deleted file mode 100644 +index 4cfa53f..0000000 +--- a/package/kernel/mac80211/patches/305-ath5k-channel-change-fix.patch ++++ /dev/null +@@ -1,137 +0,0 @@ +-From: Sergey Ryazanov +-Date: Wed, 4 Mar 2015 05:12:10 +0300 +-Subject: [PATCH] ath5k: channel change fix +- +-ath5k updates the channel pointer and after that it stops the Rx logic +-and apply channel to HW. In case of channel switch, such sequence +-creates a small window when a frame, which is received on the old +-channel is considered as a frame received on the new one. +- +-The most notable consequence of this situation occurs during the switch +-from 2 GHz band (CCK+OFDM) to the 5GHz band (OFDM-only). Frame received +-with CCK rate, e.g. beacon received at the 1mbps, causes the following +-warning: +- +- WARNING: at ath5k/base.c:589 ath5k_tasklet_rx+0x318/0x6ec [ath5k]() +- invalid hw_rix: 1a +- [..] +- Call Trace: +- [<802656a8>] show_stack+0x48/0x70 +- [<802dd92c>] warn_slowpath_common+0x88/0xbc +- [<802dd98c>] warn_slowpath_fmt+0x2c/0x38 +- [<81b51be8>] ath5k_tasklet_rx+0x318/0x6ec [ath5k] +- [<8028ac64>] tasklet_action+0x8c/0xf0 +- [<80075804>] __do_softirq+0x180/0x32c +- [<80196ce8>] irq_exit+0x54/0x70 +- [<80041848>] ret_from_irq+0x0/0x4 +- [<80182fdc>] ioread32+0x4/0xc +- [<81b4c42c>] ath5k_hw_set_sleep_clock+0x2ec/0x474 [ath5k] +- [<81b4cf28>] ath5k_hw_reset+0x50/0xeb8 [ath5k] +- [<81b50900>] ath5k_reset+0xd4/0x310 [ath5k] +- [<81b557e8>] ath5k_config+0x4c/0x104 [ath5k] +- [<80d01770>] ieee80211_hw_config+0x2f4/0x35c [mac80211] +- [<80d09aa8>] ieee80211_scan_work+0x2e4/0x414 [mac80211] +- [<8022c3f4>] process_one_work+0x28c/0x400 +- [<802df8f8>] worker_thread+0x258/0x3c0 +- [<801b5710>] kthread+0xe0/0xec +- [<800418a8>] ret_from_kernel_thread+0x14/0x1c +- +-The easiest way to reproduce this warning is to run scan with dualband +-NIC in noisy environments, when the channel 11 runs multiple APs. In my +-tests if the APs num >= 12, the warning appears in the first few +-seconds of scanning. +- +-In order to fix this, the Rx disable code moved to a higher level and +-placed before the channel pointer update. This is also makes the code a +-bit more symmetrical, since we disable and enable the Rx in the same +-function. +- +-In fact, at the pointer update time new frames should not appear, +-because interrupt generation at this point should already be disabled. +-The next patch should address this issue. +- +-CC: Jiri Slaby +-CC: Nick Kossifidis +-CC: Luis R. Rodriguez +-Reported-by: Christophe Prevotaux +-Tested-by: Christophe Prevotaux +-Tested-by: Eric Bree +-Signed-off-by: Sergey Ryazanov +---- +- +---- a/drivers/net/wireless/ath/ath5k/base.c +-+++ b/drivers/net/wireless/ath/ath5k/base.c +-@@ -2858,7 +2858,7 @@ ath5k_reset(struct ath5k_hw *ah, struct +- { +- struct ath_common *common = ath5k_hw_common(ah); +- int ret, ani_mode; +-- bool fast; +-+ bool fast = chan && modparam_fastchanswitch ? 1 : 0; +- +- ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n"); +- +-@@ -2876,11 +2876,29 @@ ath5k_reset(struct ath5k_hw *ah, struct +- * so we should also free any remaining +- * tx buffers */ +- ath5k_drain_tx_buffs(ah); +-+ +-+ /* Stop PCU */ +-+ ath5k_hw_stop_rx_pcu(ah); +-+ +-+ /* Stop DMA +-+ * +-+ * Note: If DMA didn't stop continue +-+ * since only a reset will fix it. +-+ */ +-+ ret = ath5k_hw_dma_stop(ah); +-+ +-+ /* RF Bus grant won't work if we have pending +-+ * frames +-+ */ +-+ if (ret && fast) { +-+ ATH5K_DBG(ah, ATH5K_DEBUG_RESET, +-+ "DMA didn't stop, falling back to normal reset\n"); +-+ fast = false; +-+ } +-+ +- if (chan) +- ah->curchan = chan; +- +-- fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; +-- +- ret = ath5k_hw_reset(ah, ah->opmode, ah->curchan, fast, skip_pcu); +- if (ret) { +- ATH5K_ERR(ah, "can't reset hardware (%d)\n", ret); +---- a/drivers/net/wireless/ath/ath5k/reset.c +-+++ b/drivers/net/wireless/ath/ath5k/reset.c +-@@ -1169,30 +1169,6 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum +- if (ah->ah_version == AR5K_AR5212) +- ath5k_hw_set_sleep_clock(ah, false); +- +-- /* +-- * Stop PCU +-- */ +-- ath5k_hw_stop_rx_pcu(ah); +-- +-- /* +-- * Stop DMA +-- * +-- * Note: If DMA didn't stop continue +-- * since only a reset will fix it. +-- */ +-- ret = ath5k_hw_dma_stop(ah); +-- +-- /* RF Bus grant won't work if we have pending +-- * frames */ +-- if (ret && fast) { +-- ATH5K_DBG(ah, ATH5K_DEBUG_RESET, +-- "DMA didn't stop, falling back to normal reset\n"); +-- fast = false; +-- /* Non fatal, just continue with +-- * normal reset */ +-- ret = 0; +-- } +-- +- mode = channel->hw_value; +- switch (mode) { +- case AR5K_MODE_11A: +diff --git a/package/kernel/mac80211/patches/305-ath9k-remove-the-sched-field-in-struct-ath_atx_tid.patch b/package/kernel/mac80211/patches/305-ath9k-remove-the-sched-field-in-struct-ath_atx_tid.patch +new file mode 100644 +index 0000000..ec860dc +--- /dev/null ++++ b/package/kernel/mac80211/patches/305-ath9k-remove-the-sched-field-in-struct-ath_atx_tid.patch +@@ -0,0 +1,90 @@ ++From: Felix Fietkau ++Date: Sat, 4 Apr 2015 18:42:33 +0200 ++Subject: [PATCH] ath9k: remove the sched field in struct ath_atx_tid ++ ++Use list_empty(&tid->list) instead ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ath9k.h +++++ b/drivers/net/wireless/ath/ath9k/ath9k.h ++@@ -245,7 +245,6 @@ struct ath_atx_tid { ++ int baw_tail; /* next unused tx buffer slot */ ++ ++ s8 bar_index; ++- bool sched; ++ bool active; ++ bool clear_ps_filter; ++ }; ++--- a/drivers/net/wireless/ath/ath9k/xmit.c +++++ b/drivers/net/wireless/ath/ath9k/xmit.c ++@@ -113,12 +113,9 @@ static void ath_tx_queue_tid(struct ath_ ++ if (!ctx) ++ return; ++ ++- if (tid->sched) ++- return; ++- ++- tid->sched = true; ++ list = &ctx->acq[TID_TO_WME_AC(tid->tidno)]; ++- list_add_tail(&tid->list, list); +++ if (list_empty(&tid->list)) +++ list_add_tail(&tid->list, list); ++ } ++ ++ static struct ath_frame_info *get_frame_info(struct sk_buff *skb) ++@@ -1556,15 +1553,14 @@ void ath_tx_aggr_sleep(struct ieee80211_ ++ ++ ath_txq_lock(sc, txq); ++ ++- if (!tid->sched) { +++ if (list_empty(&tid->list)) { ++ ath_txq_unlock(sc, txq); ++ continue; ++ } ++ ++ buffered = ath_tid_has_buffered(tid); ++ ++- tid->sched = false; ++- list_del(&tid->list); +++ list_del_init(&tid->list); ++ ++ ath_txq_unlock(sc, txq); ++ ++@@ -1944,8 +1940,7 @@ void ath_txq_schedule(struct ath_softc * ++ break; ++ ++ tid = list_first_entry(tid_list, struct ath_atx_tid, list); ++- list_del(&tid->list); ++- tid->sched = false; +++ list_del_init(&tid->list); ++ ++ if (ath_tx_sched_aggr(sc, txq, tid, &stop)) ++ sent = true; ++@@ -2863,11 +2858,11 @@ void ath_tx_node_init(struct ath_softc * ++ tid->seq_start = tid->seq_next = 0; ++ tid->baw_size = WME_MAX_BA; ++ tid->baw_head = tid->baw_tail = 0; ++- tid->sched = false; ++ tid->active = false; ++ tid->clear_ps_filter = true; ++ __skb_queue_head_init(&tid->buf_q); ++ __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]; ++ } ++@@ -2886,10 +2881,8 @@ void ath_tx_node_cleanup(struct ath_soft ++ ++ ath_txq_lock(sc, txq); ++ ++- if (tid->sched) { ++- list_del(&tid->list); ++- tid->sched = false; ++- } +++ if (!list_empty(&tid->list)) +++ list_del_init(&tid->list); ++ ++ ath_tid_drain(sc, txq, tid); ++ tid->active = false; +diff --git a/package/kernel/mac80211/patches/306-ath5k-fix-reset-race.patch b/package/kernel/mac80211/patches/306-ath5k-fix-reset-race.patch +deleted file mode 100644 +index 85a1904..0000000 +--- a/package/kernel/mac80211/patches/306-ath5k-fix-reset-race.patch ++++ /dev/null +@@ -1,96 +0,0 @@ +-From: Sergey Ryazanov +-Date: Wed, 4 Mar 2015 05:12:11 +0300 +-Subject: [PATCH] ath5k: fix reset race +- +-To prepare for reset ath5k should finish all asynchronous tasks. At +-first, it disables the interrupt generation, then it waits for the +-interrupt handler and tasklets completion, and then proceeds to the HW +-configuration update. But it does not consider that the interrupt +-handler or tasklet re-enables the interrupt generation. And we fall in a +-situation when ath5k assumes that interrupts are disabled, but it is +-not. +- +-This can lead to different consequences, such as reception of the frame, +-when we do not expect it. Under certain circumstances, this can lead to +-the following warning: +- +- WARNING: at ath5k/base.c:589 ath5k_tasklet_rx+0x318/0x6ec [ath5k]() +- invalid hw_rix: 1a +- [..] +- Call Trace: +- [<802656a8>] show_stack+0x48/0x70 +- [<802dd92c>] warn_slowpath_common+0x88/0xbc +- [<802dd98c>] warn_slowpath_fmt+0x2c/0x38 +- [<81b51be8>] ath5k_tasklet_rx+0x318/0x6ec [ath5k] +- [<8028ac64>] tasklet_action+0x8c/0xf0 +- [<80075804>] __do_softirq+0x180/0x32c +- [<80196ce8>] irq_exit+0x54/0x70 +- [<80041848>] ret_from_irq+0x0/0x4 +- [<80182fdc>] ioread32+0x4/0xc +- [<81b4c42c>] ath5k_hw_set_sleep_clock+0x2ec/0x474 [ath5k] +- [<81b4cf28>] ath5k_hw_reset+0x50/0xeb8 [ath5k] +- [<81b50900>] ath5k_reset+0xd4/0x310 [ath5k] +- [<81b557e8>] ath5k_config+0x4c/0x104 [ath5k] +- [<80d01770>] ieee80211_hw_config+0x2f4/0x35c [mac80211] +- [<80d09aa8>] ieee80211_scan_work+0x2e4/0x414 [mac80211] +- [<8022c3f4>] process_one_work+0x28c/0x400 +- [<802df8f8>] worker_thread+0x258/0x3c0 +- [<801b5710>] kthread+0xe0/0xec +- [<800418a8>] ret_from_kernel_thread+0x14/0x1c +- +-Fix this issue by adding a new status flag, which forbids to re-enable +-the interrupt generation until the HW configuration is completed. +- +-Note: previous patch, which reorders the Rx disable code helps to avoid +-the above warning, but not fixes the root cause of unexpected frame +-receiving. +- +-CC: Jiri Slaby +-CC: Nick Kossifidis +-CC: Luis R. Rodriguez +-Reported-by: Christophe Prevotaux +-Tested-by: Christophe Prevotaux +-Tested-by: Eric Bree +-Signed-off-by: Sergey Ryazanov +---- +- +---- a/drivers/net/wireless/ath/ath5k/ath5k.h +-+++ b/drivers/net/wireless/ath/ath5k/ath5k.h +-@@ -1283,6 +1283,7 @@ struct ath5k_hw { +- #define ATH_STAT_PROMISC 1 +- #define ATH_STAT_LEDSOFT 2 /* enable LED gpio status */ +- #define ATH_STAT_STARTED 3 /* opened & irqs enabled */ +-+#define ATH_STAT_RESET 4 /* hw reset */ +- +- unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ +- unsigned int fif_filter_flags; /* Current FIF_* filter flags */ +---- a/drivers/net/wireless/ath/ath5k/base.c +-+++ b/drivers/net/wireless/ath/ath5k/base.c +-@@ -1523,6 +1523,9 @@ ath5k_set_current_imask(struct ath5k_hw +- enum ath5k_int imask; +- unsigned long flags; +- +-+ if (test_bit(ATH_STAT_RESET, ah->status)) +-+ return; +-+ +- spin_lock_irqsave(&ah->irqlock, flags); +- imask = ah->imask; +- if (ah->rx_pending) +-@@ -2862,6 +2865,8 @@ ath5k_reset(struct ath5k_hw *ah, struct +- +- ATH5K_DBG(ah, ATH5K_DEBUG_RESET, "resetting\n"); +- +-+ __set_bit(ATH_STAT_RESET, ah->status); +-+ +- ath5k_hw_set_imr(ah, 0); +- synchronize_irq(ah->irq); +- ath5k_stop_tasklets(ah); +-@@ -2952,6 +2957,8 @@ ath5k_reset(struct ath5k_hw *ah, struct +- */ +- /* ath5k_chan_change(ah, c); */ +- +-+ __clear_bit(ATH_STAT_RESET, ah->status); +-+ +- ath5k_beacon_config(ah); +- /* intrs are enabled by ath5k_beacon_config */ +- +diff --git a/package/kernel/mac80211/patches/306-mac80211-Deinline-rate_control_rate_init-rate_contro.patch b/package/kernel/mac80211/patches/306-mac80211-Deinline-rate_control_rate_init-rate_contro.patch +new file mode 100644 +index 0000000..928c93b +--- /dev/null ++++ b/package/kernel/mac80211/patches/306-mac80211-Deinline-rate_control_rate_init-rate_contro.patch +@@ -0,0 +1,161 @@ ++From: Denys Vlasenko ++Date: Wed, 15 Jul 2015 14:56:06 +0200 ++Subject: [PATCH] mac80211: Deinline rate_control_rate_init, ++ rate_control_rate_update ++ ++With this .config: http://busybox.net/~vda/kernel_config, ++after deinlining these functions have sizes and callsite counts ++as follows: ++ ++rate_control_rate_init: 554 bytes, 8 calls ++rate_control_rate_update: 1596 bytes, 5 calls ++ ++Total size reduction: about 11 kbytes. ++ ++Signed-off-by: Denys Vlasenko ++CC: John Linville ++CC: Michal Kazior ++CC: Johannes Berg ++Cc: linux-wireless@vger.kernel.org ++Cc: netdev@vger.kernel.org ++CC: linux-kernel@vger.kernel.org ++--- ++ ++--- a/net/mac80211/rate.c +++++ b/net/mac80211/rate.c ++@@ -29,6 +29,65 @@ module_param(ieee80211_default_rc_algo, ++ MODULE_PARM_DESC(ieee80211_default_rc_algo, ++ "Default rate control algorithm for mac80211 to use"); ++ +++void rate_control_rate_init(struct sta_info *sta) +++{ +++ struct ieee80211_local *local = sta->sdata->local; +++ struct rate_control_ref *ref = sta->rate_ctrl; +++ struct ieee80211_sta *ista = &sta->sta; +++ void *priv_sta = sta->rate_ctrl_priv; +++ struct ieee80211_supported_band *sband; +++ struct ieee80211_chanctx_conf *chanctx_conf; +++ +++ ieee80211_sta_set_rx_nss(sta); +++ +++ if (!ref) +++ return; +++ +++ rcu_read_lock(); +++ +++ chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf); +++ if (WARN_ON(!chanctx_conf)) { +++ rcu_read_unlock(); +++ return; +++ } +++ +++ sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; +++ +++ spin_lock_bh(&sta->rate_ctrl_lock); +++ ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista, +++ priv_sta); +++ spin_unlock_bh(&sta->rate_ctrl_lock); +++ rcu_read_unlock(); +++ set_sta_flag(sta, WLAN_STA_RATE_CONTROL); +++} +++ +++void rate_control_rate_update(struct ieee80211_local *local, +++ struct ieee80211_supported_band *sband, +++ struct sta_info *sta, u32 changed) +++{ +++ struct rate_control_ref *ref = local->rate_ctrl; +++ struct ieee80211_sta *ista = &sta->sta; +++ void *priv_sta = sta->rate_ctrl_priv; +++ struct ieee80211_chanctx_conf *chanctx_conf; +++ +++ if (ref && ref->ops->rate_update) { +++ rcu_read_lock(); +++ +++ chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf); +++ if (WARN_ON(!chanctx_conf)) { +++ rcu_read_unlock(); +++ return; +++ } +++ +++ spin_lock_bh(&sta->rate_ctrl_lock); +++ ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def, +++ ista, priv_sta, changed); +++ spin_unlock_bh(&sta->rate_ctrl_lock); +++ rcu_read_unlock(); +++ } +++ drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); +++} +++ ++ int ieee80211_rate_control_register(const struct rate_control_ops *ops) ++ { ++ struct rate_control_alg *alg; ++--- a/net/mac80211/rate.h +++++ b/net/mac80211/rate.h ++@@ -71,64 +71,10 @@ rate_control_tx_status_noskb(struct ieee ++ spin_unlock_bh(&sta->rate_ctrl_lock); ++ } ++ ++-static inline void rate_control_rate_init(struct sta_info *sta) ++-{ ++- struct ieee80211_local *local = sta->sdata->local; ++- struct rate_control_ref *ref = sta->rate_ctrl; ++- struct ieee80211_sta *ista = &sta->sta; ++- void *priv_sta = sta->rate_ctrl_priv; ++- struct ieee80211_supported_band *sband; ++- struct ieee80211_chanctx_conf *chanctx_conf; ++- ++- ieee80211_sta_set_rx_nss(sta); ++- ++- if (!ref) ++- return; ++- ++- rcu_read_lock(); ++- ++- chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf); ++- if (WARN_ON(!chanctx_conf)) { ++- rcu_read_unlock(); ++- return; ++- } ++- ++- sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; ++- ++- spin_lock_bh(&sta->rate_ctrl_lock); ++- ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista, ++- priv_sta); ++- spin_unlock_bh(&sta->rate_ctrl_lock); ++- rcu_read_unlock(); ++- set_sta_flag(sta, WLAN_STA_RATE_CONTROL); ++-} ++- ++-static inline void rate_control_rate_update(struct ieee80211_local *local, +++void rate_control_rate_init(struct sta_info *sta); +++void rate_control_rate_update(struct ieee80211_local *local, ++ struct ieee80211_supported_band *sband, ++- struct sta_info *sta, u32 changed) ++-{ ++- struct rate_control_ref *ref = local->rate_ctrl; ++- struct ieee80211_sta *ista = &sta->sta; ++- void *priv_sta = sta->rate_ctrl_priv; ++- struct ieee80211_chanctx_conf *chanctx_conf; ++- ++- if (ref && ref->ops->rate_update) { ++- rcu_read_lock(); ++- ++- chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf); ++- if (WARN_ON(!chanctx_conf)) { ++- rcu_read_unlock(); ++- return; ++- } ++- ++- spin_lock_bh(&sta->rate_ctrl_lock); ++- ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def, ++- ista, priv_sta, changed); ++- spin_unlock_bh(&sta->rate_ctrl_lock); ++- rcu_read_unlock(); ++- } ++- drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); ++-} +++ struct sta_info *sta, u32 changed); ++ ++ static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, ++ struct sta_info *sta, gfp_t gfp) +diff --git a/package/kernel/mac80211/patches/307-ath9k-fix-tracking-of-enabled-AP-beacons.patch b/package/kernel/mac80211/patches/307-ath9k-fix-tracking-of-enabled-AP-beacons.patch +deleted file mode 100644 +index ab9771e..0000000 +--- a/package/kernel/mac80211/patches/307-ath9k-fix-tracking-of-enabled-AP-beacons.patch ++++ /dev/null +@@ -1,76 +0,0 @@ +-From: Felix Fietkau +-Date: Thu, 12 Mar 2015 17:10:50 +0100 +-Subject: [PATCH] ath9k: fix tracking of enabled AP beacons +- +-sc->nbcnvifs tracks assigned beacon slots, not enabled beacons. +-Therefore, it cannot be used to decide if cur_conf->enable_beacon (bool) +-should be updated, or if beacons have been enabled already. +-With the current code (depending on the order of calls), beacons often +-do not get enabled in an AP+STA setup. +-To fix tracking of enabled beacons, convert cur_conf->enable_beacon to a +-bitmask of enabled beacon slots. +- +-Cc: stable@vger.kernel.org +-Signed-off-by: Felix Fietkau +---- +- +---- a/drivers/net/wireless/ath/ath9k/beacon.c +-+++ b/drivers/net/wireless/ath/ath9k/beacon.c +-@@ -219,12 +219,15 @@ 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, +-@@ -521,8 +524,7 @@ static bool ath9k_allow_beacon_config(st +- } +- +- if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { +-- if ((vif->type != NL80211_IFTYPE_AP) || +-- (sc->nbcnvifs > 1)) { +-+ if (vif->type != NL80211_IFTYPE_AP) { +- ath_dbg(common, CONFIG, +- "An AP interface is already present !\n"); +- return false; +-@@ -616,12 +618,14 @@ void ath9k_beacon_config(struct ath_soft +- * enabling/disabling SWBA. +- */ +- if (changed & BSS_CHANGED_BEACON_ENABLED) { +-- if (!bss_conf->enable_beacon && +-- (sc->nbcnvifs <= 1)) { +-- cur_conf->enable_beacon = false; +-- } else if (bss_conf->enable_beacon) { +-- cur_conf->enable_beacon = true; +-- ath9k_cache_beacon_config(sc, ctx, bss_conf); +-+ 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); +- } +- } +- +---- a/drivers/net/wireless/ath/ath9k/common.h +-+++ b/drivers/net/wireless/ath/ath9k/common.h +-@@ -54,7 +54,7 @@ struct ath_beacon_config { +- u16 dtim_period; +- u16 bmiss_timeout; +- u8 dtim_count; +-- bool enable_beacon; +-+ u8 enable_beacon; +- bool ibss_creator; +- u32 nexttbtt; +- u32 intval; +diff --git a/package/kernel/mac80211/patches/307-mac80211-Deinline-drv_sta_state.patch b/package/kernel/mac80211/patches/307-mac80211-Deinline-drv_sta_state.patch +new file mode 100644 +index 0000000..474c409 +--- /dev/null ++++ b/package/kernel/mac80211/patches/307-mac80211-Deinline-drv_sta_state.patch +@@ -0,0 +1,116 @@ ++From: Denys Vlasenko ++Date: Wed, 15 Jul 2015 14:56:05 +0200 ++Subject: [PATCH] mac80211: Deinline drv_sta_state ++ ++With this .config: http://busybox.net/~vda/kernel_config, ++after deinlining the function size is 3132 bytes and there are ++7 callsites. ++ ++Total size reduction: about 20 kbytes. ++ ++Signed-off-by: Denys Vlasenko ++CC: John Linville ++CC: Michal Kazior ++Cc: Johannes Berg ++Cc: linux-wireless@vger.kernel.org ++Cc: netdev@vger.kernel.org ++CC: linux-kernel@vger.kernel.org ++--- ++ create mode 100644 net/mac80211/driver-ops.c ++ ++--- a/net/mac80211/Makefile +++++ b/net/mac80211/Makefile ++@@ -3,6 +3,7 @@ obj-$(CPTCFG_MAC80211) += mac80211.o ++ # mac80211 objects ++ mac80211-y := \ ++ main.o status.o \ +++ driver-ops.o \ ++ sta_info.o \ ++ wep.o \ ++ wpa.o \ ++--- /dev/null +++++ b/net/mac80211/driver-ops.c ++@@ -0,0 +1,41 @@ +++/* +++ * This program is free software; you can redistribute it and/or modify +++ * it under the terms of the GNU General Public License version 2 as +++ * published by the Free Software Foundation. +++ */ +++#include +++#include "ieee80211_i.h" +++#include "trace.h" +++#include "driver-ops.h" +++ +++__must_check +++int drv_sta_state(struct ieee80211_local *local, +++ struct ieee80211_sub_if_data *sdata, +++ struct sta_info *sta, +++ enum ieee80211_sta_state old_state, +++ enum ieee80211_sta_state new_state) +++{ +++ int ret = 0; +++ +++ might_sleep(); +++ +++ sdata = get_bss_sdata(sdata); +++ if (!check_sdata_in_driver(sdata)) +++ return -EIO; +++ +++ trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); +++ if (local->ops->sta_state) { +++ ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta, +++ old_state, new_state); +++ } else if (old_state == IEEE80211_STA_AUTH && +++ new_state == IEEE80211_STA_ASSOC) { +++ ret = drv_sta_add(local, sdata, &sta->sta); +++ if (ret == 0) +++ sta->uploaded = true; +++ } else if (old_state == IEEE80211_STA_ASSOC && +++ new_state == IEEE80211_STA_AUTH) { +++ drv_sta_remove(local, sdata, &sta->sta); +++ } +++ trace_drv_return_int(local, ret); +++ return ret; +++} ++--- a/net/mac80211/driver-ops.h +++++ b/net/mac80211/driver-ops.h ++@@ -573,37 +573,12 @@ static inline void drv_sta_pre_rcu_remov ++ trace_drv_return_void(local); ++ } ++ ++-static inline __must_check +++__must_check ++ int drv_sta_state(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, ++ struct sta_info *sta, ++ enum ieee80211_sta_state old_state, ++- enum ieee80211_sta_state new_state) ++-{ ++- int ret = 0; ++- ++- might_sleep(); ++- ++- sdata = get_bss_sdata(sdata); ++- if (!check_sdata_in_driver(sdata)) ++- return -EIO; ++- ++- trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state); ++- if (local->ops->sta_state) { ++- ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta, ++- old_state, new_state); ++- } else if (old_state == IEEE80211_STA_AUTH && ++- new_state == IEEE80211_STA_ASSOC) { ++- ret = drv_sta_add(local, sdata, &sta->sta); ++- if (ret == 0) ++- sta->uploaded = true; ++- } else if (old_state == IEEE80211_STA_ASSOC && ++- new_state == IEEE80211_STA_AUTH) { ++- drv_sta_remove(local, sdata, &sta->sta); ++- } ++- trace_drv_return_int(local, ret); ++- return ret; ++-} +++ enum ieee80211_sta_state new_state); ++ ++ static inline void drv_sta_rc_update(struct ieee80211_local *local, ++ struct ieee80211_sub_if_data *sdata, +diff --git a/package/kernel/mac80211/patches/308-ath9k-Fix-NF-CCA-limits-for-AR9287-and-AR9227.patch b/package/kernel/mac80211/patches/308-ath9k-Fix-NF-CCA-limits-for-AR9287-and-AR9227.patch +new file mode 100644 +index 0000000..1a3a9d4 +--- /dev/null ++++ b/package/kernel/mac80211/patches/308-ath9k-Fix-NF-CCA-limits-for-AR9287-and-AR9227.patch +@@ -0,0 +1,30 @@ ++From: Martin Blumenstingl ++Date: Wed, 22 Jul 2015 10:42:43 +0200 ++Subject: [PATCH] ath9k: Fix NF CCA limits for AR9287 and AR9227 ++ ++The FreeBSD driver [0] uses the same 2G values as for the AR9280 chips. ++Using the same values in ath9k results in much better throughput for me. ++ ++Before this patch I had a huge amount of packet loss (sometimes up to ++40%) and the max transfer speed was somewhere around 5Mbit/s. With this ++patch applied I have zero packet loss and ten times the throughput. ++My device uses a AR9227 which is the PCI variant of the AR9287. ++ ++[0] http://bxr.su/FreeBSD/sys/dev/ath/ath_hal/ar9002/ar9287.h ++ ++Signed-off-by: Martin Blumenstingl ++--- ++ ++--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h ++@@ -610,8 +610,8 @@ ++ #define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ -127 ++ #define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ -116 ++ ++-#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -120 +++#define AR_PHY_CCA_NOM_VAL_9287_2GHZ -112 ++ #define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ -127 ++-#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -110 +++#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ -97 ++ ++ #endif +diff --git a/package/kernel/mac80211/patches/308-mac80211-minstrel_ht-fix-rounding-issue-in-MCS-durat.patch b/package/kernel/mac80211/patches/308-mac80211-minstrel_ht-fix-rounding-issue-in-MCS-durat.patch +deleted file mode 100644 +index d132636..0000000 +--- a/package/kernel/mac80211/patches/308-mac80211-minstrel_ht-fix-rounding-issue-in-MCS-durat.patch ++++ /dev/null +@@ -1,43 +0,0 @@ +-From: Felix Fietkau +-Date: Fri, 13 Mar 2015 10:49:40 +0100 +-Subject: [PATCH] mac80211: minstrel_ht: fix rounding issue in MCS duration +- calculation +- +-On very high MCS bitrates, the calculated duration of rates that are +-next to each other can be very imprecise, due to the small packet size +-used as reference (1200 bytes). +-This is most visible in VHT80 nss=2 MCS8/9, for which minstrel shows the +-same throughput when the probability is also the same. This leads to a +-bad rate selection for such rates. +- +-Fix this issue by introducing an average A-MPDU size factor into the +-calculation. +- +-Signed-off-by: Felix Fietkau +---- +- +---- a/net/mac80211/rc80211_minstrel_ht.c +-+++ b/net/mac80211/rc80211_minstrel_ht.c +-@@ -17,10 +17,11 @@ +- #include "rc80211_minstrel.h" +- #include "rc80211_minstrel_ht.h" +- +-+#define AVG_AMPDU_SIZE 16 +- #define AVG_PKT_SIZE 1200 +- +- /* Number of bits for an average sized packet */ +--#define MCS_NBITS (AVG_PKT_SIZE << 3) +-+#define MCS_NBITS ((AVG_PKT_SIZE * AVG_AMPDU_SIZE) << 3) +- +- /* Number of symbols for a packet with (bps) bits per symbol */ +- #define MCS_NSYMS(bps) DIV_ROUND_UP(MCS_NBITS, (bps)) +-@@ -33,7 +34,8 @@ +- ) +- +- /* Transmit duration for the raw data part of an average sized packet */ +--#define MCS_DURATION(streams, sgi, bps) MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps))) +-+#define MCS_DURATION(streams, sgi, bps) \ +-+ (MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps))) / AVG_AMPDU_SIZE) +- +- #define BW_20 0 +- #define BW_40 1 +diff --git a/package/kernel/mac80211/patches/309-ath9k-disable-TPC-support-again-for-now.patch b/package/kernel/mac80211/patches/309-ath9k-disable-TPC-support-again-for-now.patch +deleted file mode 100644 +index 945fbce..0000000 +--- a/package/kernel/mac80211/patches/309-ath9k-disable-TPC-support-again-for-now.patch ++++ /dev/null +@@ -1,22 +0,0 @@ +-From: Felix Fietkau +-Date: Sun, 15 Mar 2015 08:02:37 +0100 +-Subject: [PATCH] ath9k: disable TPC support again (for now) +- +-TPC support has been observed to cause some tx power fluctuations on +-some devices with at least AR934x and AR938x chips. +-Disable it for now until the bugs have been found and fixed +- +-Signed-off-by: Felix Fietkau +---- +- +---- a/drivers/net/wireless/ath/ath9k/hw.c +-+++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -424,7 +424,7 @@ static void ath9k_hw_init_defaults(struc +- ah->power_mode = ATH9K_PM_UNDEFINED; +- ah->htc_reset_init = true; +- +-- ah->tpc_enabled = true; +-+ ah->tpc_enabled = false; +- +- ah->ani_function = ATH9K_ANI_ALL; +- if (!AR_SREV_9300_20_OR_LATER(ah)) +diff --git a/package/kernel/mac80211/patches/309-mac80211-make-local-tx_headroom-a-multiple-of-4.patch b/package/kernel/mac80211/patches/309-mac80211-make-local-tx_headroom-a-multiple-of-4.patch +new file mode 100644 +index 0000000..e8e9617 +--- /dev/null ++++ b/package/kernel/mac80211/patches/309-mac80211-make-local-tx_headroom-a-multiple-of-4.patch +@@ -0,0 +1,20 @@ ++From: Felix Fietkau ++Date: Thu, 30 Jul 2015 14:12:25 +0200 ++Subject: [PATCH] mac80211: make local->tx_headroom a multiple of 4 ++ ++This ensures that mac80211 generated management frames and beacons are ++aligned before being passed to the driver ++ ++Signed-off-by: Felix Fietkau ++--- ++ ++--- a/net/mac80211/main.c +++++ b/net/mac80211/main.c ++@@ -1031,6 +1031,7 @@ int ieee80211_register_hw(struct ieee802 ++ */ ++ local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, ++ IEEE80211_TX_STATUS_HEADROOM); +++ local->tx_headroom = ALIGN(local->tx_headroom, 4); ++ ++ debugfs_hw_add(local); ++ +diff --git a/package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch b/package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch +deleted file mode 100644 +index bd3050e..0000000 +--- a/package/kernel/mac80211/patches/310-mac80211-don-t-look-up-stations-for-multicast-addres.patch ++++ /dev/null +@@ -1,21 +0,0 @@ +-From: Johannes Berg +-Date: Tue, 24 Feb 2015 00:28:18 +0100 +-Subject: [PATCH] mac80211: don't look up stations for multicast addresses +- +-Since multicast addresses don't exist as stations, don't attempt +-to look them up in the hashtable on TX. +- +-Signed-off-by: Johannes Berg +---- +- +---- a/net/mac80211/tx.c +-+++ b/net/mac80211/tx.c +-@@ -1161,7 +1161,7 @@ ieee80211_tx_prepare(struct ieee80211_su +- tx->sdata->control_port_protocol == tx->skb->protocol) { +- tx->sta = sta_info_get_bss(sdata, hdr->addr1); +- } +-- if (!tx->sta) +-+ if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) +- tx->sta = sta_info_get(sdata, hdr->addr1); +- +- if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && +diff --git a/package/kernel/mac80211/patches/310-mac80211-fix-invalid-read-in-minstrel_sort_best_tp_r.patch b/package/kernel/mac80211/patches/310-mac80211-fix-invalid-read-in-minstrel_sort_best_tp_r.patch +new file mode 100644 +index 0000000..51a315c +--- /dev/null ++++ b/package/kernel/mac80211/patches/310-mac80211-fix-invalid-read-in-minstrel_sort_best_tp_r.patch +@@ -0,0 +1,34 @@ ++From: Adrien Schildknecht ++Date: Tue, 28 Jul 2015 10:30:16 +0200 ++Subject: [PATCH] mac80211: fix invalid read in minstrel_sort_best_tp_rates() ++ ++At the last iteration of the loop, j may equal zero and thus ++tp_list[j - 1] causes an invalid read. ++Changed the logic of the loop so that j - 1 is always >= 0. ++ ++Signed-off-by: Adrien Schildknecht ++--- ++ ++--- a/net/mac80211/rc80211_minstrel.c +++++ b/net/mac80211/rc80211_minstrel.c ++@@ -92,14 +92,15 @@ int minstrel_get_tp_avg(struct minstrel_ ++ static inline void ++ minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) ++ { ++- int j = MAX_THR_RATES; ++- struct minstrel_rate_stats *tmp_mrs = &mi->r[j - 1].stats; +++ int j; +++ struct minstrel_rate_stats *tmp_mrs; ++ struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats; ++ ++- while (j > 0 && (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) > ++- minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))) { ++- j--; +++ for (j = MAX_THR_RATES; j > 0; --j) { ++ tmp_mrs = &mi->r[tp_list[j - 1]].stats; +++ if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <= +++ minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma)) +++ break; ++ } ++ ++ if (j < MAX_THR_RATES - 1) +diff --git a/package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch b/package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch +new file mode 100644 +index 0000000..e44f121 +--- /dev/null ++++ b/package/kernel/mac80211/patches/311-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch +@@ -0,0 +1,45 @@ ++From: Vineet Gupta ++Date: Thu, 9 Jul 2015 13:43:18 +0530 ++Subject: [PATCH] brcmfmac: dhd_sdio.c: use existing atomic_or primitive ++ ++There's already a generic implementation so use that instead. ++ ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++@@ -2564,15 +2564,6 @@ static inline void brcmf_sdio_clrintr(st ++ } ++ } ++ ++-static void atomic_orr(int val, atomic_t *v) ++-{ ++- int old_val; ++- ++- old_val = atomic_read(v); ++- while (atomic_cmpxchg(v, old_val, val | old_val) != old_val) ++- old_val = atomic_read(v); ++-} ++- ++ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) ++ { ++ struct brcmf_core *buscore; ++@@ -2595,7 +2586,7 @@ static int brcmf_sdio_intr_rstatus(struc ++ if (val) { ++ brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret); ++ bus->sdcnt.f1regdata++; ++- atomic_orr(val, &bus->intstatus); +++ atomic_or(val, &bus->intstatus); ++ } ++ ++ return ret; ++@@ -2712,7 +2703,7 @@ static void brcmf_sdio_dpc(struct brcmf_ ++ ++ /* Keep still-pending events for next scheduling */ ++ if (intstatus) ++- atomic_orr(intstatus, &bus->intstatus); +++ atomic_or(intstatus, &bus->intstatus); ++ ++ brcmf_sdio_clrintr(bus); ++ +diff --git a/package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch b/package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch +deleted file mode 100644 +index b2475b9..0000000 +--- a/package/kernel/mac80211/patches/311-mac80211-remove-drop_unencrypted-code.patch ++++ /dev/null +@@ -1,130 +0,0 @@ +-From: Johannes Berg +-Date: Fri, 20 Mar 2015 11:41:58 +0100 +-Subject: [PATCH] mac80211: remove drop_unencrypted code +- +-This mechanism was historic, and only ever used by IBSS, which +-also doesn't need to have it as it properly manages station's +-802.1X PAE state (or, with WEP, always has a key.) +- +-Remove the mechanism to clean up the code. +- +-Signed-off-by: Johannes Berg +---- +- +---- a/net/mac80211/debugfs.c +-+++ b/net/mac80211/debugfs.c +-@@ -274,8 +274,6 @@ void debugfs_hw_add(struct ieee80211_loc +- #ifdef CPTCFG_MAC80211_DEBUG_COUNTERS +- DEBUGFS_STATS_ADD(tx_handlers_drop, local->tx_handlers_drop); +- DEBUGFS_STATS_ADD(tx_handlers_queued, local->tx_handlers_queued); +-- DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted, +-- local->tx_handlers_drop_unencrypted); +- DEBUGFS_STATS_ADD(tx_handlers_drop_fragment, +- local->tx_handlers_drop_fragment); +- DEBUGFS_STATS_ADD(tx_handlers_drop_wep, +---- a/net/mac80211/debugfs_netdev.c +-+++ b/net/mac80211/debugfs_netdev.c +-@@ -177,7 +177,6 @@ static ssize_t ieee80211_if_write_##name +- IEEE80211_IF_FILE_R(name) +- +- /* common attributes */ +--IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); +- IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ], +- HEX); +- IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], +-@@ -562,7 +561,6 @@ IEEE80211_IF_FILE(dot11MeshAwakeWindowDu +- +- static void add_common_files(struct ieee80211_sub_if_data *sdata) +- { +-- DEBUGFS_ADD(drop_unencrypted); +- DEBUGFS_ADD(rc_rateidx_mask_2ghz); +- DEBUGFS_ADD(rc_rateidx_mask_5ghz); +- DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); +---- a/net/mac80211/ibss.c +-+++ b/net/mac80211/ibss.c +-@@ -249,8 +249,6 @@ static void __ieee80211_sta_join_ibss(st +- if (presp) +- kfree_rcu(presp, rcu_head); +- +-- sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; +-- +- /* make a copy of the chandef, it could be modified below. */ +- chandef = *req_chandef; +- chan = chandef.chan; +-@@ -1289,8 +1287,6 @@ static void ieee80211_sta_create_ibss(st +- +- if (ifibss->privacy) +- capability |= WLAN_CAPABILITY_PRIVACY; +-- else +-- sdata->drop_unencrypted = 0; +- +- __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, +- &ifibss->chandef, ifibss->basic_rates, +---- a/net/mac80211/ieee80211_i.h +-+++ b/net/mac80211/ieee80211_i.h +-@@ -842,8 +842,6 @@ struct ieee80211_sub_if_data { +- +- unsigned long state; +- +-- int drop_unencrypted; +-- +- char name[IFNAMSIZ]; +- +- /* Fragment table for host-based reassembly */ +-@@ -1289,7 +1287,6 @@ struct ieee80211_local { +- /* TX/RX handler statistics */ +- unsigned int tx_handlers_drop; +- unsigned int tx_handlers_queued; +-- unsigned int tx_handlers_drop_unencrypted; +- unsigned int tx_handlers_drop_fragment; +- unsigned int tx_handlers_drop_wep; +- unsigned int tx_handlers_drop_not_assoc; +---- a/net/mac80211/iface.c +-+++ b/net/mac80211/iface.c +-@@ -1535,7 +1535,6 @@ int ieee80211_if_change_type(struct ieee +- } +- +- /* reset some values that shouldn't be kept across type changes */ +-- sdata->drop_unencrypted = 0; +- if (type == NL80211_IFTYPE_STATION) +- sdata->u.mgd.use_4addr = false; +- +---- a/net/mac80211/rx.c +-+++ b/net/mac80211/rx.c +-@@ -1897,8 +1897,7 @@ static int ieee80211_drop_unencrypted(st +- /* Drop unencrypted frames if key is set. */ +- if (unlikely(!ieee80211_has_protected(fc) && +- !ieee80211_is_nullfunc(fc) && +-- ieee80211_is_data(fc) && +-- (rx->key || rx->sdata->drop_unencrypted))) +-+ ieee80211_is_data(fc) && rx->key)) +- return -EACCES; +- +- return 0; +---- a/net/mac80211/tx.c +-+++ b/net/mac80211/tx.c +-@@ -594,23 +594,8 @@ ieee80211_tx_h_select_key(struct ieee802 +- else if (!is_multicast_ether_addr(hdr->addr1) && +- (key = rcu_dereference(tx->sdata->default_unicast_key))) +- tx->key = key; +-- else if (info->flags & IEEE80211_TX_CTL_INJECTED) +-+ else +- tx->key = NULL; +-- else if (!tx->sdata->drop_unencrypted) +-- tx->key = NULL; +-- else if (tx->skb->protocol == tx->sdata->control_port_protocol) +-- tx->key = NULL; +-- else if (ieee80211_is_robust_mgmt_frame(tx->skb) && +-- !(ieee80211_is_action(hdr->frame_control) && +-- tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) +-- tx->key = NULL; +-- else if (ieee80211_is_mgmt(hdr->frame_control) && +-- !ieee80211_is_robust_mgmt_frame(tx->skb)) +-- tx->key = NULL; +-- else { +-- I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); +-- return TX_DROP; +-- } +- +- if (tx->key) { +- bool skip_hw = false; +diff --git a/package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch b/package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch +new file mode 100644 +index 0000000..bb27115 +--- /dev/null ++++ b/package/kernel/mac80211/patches/312-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch +@@ -0,0 +1,46 @@ ++From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= ++Date: Thu, 20 Aug 2015 00:16:42 +0200 ++Subject: [PATCH] brcmfmac: check all combinations when setting wiphy's ++ addresses ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++Broadcom is working on better reflection of interface combinations. With ++upcoming patches we may have 1st combination supporting less interfaces ++than others. ++To don't run out of addresses check all combinations to find the one ++with the greatest max_interfaces value. ++ ++Signed-off-by: Rafał Miłecki ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++@@ -5786,7 +5786,9 @@ static void brcmf_wiphy_wowl_params(stru ++ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) ++ { ++ struct brcmf_pub *drvr = ifp->drvr; +++ const struct ieee80211_iface_combination *combo; ++ struct ieee80211_supported_band *band; +++ u16 max_interfaces = 0; ++ __le32 bandlist[3]; ++ u32 n_bands; ++ int err, i; ++@@ -5799,8 +5801,13 @@ static int brcmf_setup_wiphy(struct wiph ++ if (err) ++ return err; ++ ++- for (i = 0; i < wiphy->iface_combinations->max_interfaces && ++- i < ARRAY_SIZE(drvr->addresses); i++) { +++ for (i = 0, combo = wiphy->iface_combinations; +++ i < wiphy->n_iface_combinations; i++, combo++) { +++ max_interfaces = max(max_interfaces, combo->max_interfaces); +++ } +++ +++ for (i = 0; i < max_interfaces && i < ARRAY_SIZE(drvr->addresses); +++ i++) { ++ u8 *addr = drvr->addresses[i].addr; ++ ++ memcpy(addr, drvr->mac, ETH_ALEN); +diff --git a/package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch b/package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch +deleted file mode 100644 +index 02a7fab..0000000 +--- a/package/kernel/mac80211/patches/312-mac80211-don-t-look-up-destination-station-twice.patch ++++ /dev/null +@@ -1,71 +0,0 @@ +-From: Johannes Berg +-Date: Fri, 20 Mar 2015 16:24:21 +0100 +-Subject: [PATCH] mac80211: don't look up destination station twice +- +-There's no need to look up the destination station twice while +-building the 802.11 header for a given frame if the frame will +-actually be transmitted to the station we initially looked up. +- +-This happens for 4-addr VLAN interfaces and TDLS connections, which +-both directly send the frame to the station they looked up, though +-in the case of TDLS some station conditions need to be checked. +- +-To avoid that, add a variable indicating that we've looked up the +-station that the frame is going to be transmitted to, and avoid the +-lookup/flag checking if it already has been done. +- +-In the TDLS case, also move the authorized/wme_sta flag assignment +-to the correct place, i.e. only when that station is really used. +-Before this change, the new lookup should always have succeeded so +-that the potentially erroneous data would be overwritten. +- +-Signed-off-by: Johannes Berg +---- +- +---- a/net/mac80211/tx.c +-+++ b/net/mac80211/tx.c +-@@ -1894,6 +1894,7 @@ static struct sk_buff *ieee80211_build_h +- bool wme_sta = false, authorized = false, tdls_auth = false; +- bool tdls_peer = false, tdls_setup_frame = false; +- bool multicast; +-+ bool have_station = false; +- u16 info_id = 0; +- struct ieee80211_chanctx_conf *chanctx_conf; +- struct ieee80211_sub_if_data *ap_sdata; +-@@ -1918,6 +1919,7 @@ static struct sk_buff *ieee80211_build_h +- hdrlen = 30; +- authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); +- wme_sta = sta->sta.wme; +-+ have_station = true; +- } +- ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, +- u.ap); +-@@ -2034,9 +2036,6 @@ static struct sk_buff *ieee80211_build_h +- if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { +- sta = sta_info_get(sdata, skb->data); +- if (sta) { +-- authorized = test_sta_flag(sta, +-- WLAN_STA_AUTHORIZED); +-- wme_sta = sta->sta.wme; +- tdls_peer = test_sta_flag(sta, +- WLAN_STA_TDLS_PEER); +- tdls_auth = test_sta_flag(sta, +-@@ -2068,6 +2067,9 @@ static struct sk_buff *ieee80211_build_h +- memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); +- memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN); +- hdrlen = 24; +-+ have_station = true; +-+ authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); +-+ wme_sta = sta->sta.wme; +- } else if (sdata->u.mgd.use_4addr && +- cpu_to_be16(ethertype) != sdata->control_port_protocol) { +- fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | +-@@ -2130,7 +2132,7 @@ static struct sk_buff *ieee80211_build_h +- * in AP mode) +- */ +- multicast = is_multicast_ether_addr(hdr.addr1); +-- if (!multicast) { +-+ if (!multicast && !have_station) { +- sta = sta_info_get(sdata, hdr.addr1); +- if (sta) { +- authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); +diff --git a/package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch b/package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch +new file mode 100644 +index 0000000..baee295 +--- /dev/null ++++ b/package/kernel/mac80211/patches/313-brcmfmac-correct-interface-combination-info.patch +@@ -0,0 +1,204 @@ ++From: Arend van Spriel ++Date: Thu, 20 Aug 2015 22:06:03 +0200 ++Subject: [PATCH] brcmfmac: correct interface combination info ++ ++The interface combination provided by brcmfmac did not truly reflect ++the combinations supported by driver and/or firmware. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Reviewed-by: Pontus Fuchs ++Signed-off-by: Arend van Spriel ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++@@ -5695,63 +5695,132 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = ++ } ++ }; ++ +++/** +++ * brcmf_setup_ifmodes() - determine interface modes and combinations. +++ * +++ * @wiphy: wiphy object. +++ * @ifp: interface object needed for feat module api. +++ * +++ * The interface modes and combinations are determined dynamically here +++ * based on firmware functionality. +++ * +++ * no p2p and no mbss: +++ * +++ * #STA <= 1, #AP <= 1, channels = 1, 2 total +++ * +++ * no p2p and mbss: +++ * +++ * #STA <= 1, #AP <= 1, channels = 1, 2 total +++ * #AP <= 4, matching BI, channels = 1, 4 total +++ * +++ * p2p, no mchan, and mbss: +++ * +++ * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total +++ * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total +++ * #AP <= 4, matching BI, channels = 1, 4 total +++ * +++ * p2p, mchan, and mbss: +++ * +++ * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total +++ * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total +++ * #AP <= 4, matching BI, channels = 1, 4 total +++ */ ++ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) ++ { ++ struct ieee80211_iface_combination *combo = NULL; ++- struct ieee80211_iface_limit *limits = NULL; ++- int i = 0, max_iface_cnt; +++ struct ieee80211_iface_limit *c0_limits = NULL; +++ struct ieee80211_iface_limit *p2p_limits = NULL; +++ struct ieee80211_iface_limit *mbss_limits = NULL; +++ bool mbss, p2p; +++ int i, c, n_combos; ++ ++- combo = kzalloc(sizeof(*combo), GFP_KERNEL); +++ mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); +++ p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); +++ +++ n_combos = 1 + !!p2p + !!mbss; +++ combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL); ++ if (!combo) ++ goto err; ++ ++- limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL); ++- if (!limits) +++ 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); ++ ++- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) ++- combo->num_different_channels = 2; ++- else ++- combo->num_different_channels = 1; ++- ++- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) { ++- limits[i].max = 1; ++- limits[i++].types = BIT(NL80211_IFTYPE_STATION); ++- limits[i].max = 4; ++- limits[i++].types = BIT(NL80211_IFTYPE_AP); ++- max_iface_cnt = 5; ++- } else { ++- limits[i].max = 2; ++- limits[i++].types = BIT(NL80211_IFTYPE_STATION) | ++- BIT(NL80211_IFTYPE_AP); ++- max_iface_cnt = 2; ++- } ++- ++- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) { +++ c = 0; +++ i = 0; +++ combo[c].num_different_channels = 1; +++ c0_limits[i].max = 1; +++ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); +++ if (p2p) { +++ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) +++ combo[c].num_different_channels = 2; ++ wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | ++ BIT(NL80211_IFTYPE_P2P_GO) | ++ BIT(NL80211_IFTYPE_P2P_DEVICE); ++- limits[i].max = 1; ++- limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | ++- BIT(NL80211_IFTYPE_P2P_GO); ++- limits[i].max = 1; ++- limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); ++- max_iface_cnt += 2; ++- } ++- combo->max_interfaces = max_iface_cnt; ++- combo->limits = limits; ++- combo->n_limits = i; +++ c0_limits[i].max = 1; +++ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); +++ c0_limits[i].max = 1; +++ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | +++ BIT(NL80211_IFTYPE_P2P_GO); +++ } else { +++ c0_limits[i].max = 1; +++ c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); +++ } +++ combo[c].max_interfaces = i; +++ combo[c].n_limits = i; +++ combo[c].limits = c0_limits; +++ +++ if (p2p) { +++ c++; +++ i = 0; +++ combo[c].num_different_channels = 1; +++ p2p_limits[i].max = 1; +++ p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION); +++ p2p_limits[i].max = 1; +++ p2p_limits[i++].types = BIT(NL80211_IFTYPE_AP); +++ p2p_limits[i].max = 1; +++ 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].max_interfaces = i; +++ combo[c].n_limits = i; +++ combo[c].limits = p2p_limits; +++ } ++ +++ if (mbss) { +++ c++; +++ 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].limits = mbss_limits; +++ } +++ wiphy->n_iface_combinations = n_combos; ++ wiphy->iface_combinations = combo; ++- wiphy->n_iface_combinations = 1; ++ return 0; ++ ++ err: ++- kfree(limits); +++ kfree(c0_limits); +++ kfree(p2p_limits); +++ kfree(mbss_limits); ++ kfree(combo); ++ return -ENOMEM; ++ } ++@@ -6080,11 +6149,15 @@ static void brcmf_cfg80211_reg_notifier( ++ ++ static void brcmf_free_wiphy(struct wiphy *wiphy) ++ { +++ int i; +++ ++ if (!wiphy) ++ return; ++ ++- if (wiphy->iface_combinations) ++- kfree(wiphy->iface_combinations->limits); +++ if (wiphy->iface_combinations) { +++ for (i = 0; i < wiphy->n_iface_combinations; i++) +++ kfree(wiphy->iface_combinations[i].limits); +++ } ++ kfree(wiphy->iface_combinations); ++ if (wiphy->bands[IEEE80211_BAND_2GHZ]) { ++ kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); +diff --git a/package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch b/package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch +deleted file mode 100644 +index 4125351..0000000 +--- a/package/kernel/mac80211/patches/313-mac80211-drop-4-addr-VLAN-frames-earlier-if-not-conn.patch ++++ /dev/null +@@ -1,27 +0,0 @@ +-From: Johannes Berg +-Date: Fri, 20 Mar 2015 16:24:22 +0100 +-Subject: [PATCH] mac80211: drop 4-addr VLAN frames earlier if not +- connected +- +-If there's no station on the 4-addr VLAN interface, then frames +-cannot be transmitted. Drop such frames earlier, before setting +-up all the information for them. +- +-We should keep the old check though since that code might be used +-for other internally-generated frames. +- +-Signed-off-by: Johannes Berg +---- +- +---- a/net/mac80211/tx.c +-+++ b/net/mac80211/tx.c +-@@ -1920,6 +1920,9 @@ static struct sk_buff *ieee80211_build_h +- authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); +- wme_sta = sta->sta.wme; +- have_station = true; +-+ } else if (sdata->wdev.use_4addr) { +-+ ret = -ENOLINK; +-+ goto free; +- } +- ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, +- u.ap); +diff --git a/package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch b/package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch +new file mode 100644 +index 0000000..9768ef2 +--- /dev/null ++++ b/package/kernel/mac80211/patches/314-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch +@@ -0,0 +1,87 @@ ++From: Franky Lin ++Date: Thu, 20 Aug 2015 22:06:04 +0200 ++Subject: [PATCH] brcmfmac: add debugfs entry for msgbuf statistics ++ ++Expose ring buffer read/write pointers and other useful statistics ++through debugfs. ++ ++Reviewed-by: Arend Van Spriel ++Reviewed-by: Hante Meuleman ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Franky Lin ++Signed-off-by: Arend van Spriel ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c ++@@ -1360,6 +1360,60 @@ void brcmf_msgbuf_delete_flowring(struct ++ } ++ } ++ +++#ifdef DEBUG +++static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data) +++{ +++ struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); +++ struct brcmf_pub *drvr = bus_if->drvr; +++ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; +++ struct brcmf_commonring *commonring; +++ u16 i; +++ struct brcmf_flowring_ring *ring; +++ struct brcmf_flowring_hash *hash; +++ +++ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT]; +++ seq_printf(seq, "h2d_ctl_submit: rp %4u, wp %4u, depth %4u\n", +++ commonring->r_ptr, commonring->w_ptr, commonring->depth); +++ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT]; +++ seq_printf(seq, "h2d_rx_submit: rp %4u, wp %4u, depth %4u\n", +++ commonring->r_ptr, commonring->w_ptr, commonring->depth); +++ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE]; +++ seq_printf(seq, "d2h_ctl_cmplt: rp %4u, wp %4u, depth %4u\n", +++ commonring->r_ptr, commonring->w_ptr, commonring->depth); +++ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE]; +++ seq_printf(seq, "d2h_tx_cmplt: rp %4u, wp %4u, depth %4u\n", +++ commonring->r_ptr, commonring->w_ptr, commonring->depth); +++ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE]; +++ seq_printf(seq, "d2h_rx_cmplt: rp %4u, wp %4u, depth %4u\n", +++ commonring->r_ptr, commonring->w_ptr, commonring->depth); +++ +++ seq_printf(seq, "\nh2d_flowrings: depth %u\n", +++ BRCMF_H2D_TXFLOWRING_MAX_ITEM); +++ seq_puts(seq, "Active flowrings:\n"); +++ hash = msgbuf->flow->hash; +++ for (i = 0; i < msgbuf->flow->nrofrings; i++) { +++ if (!msgbuf->flow->rings[i]) +++ continue; +++ ring = msgbuf->flow->rings[i]; +++ if (ring->status != RING_OPEN) +++ continue; +++ commonring = msgbuf->flowrings[i]; +++ hash = &msgbuf->flow->hash[ring->hash_id]; +++ seq_printf(seq, "id %3u: rp %4u, wp %4u, qlen %4u, blocked %u\n" +++ " ifidx %u, fifo %u, da %pM\n", +++ i, commonring->r_ptr, commonring->w_ptr, +++ skb_queue_len(&ring->skblist), ring->blocked, +++ hash->ifidx, hash->fifo, hash->mac); +++ } +++ +++ return 0; +++} +++#else +++static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data) +++{ +++ return 0; +++} +++#endif ++ ++ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) ++ { ++@@ -1460,6 +1514,8 @@ int brcmf_proto_msgbuf_attach(struct brc ++ spin_lock_init(&msgbuf->flowring_work_lock); ++ INIT_LIST_HEAD(&msgbuf->work_queue); ++ +++ brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read); +++ ++ return 0; ++ ++ fail: +diff --git a/package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch b/package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch +deleted file mode 100644 +index 9105a64..0000000 +--- a/package/kernel/mac80211/patches/314-mac80211-mesh-avoid-pointless-station-lookup.patch ++++ /dev/null +@@ -1,33 +0,0 @@ +-From: Johannes Berg +-Date: Fri, 20 Mar 2015 16:24:23 +0100 +-Subject: [PATCH] mac80211: mesh: avoid pointless station lookup +- +-In ieee80211_build_hdr(), the station is looked up to build the +-header correctly (QoS field) and to check for authorization. For +-mesh, authorization isn't checked here, and QoS capability is +-mandatory, so the station lookup can be avoided. +- +-Signed-off-by: Johannes Berg +---- +- +---- a/net/mac80211/tx.c +-+++ b/net/mac80211/tx.c +-@@ -2130,12 +2130,14 @@ static struct sk_buff *ieee80211_build_h +- } +- +- /* +-- * There's no need to try to look up the destination +-- * if it is a multicast address (which can only happen +-- * in AP mode) +-+ * There's no need to try to look up the destination station +-+ * if it is a multicast address. In mesh, there's no need to +-+ * look up the station at all as it always must be QoS capable +-+ * and mesh mode checks authorization later. +- */ +- multicast = is_multicast_ether_addr(hdr.addr1); +-- if (!multicast && !have_station) { +-+ if (!multicast && !have_station && +-+ !ieee80211_vif_is_mesh(&sdata->vif)) { +- sta = sta_info_get(sdata, hdr.addr1); +- if (sta) { +- authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); +diff --git a/package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch b/package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch +new file mode 100644 +index 0000000..281f02b +--- /dev/null ++++ b/package/kernel/mac80211/patches/315-brcmfmac-make-use-of-cfg80211_check_combinations.patch +@@ -0,0 +1,83 @@ ++From: Arend van Spriel ++Date: Thu, 20 Aug 2015 22:06:05 +0200 ++Subject: [PATCH] brcmfmac: make use of cfg80211_check_combinations() ++ ++Use cfg80211_check_combinations() so we can bail out early when an ++interface add or change results in an invalid combination. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++@@ -469,6 +469,36 @@ brcmf_find_wpsie(const u8 *parse, u32 le ++ return NULL; ++ } ++ +++static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg, +++ struct brcmf_cfg80211_vif *vif, +++ enum nl80211_iftype new_type) +++{ +++ int iftype_num[NUM_NL80211_IFTYPES]; +++ struct brcmf_cfg80211_vif *pos; +++ +++ memset(&iftype_num[0], 0, sizeof(iftype_num)); +++ list_for_each_entry(pos, &cfg->vif_list, list) +++ if (pos == vif) +++ iftype_num[new_type]++; +++ else +++ iftype_num[pos->wdev.iftype]++; +++ +++ return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); +++} +++ +++static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg, +++ enum nl80211_iftype new_type) +++{ +++ int iftype_num[NUM_NL80211_IFTYPES]; +++ struct brcmf_cfg80211_vif *pos; +++ +++ memset(&iftype_num[0], 0, sizeof(iftype_num)); +++ list_for_each_entry(pos, &cfg->vif_list, list) +++ iftype_num[pos->wdev.iftype]++; +++ +++ iftype_num[new_type]++; +++ return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); +++} ++ ++ static void convert_key_from_CPU(struct brcmf_wsec_key *key, ++ struct brcmf_wsec_key_le *key_le) ++@@ -663,8 +693,14 @@ static struct wireless_dev *brcmf_cfg802 ++ struct vif_params *params) ++ { ++ struct wireless_dev *wdev; +++ int err; ++ ++ brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); +++ err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); +++ if (err) { +++ brcmf_err("iface validation failed: err=%d\n", err); +++ return ERR_PTR(err); +++ } ++ switch (type) { ++ case NL80211_IFTYPE_ADHOC: ++ case NL80211_IFTYPE_STATION: ++@@ -823,8 +859,12 @@ brcmf_cfg80211_change_iface(struct wiphy ++ s32 ap = 0; ++ s32 err = 0; ++ ++- brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type); ++- +++ brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type); +++ err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type); +++ if (err) { +++ brcmf_err("iface validation failed: err=%d\n", err); +++ return err; +++ } ++ switch (type) { ++ case NL80211_IFTYPE_MONITOR: ++ case NL80211_IFTYPE_WDS: +diff --git a/package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch b/package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch +deleted file mode 100644 +index d143025..0000000 +--- a/package/kernel/mac80211/patches/315-mac80211-avoid-duplicate-TX-path-station-lookup.patch ++++ /dev/null +@@ -1,267 +0,0 @@ +-From: Johannes Berg +-Date: Fri, 20 Mar 2015 14:18:27 +0100 +-Subject: [PATCH] mac80211: avoid duplicate TX path station lookup +- +-Instead of looking up the destination station twice in the TX path +-(first to build the header, and then for control processing), save +-it when building the header and use it later in the TX path. +- +-To avoid having to look up the station in the many callers, allow +-those to pass %NULL which keeps the existing lookup. +- +-Signed-off-by: Johannes Berg +---- +- +---- a/net/mac80211/cfg.c +-+++ b/net/mac80211/cfg.c +-@@ -3565,7 +3565,7 @@ static int ieee80211_probe_client(struct +- nullfunc->qos_ctrl = cpu_to_le16(7); +- +- local_bh_disable(); +-- ieee80211_xmit(sdata, skb); +-+ ieee80211_xmit(sdata, sta, skb); +- local_bh_enable(); +- rcu_read_unlock(); +- +---- a/net/mac80211/ieee80211_i.h +-+++ b/net/mac80211/ieee80211_i.h +-@@ -1775,7 +1775,8 @@ void mac80211_ev_michael_mic_failure(str +- gfp_t gfp); +- void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, +- bool bss_notify); +--void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); +-+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, +-+ struct sta_info *sta, struct sk_buff *skb); +- +- void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, +- struct sk_buff *skb, int tid, +---- a/net/mac80211/sta_info.c +-+++ b/net/mac80211/sta_info.c +-@@ -1279,7 +1279,7 @@ static void ieee80211_send_null_response +- } +- +- info->band = chanctx_conf->def.chan->band; +-- ieee80211_xmit(sdata, skb); +-+ ieee80211_xmit(sdata, sta, skb); +- rcu_read_unlock(); +- } +- +---- a/net/mac80211/tx.c +-+++ b/net/mac80211/tx.c +-@@ -1110,11 +1110,13 @@ static bool ieee80211_tx_prep_agg(struct +- +- /* +- * initialises @tx +-+ * pass %NULL for the station if unknown, a valid pointer if known +-+ * or an ERR_PTR() if the station is known not to exist +- */ +- static ieee80211_tx_result +- ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, +- struct ieee80211_tx_data *tx, +-- struct sk_buff *skb) +-+ struct sta_info *sta, struct sk_buff *skb) +- { +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_hdr *hdr; +-@@ -1137,17 +1139,22 @@ ieee80211_tx_prepare(struct ieee80211_su +- +- hdr = (struct ieee80211_hdr *) skb->data; +- +-- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +-- tx->sta = rcu_dereference(sdata->u.vlan.sta); +-- if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr) +-- return TX_DROP; +-- } else if (info->flags & (IEEE80211_TX_CTL_INJECTED | +-- IEEE80211_TX_INTFL_NL80211_FRAME_TX) || +-- tx->sdata->control_port_protocol == tx->skb->protocol) { +-- tx->sta = sta_info_get_bss(sdata, hdr->addr1); +-+ if (likely(sta)) { +-+ if (!IS_ERR(sta)) +-+ tx->sta = sta; +-+ } else { +-+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { +-+ tx->sta = rcu_dereference(sdata->u.vlan.sta); +-+ if (!tx->sta && sdata->wdev.use_4addr) +-+ return TX_DROP; +-+ } else if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX | +-+ IEEE80211_TX_CTL_INJECTED) || +-+ tx->sdata->control_port_protocol == tx->skb->protocol) { +-+ tx->sta = sta_info_get_bss(sdata, hdr->addr1); +-+ } +-+ if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) +-+ tx->sta = sta_info_get(sdata, hdr->addr1); +- } +-- if (!tx->sta && !is_multicast_ether_addr(hdr->addr1)) +-- tx->sta = sta_info_get(sdata, hdr->addr1); +- +- if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && +- !ieee80211_is_qos_nullfunc(hdr->frame_control) && +-@@ -1485,7 +1492,7 @@ bool ieee80211_tx_prepare_skb(struct iee +- struct ieee80211_tx_data tx; +- struct sk_buff *skb2; +- +-- if (ieee80211_tx_prepare(sdata, &tx, skb) == TX_DROP) +-+ if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) +- return false; +- +- info->band = band; +-@@ -1518,7 +1525,8 @@ EXPORT_SYMBOL(ieee80211_tx_prepare_skb); +- * Returns false if the frame couldn't be transmitted but was queued instead. +- */ +- static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, +-- struct sk_buff *skb, bool txpending) +-+ struct sta_info *sta, struct sk_buff *skb, +-+ bool txpending) +- { +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_tx_data tx; +-@@ -1534,7 +1542,7 @@ static bool ieee80211_tx(struct ieee8021 +- +- /* initialises tx */ +- led_len = skb->len; +-- res_prepare = ieee80211_tx_prepare(sdata, &tx, skb); +-+ res_prepare = ieee80211_tx_prepare(sdata, &tx, sta, skb); +- +- if (unlikely(res_prepare == TX_DROP)) { +- ieee80211_free_txskb(&local->hw, skb); +-@@ -1590,7 +1598,8 @@ static int ieee80211_skb_resize(struct i +- return 0; +- } +- +--void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) +-+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, +-+ struct sta_info *sta, struct sk_buff *skb) +- { +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); +-@@ -1625,7 +1634,7 @@ void ieee80211_xmit(struct ieee80211_sub +- } +- +- ieee80211_set_qos_hdr(sdata, skb); +-- ieee80211_tx(sdata, skb, false); +-+ ieee80211_tx(sdata, sta, skb, false); +- } +- +- static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb) +-@@ -1846,7 +1855,7 @@ netdev_tx_t ieee80211_monitor_start_xmit +- goto fail_rcu; +- +- info->band = chandef->chan->band; +-- ieee80211_xmit(sdata, skb); +-+ ieee80211_xmit(sdata, NULL, skb); +- rcu_read_unlock(); +- +- return NETDEV_TX_OK; +-@@ -1877,7 +1886,8 @@ fail: +- * Returns: the (possibly reallocated) skb or an ERR_PTR() code +- */ +- static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, +-- struct sk_buff *skb, u32 info_flags) +-+ struct sk_buff *skb, u32 info_flags, +-+ struct sta_info **sta_out) +- { +- struct ieee80211_local *local = sdata->local; +- struct ieee80211_tx_info *info; +-@@ -1920,6 +1930,7 @@ static struct sk_buff *ieee80211_build_h +- authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); +- wme_sta = sta->sta.wme; +- have_station = true; +-+ *sta_out = sta; +- } else if (sdata->wdev.use_4addr) { +- ret = -ENOLINK; +- goto free; +-@@ -2073,6 +2084,7 @@ static struct sk_buff *ieee80211_build_h +- have_station = true; +- authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); +- wme_sta = sta->sta.wme; +-+ *sta_out = sta; +- } else if (sdata->u.mgd.use_4addr && +- cpu_to_be16(ethertype) != sdata->control_port_protocol) { +- fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | +-@@ -2136,13 +2148,18 @@ static struct sk_buff *ieee80211_build_h +- * and mesh mode checks authorization later. +- */ +- multicast = is_multicast_ether_addr(hdr.addr1); +-- if (!multicast && !have_station && +-- !ieee80211_vif_is_mesh(&sdata->vif)) { +-- sta = sta_info_get(sdata, hdr.addr1); +-+ if (multicast) { +-+ *sta_out = ERR_PTR(-ENOENT); +-+ } else if (!have_station && !ieee80211_vif_is_mesh(&sdata->vif)) { +-+ if (sdata->control_port_protocol == skb->protocol) +-+ sta = sta_info_get_bss(sdata, hdr.addr1); +-+ else +-+ sta = sta_info_get(sdata, hdr.addr1); +- if (sta) { +- authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); +- wme_sta = sta->sta.wme; +- } +-+ *sta_out = sta ?: ERR_PTR(-ENOENT); +- } +- +- /* For mesh, the use of the QoS header is mandatory */ +-@@ -2320,6 +2337,7 @@ void __ieee80211_subif_start_xmit(struct +- u32 info_flags) +- { +- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); +-+ struct sta_info *sta = NULL; +- +- if (unlikely(skb->len < ETH_HLEN)) { +- kfree_skb(skb); +-@@ -2328,7 +2346,7 @@ void __ieee80211_subif_start_xmit(struct +- +- rcu_read_lock(); +- +-- skb = ieee80211_build_hdr(sdata, skb, info_flags); +-+ skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta); +- if (IS_ERR(skb)) +- goto out; +- +-@@ -2336,7 +2354,7 @@ void __ieee80211_subif_start_xmit(struct +- dev->stats.tx_bytes += skb->len; +- dev->trans_start = jiffies; +- +-- ieee80211_xmit(sdata, skb); +-+ ieee80211_xmit(sdata, sta, skb); +- out: +- rcu_read_unlock(); +- } +-@@ -2364,10 +2382,11 @@ ieee80211_build_data_template(struct iee +- .local = sdata->local, +- .sdata = sdata, +- }; +-+ struct sta_info *sta_ignore; +- +- rcu_read_lock(); +- +-- skb = ieee80211_build_hdr(sdata, skb, info_flags); +-+ skb = ieee80211_build_hdr(sdata, skb, info_flags, &sta_ignore); +- if (IS_ERR(skb)) +- goto out; +- +-@@ -2425,7 +2444,7 @@ static bool ieee80211_tx_pending_skb(str +- return true; +- } +- info->band = chanctx_conf->def.chan->band; +-- result = ieee80211_tx(sdata, skb, true); +-+ result = ieee80211_tx(sdata, NULL, skb, true); +- } else { +- struct sk_buff_head skbs; +- +-@@ -3163,7 +3182,7 @@ ieee80211_get_buffered_bc(struct ieee802 +- +- if (sdata->vif.type == NL80211_IFTYPE_AP) +- sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); +-- if (!ieee80211_tx_prepare(sdata, &tx, skb)) +-+ if (!ieee80211_tx_prepare(sdata, &tx, NULL, skb)) +- break; +- dev_kfree_skb_any(skb); +- } +-@@ -3295,6 +3314,6 @@ void __ieee80211_tx_skb_tid_band(struct +- */ +- local_bh_disable(); +- IEEE80211_SKB_CB(skb)->band = band; +-- ieee80211_xmit(sdata, skb); +-+ ieee80211_xmit(sdata, NULL, skb); +- local_bh_enable(); +- } +diff --git a/package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch b/package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch +new file mode 100644 +index 0000000..2d5f7b9 +--- /dev/null ++++ b/package/kernel/mac80211/patches/316-brcmfmac-block-the-correct-flowring-when-backup-queu.patch +@@ -0,0 +1,48 @@ ++From: Franky Lin ++Date: Thu, 20 Aug 2015 22:06:06 +0200 ++Subject: [PATCH] brcmfmac: block the correct flowring when backup queue ++ overflow ++ ++brcmf_flowring_block blocks the last active flowring under the same ++interface instead of the one provided by caller. This could lead to a ++dead lock of netif stop if there are more than one flowring under the ++interface and the traffic is high enough so brcmf_flowring_enqueue can ++not unblock the ring right away. ++ ++Reviewed-by: Pieter-Paul Giesberts ++Reviewed-by: Hante Meuleman ++Signed-off-by: Franky Lin ++Signed-off-by: Arend van Spriel ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c ++@@ -194,11 +194,15 @@ static void brcmf_flowring_block(struct ++ spin_lock_irqsave(&flow->block_lock, flags); ++ ++ ring = flow->rings[flowid]; +++ if (ring->blocked == blocked) { +++ spin_unlock_irqrestore(&flow->block_lock, flags); +++ return; +++ } ++ ifidx = brcmf_flowring_ifidx_get(flow, flowid); ++ ++ currently_blocked = false; ++ for (i = 0; i < flow->nrofrings; i++) { ++- if (flow->rings[i]) { +++ if ((flow->rings[i]) && (i != flowid)) { ++ ring = flow->rings[i]; ++ if ((ring->status == RING_OPEN) && ++ (brcmf_flowring_ifidx_get(flow, i) == ifidx)) { ++@@ -209,8 +213,8 @@ static void brcmf_flowring_block(struct ++ } ++ } ++ } ++- ring->blocked = blocked; ++- if (currently_blocked == blocked) { +++ flow->rings[flowid]->blocked = blocked; +++ if (currently_blocked) { ++ spin_unlock_irqrestore(&flow->block_lock, flags); ++ return; ++ } +diff --git a/package/kernel/mac80211/patches/316-mac80211-reduce-log-spam-from-ieee80211_handle_pwr_c.patch b/package/kernel/mac80211/patches/316-mac80211-reduce-log-spam-from-ieee80211_handle_pwr_c.patch +deleted file mode 100644 +index 77a82c2..0000000 +--- a/package/kernel/mac80211/patches/316-mac80211-reduce-log-spam-from-ieee80211_handle_pwr_c.patch ++++ /dev/null +@@ -1,38 +0,0 @@ +-From: John Linville +-Date: Tue, 31 Mar 2015 10:49:14 -0400 +-Subject: [PATCH] mac80211: reduce log spam from ieee80211_handle_pwr_constr +- +-This changes a couple of messages from sdata_info to sdata_dbg. +-This should reduce some log spam, as reported here: +- +- https://bugzilla.redhat.com/show_bug.cgi?id=1206468 +- +-Signed-off-by: John W. Linville +-Signed-off-by: Johannes Berg +---- +- +---- a/net/mac80211/mlme.c +-+++ b/net/mac80211/mlme.c +-@@ -1347,15 +1347,15 @@ static u32 ieee80211_handle_pwr_constr(s +- */ +- if (has_80211h_pwr && +- (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) { +-- sdata_info(sdata, +-- "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", +-- pwr_level_80211h, chan_pwr, pwr_reduction_80211h, +-- sdata->u.mgd.bssid); +-+ sdata_dbg(sdata, +-+ "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n", +-+ pwr_level_80211h, chan_pwr, pwr_reduction_80211h, +-+ sdata->u.mgd.bssid); +- new_ap_level = pwr_level_80211h; +- } else { /* has_cisco_pwr is always true here. */ +-- sdata_info(sdata, +-- "Limiting TX power to %d dBm as advertised by %pM\n", +-- pwr_level_cisco, sdata->u.mgd.bssid); +-+ sdata_dbg(sdata, +-+ "Limiting TX power to %d dBm as advertised by %pM\n", +-+ pwr_level_cisco, sdata->u.mgd.bssid); +- new_ap_level = pwr_level_cisco; +- } +- +diff --git a/package/kernel/mac80211/patches/317-brcmfmac-Fix-race-condition-in-msgbuf-ioctl-processi.patch b/package/kernel/mac80211/patches/317-brcmfmac-Fix-race-condition-in-msgbuf-ioctl-processi.patch +deleted file mode 100644 +index e005fe7..0000000 +--- a/package/kernel/mac80211/patches/317-brcmfmac-Fix-race-condition-in-msgbuf-ioctl-processi.patch ++++ /dev/null +@@ -1,35 +0,0 @@ +-From: Hante Meuleman +-Date: Fri, 6 Mar 2015 18:40:41 +0100 +-Subject: [PATCH] brcmfmac: Fix race condition in msgbuf ioctl processing. +- +-Msgbuf is using a wait_event_timeout to wait for the response on +-an ioctl. The wakeup routine uses waitqueue_active to see if +-wait_event_timeout has been called. There is a chance that the +-response arrives before wait_event_timeout is called, this +-will result in situation that wait_event_timeout never gets +-woken again and assumed result will be a timeout. This patch +-removes that errornous situation by always setting the +-ctl_completed var before checking for queue active. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-@@ -481,10 +481,9 @@ static int brcmf_msgbuf_ioctl_resp_wait( +- +- static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf) +- { +-- if (waitqueue_active(&msgbuf->ioctl_resp_wait)) { +-- msgbuf->ctl_completed = true; +-+ msgbuf->ctl_completed = true; +-+ if (waitqueue_active(&msgbuf->ioctl_resp_wait)) +- wake_up(&msgbuf->ioctl_resp_wait); +-- } +- } +- +- +diff --git a/package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch b/package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch +new file mode 100644 +index 0000000..7378401 +--- /dev/null ++++ b/package/kernel/mac80211/patches/317-brcmfmac-bump-highest-event-number-for-4339-firmware.patch +@@ -0,0 +1,52 @@ ++From: Arend van Spriel ++Date: Thu, 20 Aug 2015 22:06:07 +0200 ++Subject: [PATCH] brcmfmac: bump highest event number for 4339 firmware ++ ++The event mask length is determined by the highest event number ++that is specified in the driver. When this length is shorter than ++firmware expects setting event mask will fail and device becomes ++pretty useless. This issue was reported with bcm4339 firmware that ++was recently released. ++ ++Reported-by: Pontus Fuchs ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Reviewed-by: Pontus Fuchs ++Signed-off-by: Arend van Spriel ++Signed-off-by: Kalle Valo ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h ++@@ -85,7 +85,6 @@ struct brcmf_event; ++ BRCMF_ENUM_DEF(IF, 54) \ ++ BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \ ++ BRCMF_ENUM_DEF(RSSI, 56) \ ++- BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \ ++ BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \ ++ BRCMF_ENUM_DEF(ACTION_FRAME, 59) \ ++ BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \ ++@@ -103,8 +102,7 @@ struct brcmf_event; ++ BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \ ++ BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \ ++ BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \ ++- BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \ ++- BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128) +++ BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) ++ ++ #define BRCMF_ENUM_DEF(id, val) \ ++ BRCMF_E_##id = (val), ++@@ -112,7 +110,11 @@ struct brcmf_event; ++ /* firmware event codes sent by the dongle */ ++ enum brcmf_fweh_event_code { ++ BRCMF_FWEH_EVENT_ENUM_DEFLIST ++- BRCMF_E_LAST +++ /* this determines event mask length which must match +++ * minimum length check in device firmware so it is +++ * hard-coded here. +++ */ +++ BRCMF_E_LAST = 139 ++ }; ++ #undef BRCMF_ENUM_DEF ++ +diff --git a/package/kernel/mac80211/patches/318-brcmfmac-Update-msgbuf-commonring-size-for-improved-.patch b/package/kernel/mac80211/patches/318-brcmfmac-Update-msgbuf-commonring-size-for-improved-.patch +deleted file mode 100644 +index c2cd1c5..0000000 +--- a/package/kernel/mac80211/patches/318-brcmfmac-Update-msgbuf-commonring-size-for-improved-.patch ++++ /dev/null +@@ -1,30 +0,0 @@ +-From: Hante Meuleman +-Date: Wed, 18 Mar 2015 13:25:23 +0100 +-Subject: [PATCH] brcmfmac: Update msgbuf commonring size for improved +- throughput. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h +-@@ -17,11 +17,11 @@ +- +- #ifdef CPTCFG_BRCMFMAC_PROTO_MSGBUF +- +--#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 20 +--#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 256 +--#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 20 +-+#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 64 +-+#define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 512 +-+#define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_MAX_ITEM 64 +- #define BRCMF_D2H_MSGRING_TX_COMPLETE_MAX_ITEM 1024 +--#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 256 +-+#define BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM 512 +- #define BRCMF_H2D_TXFLOWRING_MAX_ITEM 512 +- +- #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40 +diff --git a/package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch b/package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch +deleted file mode 100644 +index 6af69eb..0000000 +--- a/package/kernel/mac80211/patches/319-ath9k_htc-add-new-WMI_REG_RMW_CMDID-command.patch ++++ /dev/null +@@ -1,307 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:46 +0100 +-Subject: [PATCH] ath9k_htc: add new WMI_REG_RMW_CMDID command +- +-Since usb bus add extra delay on each request, a command +-with read + write requests is too expensive. We can dramtically +-reduce usb load by moving this command to firmware. +- +-In my tests, this patch will reduce channel scan time +-for about 5-10 seconds. +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath.h +-+++ b/drivers/net/wireless/ath/ath.h +-@@ -131,6 +131,9 @@ struct ath_ops { +- void (*enable_write_buffer)(void *); +- void (*write_flush) (void *); +- u32 (*rmw)(void *, u32 reg_offset, u32 set, u32 clr); +-+ void (*enable_rmw_buffer)(void *); +-+ void (*rmw_flush) (void *); +-+ +- }; +- +- struct ath_common; +---- a/drivers/net/wireless/ath/ath9k/htc.h +-+++ b/drivers/net/wireless/ath/ath9k/htc.h +-@@ -444,6 +444,10 @@ static inline void ath9k_htc_stop_btcoex +- #define OP_BT_SCAN BIT(4) +- #define OP_TSF_RESET BIT(6) +- +-+enum htc_op_flags { +-+ HTC_FWFLAG_NO_RMW, +-+}; +-+ +- struct ath9k_htc_priv { +- struct device *dev; +- struct ieee80211_hw *hw; +-@@ -482,6 +486,7 @@ struct ath9k_htc_priv { +- bool reconfig_beacon; +- unsigned int rxfilter; +- unsigned long op_flags; +-+ unsigned long fw_flags; +- +- struct ath9k_hw_cal_data caldata; +- struct ath_spec_scan_priv spec_priv; +---- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +-+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c +-@@ -376,17 +376,139 @@ static void ath9k_regwrite_flush(void *h +- mutex_unlock(&priv->wmi->multi_write_mutex); +- } +- +--static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) +-+static void ath9k_reg_rmw_buffer(void *hw_priv, +-+ u32 reg_offset, u32 set, u32 clr) +-+{ +-+ struct ath_hw *ah = (struct ath_hw *) hw_priv; +-+ struct ath_common *common = ath9k_hw_common(ah); +-+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; +-+ u32 rsp_status; +-+ int r; +-+ +-+ mutex_lock(&priv->wmi->multi_rmw_mutex); +-+ +-+ /* Store the register/value */ +-+ priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].reg = +-+ cpu_to_be32(reg_offset); +-+ priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].set = +-+ cpu_to_be32(set); +-+ priv->wmi->multi_rmw[priv->wmi->multi_rmw_idx].clr = +-+ cpu_to_be32(clr); +-+ +-+ priv->wmi->multi_rmw_idx++; +-+ +-+ /* If the buffer is full, send it out. */ +-+ if (priv->wmi->multi_rmw_idx == MAX_RMW_CMD_NUMBER) { +-+ r = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID, +-+ (u8 *) &priv->wmi->multi_rmw, +-+ sizeof(struct register_write) * priv->wmi->multi_rmw_idx, +-+ (u8 *) &rsp_status, sizeof(rsp_status), +-+ 100); +-+ if (unlikely(r)) { +-+ ath_dbg(common, WMI, +-+ "REGISTER RMW FAILED, multi len: %d\n", +-+ priv->wmi->multi_rmw_idx); +-+ } +-+ priv->wmi->multi_rmw_idx = 0; +-+ } +-+ +-+ mutex_unlock(&priv->wmi->multi_rmw_mutex); +-+} +-+ +-+static void ath9k_reg_rmw_flush(void *hw_priv) +- { +-- u32 val; +-+ struct ath_hw *ah = (struct ath_hw *) hw_priv; +-+ struct ath_common *common = ath9k_hw_common(ah); +-+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; +-+ u32 rsp_status; +-+ int r; +-+ +-+ if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) +-+ return; +-+ +-+ atomic_dec(&priv->wmi->m_rmw_cnt); +-+ +-+ mutex_lock(&priv->wmi->multi_rmw_mutex); +-+ +-+ if (priv->wmi->multi_rmw_idx) { +-+ r = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID, +-+ (u8 *) &priv->wmi->multi_rmw, +-+ sizeof(struct register_rmw) * priv->wmi->multi_rmw_idx, +-+ (u8 *) &rsp_status, sizeof(rsp_status), +-+ 100); +-+ if (unlikely(r)) { +-+ ath_dbg(common, WMI, +-+ "REGISTER RMW FAILED, multi len: %d\n", +-+ priv->wmi->multi_rmw_idx); +-+ } +-+ priv->wmi->multi_rmw_idx = 0; +-+ } +- +-- val = ath9k_regread(hw_priv, reg_offset); +-- val &= ~clr; +-- val |= set; +-- ath9k_regwrite(hw_priv, val, reg_offset); +-+ mutex_unlock(&priv->wmi->multi_rmw_mutex); +-+} +-+ +-+static void ath9k_enable_rmw_buffer(void *hw_priv) +-+{ +-+ struct ath_hw *ah = (struct ath_hw *) hw_priv; +-+ struct ath_common *common = ath9k_hw_common(ah); +-+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; +-+ +-+ if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) +-+ return; +-+ +-+ atomic_inc(&priv->wmi->m_rmw_cnt); +-+} +-+ +-+static u32 ath9k_reg_rmw_single(void *hw_priv, +-+ u32 reg_offset, u32 set, u32 clr) +-+{ +-+ struct ath_hw *ah = (struct ath_hw *) hw_priv; +-+ struct ath_common *common = ath9k_hw_common(ah); +-+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; +-+ struct register_rmw buf, buf_ret; +-+ int ret; +-+ u32 val = 0; +-+ +-+ buf.reg = cpu_to_be32(reg_offset); +-+ buf.set = cpu_to_be32(set); +-+ buf.clr = cpu_to_be32(clr); +-+ +-+ ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_RMW_CMDID, +-+ (u8 *) &buf, sizeof(buf), +-+ (u8 *) &buf_ret, sizeof(buf_ret), +-+ 100); +-+ if (unlikely(ret)) { +-+ ath_dbg(common, WMI, "REGISTER RMW FAILED:(0x%04x, %d)\n", +-+ reg_offset, ret); +-+ } +- return val; +- } +- +-+static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) +-+{ +-+ struct ath_hw *ah = (struct ath_hw *) hw_priv; +-+ struct ath_common *common = ath9k_hw_common(ah); +-+ struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; +-+ +-+ if (test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags)) { +-+ u32 val; +-+ +-+ val = REG_READ(ah, reg_offset); +-+ val &= ~clr; +-+ val |= set; +-+ REG_WRITE(ah, reg_offset, val); +-+ +-+ return 0; +-+ } +-+ +-+ if (atomic_read(&priv->wmi->m_rmw_cnt)) +-+ ath9k_reg_rmw_buffer(hw_priv, reg_offset, set, clr); +-+ else +-+ ath9k_reg_rmw_single(hw_priv, reg_offset, set, clr); +-+ +-+ return 0; +-+} +-+ +- static void ath_usb_read_cachesize(struct ath_common *common, int *csz) +- { +- *csz = L1_CACHE_BYTES >> 2; +-@@ -501,6 +623,8 @@ static int ath9k_init_priv(struct ath9k_ +- ah->reg_ops.write = ath9k_regwrite; +- ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; +- ah->reg_ops.write_flush = ath9k_regwrite_flush; +-+ ah->reg_ops.enable_rmw_buffer = ath9k_enable_rmw_buffer; +-+ ah->reg_ops.rmw_flush = ath9k_reg_rmw_flush; +- ah->reg_ops.rmw = ath9k_reg_rmw; +- priv->ah = ah; +- +-@@ -686,6 +810,12 @@ static int ath9k_init_firmware_version(s +- return -EINVAL; +- } +- +-+ if (priv->fw_version_major == 1 && priv->fw_version_minor < 4) +-+ set_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags); +-+ +-+ dev_info(priv->dev, "FW RMW support: %s\n", +-+ test_bit(HTC_FWFLAG_NO_RMW, &priv->fw_flags) ? "Off" : "On"); +-+ +- return 0; +- } +- +---- a/drivers/net/wireless/ath/ath9k/hw.h +-+++ b/drivers/net/wireless/ath/ath9k/hw.h +-@@ -100,6 +100,18 @@ +- (_ah)->reg_ops.write_flush((_ah)); \ +- } while (0) +- +-+#define ENABLE_REG_RMW_BUFFER(_ah) \ +-+ do { \ +-+ if ((_ah)->reg_ops.enable_rmw_buffer) \ +-+ (_ah)->reg_ops.enable_rmw_buffer((_ah)); \ +-+ } while (0) +-+ +-+#define REG_RMW_BUFFER_FLUSH(_ah) \ +-+ do { \ +-+ if ((_ah)->reg_ops.rmw_flush) \ +-+ (_ah)->reg_ops.rmw_flush((_ah)); \ +-+ } while (0) +-+ +- #define PR_EEP(_s, _val) \ +- do { \ +- len += scnprintf(buf + len, size - len, "%20s : %10d\n",\ +---- a/drivers/net/wireless/ath/ath9k/wmi.c +-+++ b/drivers/net/wireless/ath/ath9k/wmi.c +-@@ -61,6 +61,8 @@ static const char *wmi_cmd_to_name(enum +- return "WMI_REG_READ_CMDID"; +- case WMI_REG_WRITE_CMDID: +- return "WMI_REG_WRITE_CMDID"; +-+ case WMI_REG_RMW_CMDID: +-+ return "WMI_REG_RMW_CMDID"; +- case WMI_RC_STATE_CHANGE_CMDID: +- return "WMI_RC_STATE_CHANGE_CMDID"; +- case WMI_RC_RATE_UPDATE_CMDID: +-@@ -101,6 +103,7 @@ struct wmi *ath9k_init_wmi(struct ath9k_ +- spin_lock_init(&wmi->event_lock); +- mutex_init(&wmi->op_mutex); +- mutex_init(&wmi->multi_write_mutex); +-+ mutex_init(&wmi->multi_rmw_mutex); +- init_completion(&wmi->cmd_wait); +- INIT_LIST_HEAD(&wmi->pending_tx_events); +- tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, +---- a/drivers/net/wireless/ath/ath9k/wmi.h +-+++ b/drivers/net/wireless/ath/ath9k/wmi.h +-@@ -112,6 +112,7 @@ enum wmi_cmd_id { +- WMI_TX_STATS_CMDID, +- WMI_RX_STATS_CMDID, +- WMI_BITRATE_MASK_CMDID, +-+ WMI_REG_RMW_CMDID, +- }; +- +- enum wmi_event_id { +-@@ -125,12 +126,19 @@ enum wmi_event_id { +- }; +- +- #define MAX_CMD_NUMBER 62 +-+#define MAX_RMW_CMD_NUMBER 15 +- +- struct register_write { +- __be32 reg; +- __be32 val; +- }; +- +-+struct register_rmw { +-+ __be32 reg; +-+ __be32 set; +-+ __be32 clr; +-+} __packed; +-+ +- struct ath9k_htc_tx_event { +- int count; +- struct __wmi_event_txstatus txs; +-@@ -156,10 +164,18 @@ struct wmi { +- +- spinlock_t wmi_lock; +- +-+ /* multi write section */ +- atomic_t mwrite_cnt; +- struct register_write multi_write[MAX_CMD_NUMBER]; +- u32 multi_write_idx; +- struct mutex multi_write_mutex; +-+ +-+ /* multi rmw section */ +-+ atomic_t m_rmw_cnt; +-+ struct register_rmw multi_rmw[MAX_RMW_CMD_NUMBER]; +-+ u32 multi_rmw_idx; +-+ struct mutex multi_rmw_mutex; +-+ +- }; +- +- struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv); +diff --git a/package/kernel/mac80211/patches/319-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch b/package/kernel/mac80211/patches/319-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch +new file mode 100644 +index 0000000..97444b3 +--- /dev/null ++++ b/package/kernel/mac80211/patches/319-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch +@@ -0,0 +1,138 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:14:53 +0200 ++Subject: [PATCH] brcmfmac: consolidate ifp lookup in driver core ++ ++In rx path the firmware provide an interface index which is used to ++map to a struct brcmf_if instance. However, this involves some trick ++that is done in two places. This is changed by having driver core ++providing brcmf_get_ifp() function. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c ++@@ -276,6 +276,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu ++ struct sk_buff *pktbuf) ++ { ++ struct brcmf_proto_bcdc_header *h; +++ struct brcmf_if *ifp; ++ ++ brcmf_dbg(BCDC, "Enter\n"); ++ ++@@ -289,30 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu ++ trace_brcmf_bcdchdr(pktbuf->data); ++ h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); ++ ++- *ifidx = BCDC_GET_IF_IDX(h); ++- if (*ifidx >= BRCMF_MAX_IFS) { ++- brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); +++ ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); +++ if (IS_ERR_OR_NULL(ifp)) { +++ brcmf_dbg(INFO, "no matching ifp found\n"); ++ return -EBADE; ++ } ++- /* The ifidx is the idx to map to matching netdev/ifp. When receiving ++- * events this is easy because it contains the bssidx which maps ++- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. ++- * bssidx 1 is used for p2p0 and no data can be received or ++- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 ++- */ ++- if (*ifidx) ++- (*ifidx)++; ++- ++ if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != ++ BCDC_PROTO_VER) { ++ brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", ++- brcmf_ifname(drvr, *ifidx), h->flags); +++ brcmf_ifname(drvr, ifp->ifidx), h->flags); ++ return -EBADE; ++ } ++ ++ if (h->flags & BCDC_FLAG_SUM_GOOD) { ++ brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", ++- brcmf_ifname(drvr, *ifidx), h->flags); +++ brcmf_ifname(drvr, ifp->ifidx), h->flags); ++ pktbuf->ip_summed = CHECKSUM_UNNECESSARY; ++ } ++ ++@@ -320,12 +312,15 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu ++ ++ skb_pull(pktbuf, BCDC_HEADER_LEN); ++ if (do_fws) ++- brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); +++ brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2, +++ pktbuf); ++ else ++ skb_pull(pktbuf, h->data_offset << 2); ++ ++ if (pktbuf->len == 0) ++ return -ENODATA; +++ +++ *ifidx = ifp->ifidx; ++ return 0; ++ } ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c ++@@ -83,6 +83,25 @@ char *brcmf_ifname(struct brcmf_pub *drv ++ return ""; ++ } ++ +++struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) +++{ +++ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { +++ brcmf_err("ifidx %d out of range\n", ifidx); +++ return ERR_PTR(-ERANGE); +++ } +++ +++ /* The ifidx is the idx to map to matching netdev/ifp. When receiving +++ * events this is easy because it contains the bssidx which maps +++ * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. +++ * bssidx 1 is used for p2p0 and no data can be received or +++ * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 +++ */ +++ if (ifidx) +++ ifidx++; +++ +++ return drvr->iflist[ifidx]; +++} +++ ++ static void _brcmf_set_multicast_list(struct work_struct *work) ++ { ++ struct brcmf_if *ifp; ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h ++@@ -202,7 +202,7 @@ int brcmf_netdev_wait_pend8021x(struct b ++ ++ /* Return pointer to interface name */ ++ char *brcmf_ifname(struct brcmf_pub *drvr, int idx); ++- +++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 bssidx, s32 ifidx, ++ char *name, u8 *mac_addr); ++--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c ++@@ -1081,16 +1081,8 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf ++ { ++ struct brcmf_if *ifp; ++ ++- /* The ifidx is the idx to map to matching netdev/ifp. When receiving ++- * events this is easy because it contains the bssidx which maps ++- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. ++- * bssidx 1 is used for p2p0 and no data can be received or ++- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 ++- */ ++- if (ifidx) ++- (ifidx)++; ++- ifp = msgbuf->drvr->iflist[ifidx]; ++- if (!ifp || !ifp->ndev) { +++ ifp = brcmf_get_ifp(msgbuf->drvr, ifidx); +++ if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) { ++ brcmf_err("Received pkt for invalid ifidx %d\n", ifidx); ++ brcmu_pkt_buf_free_skb(skb); ++ return; +diff --git a/package/kernel/mac80211/patches/320-ath9k-ar9271_hw_pa_cal-use-defs-instead-of-magin-num.patch b/package/kernel/mac80211/patches/320-ath9k-ar9271_hw_pa_cal-use-defs-instead-of-magin-num.patch +deleted file mode 100644 +index c4dd1af..0000000 +--- a/package/kernel/mac80211/patches/320-ath9k-ar9271_hw_pa_cal-use-defs-instead-of-magin-num.patch ++++ /dev/null +@@ -1,89 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:47 +0100 +-Subject: [PATCH] ath9k: ar9271_hw_pa_cal - use defs instead of magin +- numbers +- +-This function uses mixed styles for register names/numbers which +-is make harder reading and optimisation. +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c +-@@ -430,22 +430,22 @@ static void ar9271_hw_pa_cal(struct ath_ +- u32 regVal; +- unsigned int i; +- u32 regList[][2] = { +-- { 0x786c, 0 }, +-- { 0x7854, 0 }, +-- { 0x7820, 0 }, +-- { 0x7824, 0 }, +-- { 0x7868, 0 }, +-- { 0x783c, 0 }, +-- { 0x7838, 0 } , +-- { 0x7828, 0 } , +-+ { AR9285_AN_TOP3, 0 }, +-+ { AR9285_AN_RXTXBB1, 0 }, +-+ { AR9285_AN_RF2G1, 0 }, +-+ { AR9285_AN_RF2G2, 0 }, +-+ { AR9285_AN_TOP2, 0 }, +-+ { AR9285_AN_RF2G8, 0 }, +-+ { AR9285_AN_RF2G7, 0 } , +-+ { AR9285_AN_RF2G3, 0 } , +- }; +- +- for (i = 0; i < ARRAY_SIZE(regList); i++) +- regList[i][1] = REG_READ(ah, regList[i][0]); +- +-- regVal = REG_READ(ah, 0x7834); +-+ regVal = REG_READ(ah, AR9285_AN_RF2G6); +- regVal &= (~(0x1)); +-- REG_WRITE(ah, 0x7834, regVal); +-+ REG_WRITE(ah, AR9285_AN_RF2G6, regVal); +- regVal = REG_READ(ah, 0x9808); +- regVal |= (0x1 << 27); +- REG_WRITE(ah, 0x9808, regVal); +-@@ -477,7 +477,7 @@ static void ar9271_hw_pa_cal(struct ath_ +- * does not matter since we turn it off +- */ +- REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); +-- +-+ /* 7828, b0-11, ccom=fff */ +- REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); +- +- /* Set: +-@@ -490,15 +490,16 @@ static void ar9271_hw_pa_cal(struct ath_ +- +- /* find off_6_1; */ +- for (i = 6; i > 0; i--) { +-- regVal = REG_READ(ah, 0x7834); +-+ regVal = REG_READ(ah, AR9285_AN_RF2G6); +- regVal |= (1 << (20 + i)); +-- REG_WRITE(ah, 0x7834, regVal); +-+ REG_WRITE(ah, AR9285_AN_RF2G6, regVal); +- udelay(1); +- /* regVal = REG_READ(ah, 0x7834); */ +- regVal &= (~(0x1 << (20 + i))); +-- regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) +-+ regVal |= (MS(REG_READ(ah, AR9285_AN_RF2G9), +-+ AR9285_AN_RXTXBB1_SPARE9) +- << (20 + i)); +-- REG_WRITE(ah, 0x7834, regVal); +-+ REG_WRITE(ah, AR9285_AN_RF2G6, regVal); +- } +- +- regVal = (regVal >> 20) & 0x7f; +-@@ -517,9 +518,9 @@ static void ar9271_hw_pa_cal(struct ath_ +- +- ENABLE_REGWRITE_BUFFER(ah); +- +-- regVal = REG_READ(ah, 0x7834); +-+ regVal = REG_READ(ah, AR_AN_RF2G1_CH1); +- regVal |= 0x1; +-- REG_WRITE(ah, 0x7834, regVal); +-+ REG_WRITE(ah, AR_AN_RF2G1_CH1, regVal); +- regVal = REG_READ(ah, 0x9808); +- regVal &= (~(0x1 << 27)); +- REG_WRITE(ah, 0x9808, regVal); +diff --git a/package/kernel/mac80211/patches/320-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch b/package/kernel/mac80211/patches/320-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch +new file mode 100644 +index 0000000..632714c +--- /dev/null ++++ b/package/kernel/mac80211/patches/320-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch +@@ -0,0 +1,222 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:14:54 +0200 ++Subject: [PATCH] brcmfmac: make brcmf_proto_hdrpull() return struct ++ brcmf_if instance ++ ++Avoid spreading the ifidx in the driver, but have it return the ++struct brcmf_if instance. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c ++@@ -272,11 +272,11 @@ brcmf_proto_bcdc_hdrpush(struct brcmf_pu ++ } ++ ++ static int ++-brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, ++- struct sk_buff *pktbuf) +++brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, +++ struct sk_buff *pktbuf, struct brcmf_if **ifp) ++ { ++ struct brcmf_proto_bcdc_header *h; ++- struct brcmf_if *ifp; +++ struct brcmf_if *tmp_if; ++ ++ brcmf_dbg(BCDC, "Enter\n"); ++ ++@@ -290,21 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu ++ trace_brcmf_bcdchdr(pktbuf->data); ++ h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); ++ ++- ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); ++- if (IS_ERR_OR_NULL(ifp)) { +++ tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); +++ if (!tmp_if) { ++ brcmf_dbg(INFO, "no matching ifp found\n"); ++ return -EBADE; ++ } ++ if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != ++ BCDC_PROTO_VER) { ++ brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", ++- brcmf_ifname(drvr, ifp->ifidx), h->flags); +++ brcmf_ifname(drvr, tmp_if->ifidx), h->flags); ++ return -EBADE; ++ } ++ ++ if (h->flags & BCDC_FLAG_SUM_GOOD) { ++ brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", ++- brcmf_ifname(drvr, ifp->ifidx), h->flags); +++ brcmf_ifname(drvr, tmp_if->ifidx), h->flags); ++ pktbuf->ip_summed = CHECKSUM_UNNECESSARY; ++ } ++ ++@@ -312,7 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu ++ ++ skb_pull(pktbuf, BCDC_HEADER_LEN); ++ if (do_fws) ++- brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2, +++ brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2, ++ pktbuf); ++ else ++ skb_pull(pktbuf, h->data_offset << 2); ++@@ -320,7 +320,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu ++ if (pktbuf->len == 0) ++ return -ENODATA; ++ ++- *ifidx = ifp->ifidx; +++ *ifp = tmp_if; ++ return 0; ++ } ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c ++@@ -87,7 +87,7 @@ struct brcmf_if *brcmf_get_ifp(struct br ++ { ++ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { ++ brcmf_err("ifidx %d out of range\n", ifidx); ++- return ERR_PTR(-ERANGE); +++ return NULL; ++ } ++ ++ /* The ifidx is the idx to map to matching netdev/ifp. When receiving ++@@ -539,17 +539,15 @@ void brcmf_rx_frame(struct device *dev, ++ struct brcmf_bus *bus_if = dev_get_drvdata(dev); ++ struct brcmf_pub *drvr = bus_if->drvr; ++ struct brcmf_skb_reorder_data *rd; ++- u8 ifidx; ++ int ret; ++ ++ brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); ++ ++ /* process and remove protocol-specific header */ ++- ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb); ++- ifp = drvr->iflist[ifidx]; +++ ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); ++ ++ if (ret || !ifp || !ifp->ndev) { ++- if ((ret != -ENODATA) && ifp) +++ if (ret != -ENODATA && ifp) ++ ifp->stats.rx_errors++; ++ brcmu_pkt_buf_free_skb(skb); ++ return; ++@@ -592,17 +590,17 @@ void brcmf_txcomplete(struct device *dev ++ { ++ struct brcmf_bus *bus_if = dev_get_drvdata(dev); ++ struct brcmf_pub *drvr = bus_if->drvr; ++- u8 ifidx; +++ struct brcmf_if *ifp; ++ ++ /* await txstatus signal for firmware if active */ ++ if (brcmf_fws_fc_active(drvr->fws)) { ++ if (!success) ++ brcmf_fws_bustxfail(drvr->fws, txp); ++ } else { ++- if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp)) +++ if (brcmf_proto_hdrpull(drvr, false, txp, &ifp)) ++ brcmu_pkt_buf_free_skb(txp); ++ else ++- brcmf_txfinalize(drvr, txp, ifidx, success); +++ brcmf_txfinalize(drvr, txp, ifp->ifidx, success); ++ } ++ } ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c ++@@ -1448,7 +1448,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i ++ struct sk_buff *skb; ++ struct brcmf_skbuff_cb *skcb; ++ struct brcmf_fws_mac_descriptor *entry = NULL; ++- u8 ifidx; +++ struct brcmf_if *ifp; ++ ++ brcmf_dbg(DATA, "flags %d\n", flags); ++ ++@@ -1497,15 +1497,16 @@ brcmf_fws_txs_process(struct brcmf_fws_i ++ } ++ brcmf_fws_macdesc_return_req_credit(skb); ++ ++- if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) { +++ ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp); +++ if (ret) { ++ brcmu_pkt_buf_free_skb(skb); ++ return -EINVAL; ++ } ++ if (!remove_from_hanger) ++- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx, +++ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx, ++ genbit, seq); ++ if (remove_from_hanger || ret) ++- brcmf_txfinalize(fws->drvr, skb, ifidx, true); +++ brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true); ++ ++ return 0; ++ } ++@@ -1848,7 +1849,7 @@ static int brcmf_fws_commit_skb(struct b ++ entry->transit_count--; ++ if (entry->suppressed) ++ entry->suppr_transit_count--; ++- brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); +++ (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL); ++ goto rollback; ++ } ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c ++@@ -522,7 +522,7 @@ static int brcmf_msgbuf_set_dcmd(struct ++ ++ ++ static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws, ++- u8 *ifidx, struct sk_buff *skb) +++ struct sk_buff *skb, struct brcmf_if **ifp) ++ { ++ return -ENODEV; ++ } ++@@ -1082,7 +1082,7 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf ++ struct brcmf_if *ifp; ++ ++ ifp = brcmf_get_ifp(msgbuf->drvr, ifidx); ++- if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) { +++ if (!ifp || !ifp->ndev) { ++ brcmf_err("Received pkt for invalid ifidx %d\n", ifidx); ++ brcmu_pkt_buf_free_skb(skb); ++ return; ++--- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h ++@@ -24,8 +24,8 @@ enum proto_addr_mode { ++ ++ ++ struct brcmf_proto { ++- int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, ++- struct sk_buff *skb); +++ int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, +++ struct sk_buff *skb, struct brcmf_if **ifp); ++ int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, ++ void *buf, uint len); ++ int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, ++@@ -46,9 +46,19 @@ int brcmf_proto_attach(struct brcmf_pub ++ void brcmf_proto_detach(struct brcmf_pub *drvr); ++ ++ static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, ++- u8 *ifidx, struct sk_buff *skb) +++ struct sk_buff *skb, +++ struct brcmf_if **ifp) ++ { ++- return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb); +++ struct brcmf_if *tmp = NULL; +++ +++ /* assure protocol is always called with +++ * non-null initialized pointer. +++ */ +++ if (ifp) +++ *ifp = NULL; +++ else +++ ifp = &tmp; +++ return drvr->proto->hdrpull(drvr, do_fws, skb, ifp); ++ } ++ static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx, ++ uint cmd, void *buf, uint len) +diff --git a/package/kernel/mac80211/patches/321-ath9k-ar9271_hw_pa_cal-use-proper-makroses.patch b/package/kernel/mac80211/patches/321-ath9k-ar9271_hw_pa_cal-use-proper-makroses.patch +deleted file mode 100644 +index f05287d..0000000 +--- a/package/kernel/mac80211/patches/321-ath9k-ar9271_hw_pa_cal-use-proper-makroses.patch ++++ /dev/null +@@ -1,79 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:48 +0100 +-Subject: [PATCH] ath9k: ar9271_hw_pa_cal: use proper makroses. +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c +-@@ -443,33 +443,30 @@ static void ar9271_hw_pa_cal(struct ath_ +- for (i = 0; i < ARRAY_SIZE(regList); i++) +- regList[i][1] = REG_READ(ah, regList[i][0]); +- +-- regVal = REG_READ(ah, AR9285_AN_RF2G6); +-- regVal &= (~(0x1)); +-- REG_WRITE(ah, AR9285_AN_RF2G6, regVal); +-- regVal = REG_READ(ah, 0x9808); +-- regVal |= (0x1 << 27); +-- REG_WRITE(ah, 0x9808, regVal); +-- +-+ /* 7834, b1=0 */ +-+ REG_CLR_BIT(ah, AR9285_AN_RF2G6, 1 << 0); +-+ /* 9808, b27=1 */ +-+ REG_SET_BIT(ah, 0x9808, 1 << 27); +- /* 786c,b23,1, pwddac=1 */ +-- REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); +-+ REG_SET_BIT(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC); +- /* 7854, b5,1, pdrxtxbb=1 */ +-- REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); +-+ REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1); +- /* 7854, b7,1, pdv2i=1 */ +-- REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); +-+ REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I); +- /* 7854, b8,1, pddacinterface=1 */ +-- REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); +-+ REG_SET_BIT(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF); +- /* 7824,b12,0, offcal=0 */ +-- REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); +-+ REG_CLR_BIT(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL); +- /* 7838, b1,0, pwddb=0 */ +-- REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); +-+ REG_CLR_BIT(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB); +- /* 7820,b11,0, enpacal=0 */ +-- REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); +-+ REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL); +- /* 7820,b25,1, pdpadrv1=0 */ +-- REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); +-+ REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1); +- /* 7820,b24,0, pdpadrv2=0 */ +-- REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); +-+ REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2); +- /* 7820,b23,0, pdpaout=0 */ +-- REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); +-+ REG_CLR_BIT(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT); +- /* 783c,b14-16,7, padrvgn2tab_0=7 */ +- REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); +- /* +-@@ -516,15 +513,13 @@ static void ar9271_hw_pa_cal(struct ath_ +- ah->pacal_info.prev_offset = regVal; +- } +- +-- ENABLE_REGWRITE_BUFFER(ah); +- +-- regVal = REG_READ(ah, AR_AN_RF2G1_CH1); +-- regVal |= 0x1; +-- REG_WRITE(ah, AR_AN_RF2G1_CH1, regVal); +-- regVal = REG_READ(ah, 0x9808); +-- regVal &= (~(0x1 << 27)); +-- REG_WRITE(ah, 0x9808, regVal); +-+ /* 7834, b1=1 */ +-+ REG_SET_BIT(ah, AR9285_AN_RF2G6, 1 << 0); +-+ /* 9808, b27=0 */ +-+ REG_CLR_BIT(ah, 0x9808, 1 << 27); +- +-+ ENABLE_REGWRITE_BUFFER(ah); +- for (i = 0; i < ARRAY_SIZE(regList); i++) +- REG_WRITE(ah, regList[i][0], regList[i][1]); +- +diff --git a/package/kernel/mac80211/patches/321-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch b/package/kernel/mac80211/patches/321-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch +new file mode 100644 +index 0000000..3360cbc +--- /dev/null ++++ b/package/kernel/mac80211/patches/321-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch +@@ -0,0 +1,87 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:14:55 +0200 ++Subject: [PATCH] brcmfmac: change parameters for ++ brcmf_remove_interface() ++ ++Just pass the interface to be removed, ie. the struct brcmf_if instance. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++@@ -4983,7 +4983,7 @@ brcmf_notify_connect_status_ap(struct br ++ brcmf_dbg(CONN, "AP mode link down\n"); ++ complete(&cfg->vif_disabled); ++ if (ifp->vif->mbss) ++- brcmf_remove_interface(ifp->drvr, ifp->bssidx); +++ brcmf_remove_interface(ifp); ++ return 0; ++ } ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c ++@@ -887,12 +887,13 @@ static void brcmf_del_if(struct brcmf_pu ++ } ++ } ++ ++-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx) +++void brcmf_remove_interface(struct brcmf_if *ifp) ++ { ++- if (drvr->iflist[bssidx]) { ++- brcmf_fws_del_interface(drvr->iflist[bssidx]); ++- brcmf_del_if(drvr, bssidx); ++- } +++ if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp)) +++ return; +++ +++ brcmf_fws_del_interface(ifp); +++ brcmf_del_if(ifp->drvr, ifp->bssidx); ++ } ++ ++ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr) ++@@ -1122,7 +1123,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, i); +++ brcmf_remove_interface(drvr->iflist[i]); ++ ++ brcmf_cfg80211_detach(drvr->config); ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h ++@@ -206,7 +206,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 bssidx, s32 ifidx, ++ char *name, u8 *mac_addr); ++-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx); +++void brcmf_remove_interface(struct brcmf_if *ifp); ++ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); ++ void brcmf_txflowblock_if(struct brcmf_if *ifp, ++ enum brcmf_netif_stop_reason reason, bool state); ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c ++@@ -222,7 +222,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(drvr, ifevent->bssidx); +++ brcmf_remove_interface(ifp); ++ } ++ ++ /** ++--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c ++@@ -2140,7 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(stru ++ { ++ cfg80211_unregister_wdev(&vif->wdev); ++ p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; ++- brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx); +++ brcmf_remove_interface(vif->ifp); ++ brcmf_free_vif(vif); ++ } ++ +diff --git a/package/kernel/mac80211/patches/322-ath9k-ar9271_hw_pa_cal-use-RMW-buffer.patch b/package/kernel/mac80211/patches/322-ath9k-ar9271_hw_pa_cal-use-RMW-buffer.patch +deleted file mode 100644 +index 7247369..0000000 +--- a/package/kernel/mac80211/patches/322-ath9k-ar9271_hw_pa_cal-use-RMW-buffer.patch ++++ /dev/null +@@ -1,48 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:49 +0100 +-Subject: [PATCH] ath9k: ar9271_hw_pa_cal: use RMW buffer +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c +-@@ -436,13 +436,14 @@ static void ar9271_hw_pa_cal(struct ath_ +- { AR9285_AN_RF2G2, 0 }, +- { AR9285_AN_TOP2, 0 }, +- { AR9285_AN_RF2G8, 0 }, +-- { AR9285_AN_RF2G7, 0 } , +-- { AR9285_AN_RF2G3, 0 } , +-+ { AR9285_AN_RF2G7, 0 }, +-+ { AR9285_AN_RF2G3, 0 }, +- }; +- +- for (i = 0; i < ARRAY_SIZE(regList); i++) +- regList[i][1] = REG_READ(ah, regList[i][0]); +- +-+ ENABLE_REG_RMW_BUFFER(ah); +- /* 7834, b1=0 */ +- REG_CLR_BIT(ah, AR9285_AN_RF2G6, 1 << 0); +- /* 9808, b27=1 */ +-@@ -476,6 +477,7 @@ static void ar9271_hw_pa_cal(struct ath_ +- REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); +- /* 7828, b0-11, ccom=fff */ +- REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); +-+ REG_RMW_BUFFER_FLUSH(ah); +- +- /* Set: +- * localmode=1,bmode=1,bmoderxtx=1,synthon=1, +-@@ -514,10 +516,12 @@ static void ar9271_hw_pa_cal(struct ath_ +- } +- +- +-+ ENABLE_REG_RMW_BUFFER(ah); +- /* 7834, b1=1 */ +- REG_SET_BIT(ah, AR9285_AN_RF2G6, 1 << 0); +- /* 9808, b27=0 */ +- REG_CLR_BIT(ah, 0x9808, 1 << 27); +-+ REG_RMW_BUFFER_FLUSH(ah); +- +- ENABLE_REGWRITE_BUFFER(ah); +- for (i = 0; i < ARRAY_SIZE(regList); i++) +diff --git a/package/kernel/mac80211/patches/322-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch b/package/kernel/mac80211/patches/322-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch +new file mode 100644 +index 0000000..2b61f4e +--- /dev/null ++++ b/package/kernel/mac80211/patches/322-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch +@@ -0,0 +1,92 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:14:56 +0200 ++Subject: [PATCH] brcmfmac: only call brcmf_cfg80211_detach() when attach ++ was successful ++ ++In brcmf_bus_start() the function brcmf_cfg80211_attach() is called which ++may fail. If this happens we should not call brcmf_cfg80211_detach() in ++the failure path as it will result in NULL pointer dereference: ++ ++ brcmf_fweh_activate_events: Set event_msgs error (-5) ++ brcmf_bus_start: failed: -5 ++ brcmf_sdio_firmware_callback: dongle is not responding ++ BUG: unable to handle kernel NULL pointer dereference at 0000000000000068 ++ IP: [] kernfs_find_ns+0x18/0xd0 ++ PGD 0 ++ Oops: 0000 [#1] SMP ++ Modules linked in: brcmfmac(O) brcmutil(O) cfg80211 auth_rpcgss ++ CPU: 1 PID: 45 Comm: kworker/1:1 Tainted: G O ++ Hardware name: Dell Inc. Latitude E6410/07XJP9, BIOS A07 02/15/2011 ++ Workqueue: events request_firmware_work_func ++ task: ffff880036c09ac0 ti: ffff880036dd4000 task.ti: ffff880036dd4000 ++ RIP: 0010:[] [] kernfs_find_ns+0x18/0xd0 ++ RSP: 0018:ffff880036dd7a28 EFLAGS: 00010246 ++ RAX: ffff880036c09ac0 RBX: 0000000000000000 RCX: 000000007fffffff ++ RDX: 0000000000000000 RSI: ffffffff816578b9 RDI: 0000000000000000 ++ RBP: ffff880036dd7a48 R08: 0000000000000000 R09: ffff880036c0b340 ++ R10: 00000000000002ec R11: ffff880036dd7b08 R12: ffffffff816578b9 ++ R13: 0000000000000000 R14: ffffffff816578b9 R15: ffff8800c6c87000 ++ FS: 0000000000000000(0000) GS:ffff88012bc40000(0000) knlGS:0000000000000000 ++ CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b ++ CR2: 0000000000000068 CR3: 0000000001a0b000 CR4: 00000000000006e0 ++ Stack: ++ 0000000000000000 ffffffff816578b9 0000000000000000 ffff8800c0d003c8 ++ ffff880036dd7a78 ffffffff811e8ff5 0000000ffffffff1 ffffffff81a9b060 ++ ffff8800c789f880 ffff8800c0d00000 ffff880036dd7a98 ffffffff811ebe0d ++ Call Trace: ++ [] kernfs_find_and_get_ns+0x35/0x60 ++ [] sysfs_unmerge_group+0x1d/0x60 ++ [] dpm_sysfs_remove+0x22/0x60 ++ [] device_del+0x49/0x240 ++ [] rfkill_unregister+0x58/0xc0 ++ [] wiphy_unregister+0xab/0x2f0 [cfg80211] ++ [] brcmf_cfg80211_detach+0x23/0x50 [brcmfmac] ++ [] brcmf_detach+0x86/0xe0 [brcmfmac] ++ [] brcmf_sdio_remove+0x48/0x120 [brcmfmac] ++ [] brcmf_sdiod_remove+0x29/0xd0 [brcmfmac] ++ [] brcmf_ops_sdio_remove+0xb1/0x110 [brcmfmac] ++ [] sdio_bus_remove+0x37/0x100 [mmc_core] ++ [] __device_release_driver+0x96/0x130 ++ [] device_release_driver+0x23/0x30 ++ [] brcmf_sdio_firmware_callback+0x2a8/0x5d0 [brcmfmac] ++ [] brcmf_fw_request_nvram_done+0x15f/0x5e0 [brcmfmac] ++ [] ? devres_add+0x3f/0x50 ++ [] ? usermodehelper_read_unlock+0x15/0x20 ++ [] ? platform_match+0x70/0xa0 ++ [] request_firmware_work_func+0x30/0x60 ++ [] process_one_work+0x14c/0x3d0 ++ [] worker_thread+0x11a/0x450 ++ [] ? process_one_work+0x3d0/0x3d0 ++ [] kthread+0xd2/0xf0 ++ [] ? kthread_create_on_node+0x180/0x180 ++ [] ret_from_fork+0x3f/0x70 ++ [] ? kthread_create_on_node+0x180/0x180 ++ Code: e9 40 fe ff ff 48 89 d8 eb 87 66 0f 1f 84 00 00 00 00 00 66 66 66 66 ++ 90 55 48 89 e5 41 56 49 89 f6 41 55 49 89 d5 31 d2 41 54 53 <0f> b7 ++ 47 68 48 8b 5f 48 66 c1 e8 05 83 e0 01 4d 85 ed 0f b6 c8 ++ RIP [] kernfs_find_ns+0x18/0xd0 ++ RSP ++ CR2: 0000000000000068 ++ ---[ end trace 87d6ec0d3fe46740 ]--- ++ ++Reported-by: Daniel (Deognyoun) Kim ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c ++@@ -1049,7 +1049,10 @@ int brcmf_bus_start(struct device *dev) ++ fail: ++ if (ret < 0) { ++ brcmf_err("failed: %d\n", ret); ++- brcmf_cfg80211_detach(drvr->config); +++ if (drvr->config) { +++ brcmf_cfg80211_detach(drvr->config); +++ drvr->config = NULL; +++ } ++ if (drvr->fws) { ++ brcmf_fws_del_interface(ifp); ++ brcmf_fws_deinit(drvr); +diff --git a/package/kernel/mac80211/patches/323-ath9k-add-multi_read-to-be-compatible-with-ath9k_htc.patch b/package/kernel/mac80211/patches/323-ath9k-add-multi_read-to-be-compatible-with-ath9k_htc.patch +deleted file mode 100644 +index 246bb9d..0000000 +--- a/package/kernel/mac80211/patches/323-ath9k-add-multi_read-to-be-compatible-with-ath9k_htc.patch ++++ /dev/null +@@ -1,35 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:50 +0100 +-Subject: [PATCH] ath9k: add multi_read to be compatible with ath9k_htc +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/init.c +-+++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -141,6 +141,16 @@ static unsigned int ath9k_ioread32(void +- return val; +- } +- +-+static void ath9k_multi_ioread32(void *hw_priv, u32 *addr, +-+ u32 *val, u16 count) +-+{ +-+ int i; +-+ +-+ for (i = 0; i < count; i++) +-+ val[i] = ath9k_ioread32(hw_priv, addr[i]); +-+} +-+ +-+ +- static unsigned int __ath9k_reg_rmw(struct ath_softc *sc, u32 reg_offset, +- u32 set, u32 clr) +- { +-@@ -530,6 +540,7 @@ static int ath9k_init_softc(u16 devid, s +- ah->hw = sc->hw; +- ah->hw_version.devid = devid; +- ah->reg_ops.read = ath9k_ioread32; +-+ ah->reg_ops.multi_read = ath9k_multi_ioread32; +- ah->reg_ops.write = ath9k_iowrite32; +- ah->reg_ops.rmw = ath9k_reg_rmw; +- pCap = &ah->caps; +diff --git a/package/kernel/mac80211/patches/323-brcmfmac-correct-detection-of-p2pdev-interface-event.patch b/package/kernel/mac80211/patches/323-brcmfmac-correct-detection-of-p2pdev-interface-event.patch +new file mode 100644 +index 0000000..868b0a8 +--- /dev/null ++++ b/package/kernel/mac80211/patches/323-brcmfmac-correct-detection-of-p2pdev-interface-event.patch +@@ -0,0 +1,105 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:14:57 +0200 ++Subject: [PATCH] brcmfmac: correct detection of p2pdev interface event ++ ++The p2pdev interface is setup in firmware resulting in a interface ++event. This event has role and no-if flag. When role is p2p client ++and no-if flag is set it indicates that this is the p2pdev interface. ++This info is used in handling the event and adding interface in the ++driver. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c ++@@ -795,7 +795,7 @@ fail: ++ } ++ ++ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, ++- char *name, u8 *mac_addr) +++ bool is_p2pdev, char *name, u8 *mac_addr) ++ { ++ struct brcmf_if *ifp; ++ struct net_device *ndev; ++@@ -821,7 +821,7 @@ struct brcmf_if *brcmf_add_if(struct brc ++ } ++ } ++ ++- if (!brcmf_p2p_enable && bssidx == 1) { +++ if (!brcmf_p2p_enable && is_p2pdev) { ++ /* this is P2P_DEVICE interface */ ++ brcmf_dbg(INFO, "allocate non-netdev interface\n"); ++ ifp = kzalloc(sizeof(*ifp), GFP_KERNEL); ++@@ -999,12 +999,12 @@ int brcmf_bus_start(struct device *dev) ++ brcmf_dbg(TRACE, "\n"); ++ ++ /* add primary networking interface */ ++- ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL); +++ ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL); ++ if (IS_ERR(ifp)) ++ return PTR_ERR(ifp); ++ ++ if (brcmf_p2p_enable) ++- p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL); +++ p2p_ifp = brcmf_add_if(drvr, 1, 0, false, "p2p%d", NULL); ++ else ++ p2p_ifp = NULL; ++ if (IS_ERR(p2p_ifp)) ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h ++@@ -205,7 +205,7 @@ char *brcmf_ifname(struct brcmf_pub *drv ++ 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 bssidx, s32 ifidx, ++- char *name, u8 *mac_addr); +++ bool is_p2pdev, char *name, u8 *mac_addr); ++ void brcmf_remove_interface(struct brcmf_if *ifp); ++ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); ++ void brcmf_txflowblock_if(struct brcmf_if *ifp, ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c ++@@ -179,6 +179,7 @@ static void brcmf_fweh_handle_if_event(s ++ { ++ struct brcmf_if_event *ifevent = data; ++ struct brcmf_if *ifp; +++ bool is_p2pdev; ++ int err = 0; ++ ++ brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n", ++@@ -186,18 +187,16 @@ static void brcmf_fweh_handle_if_event(s ++ ifevent->flags, ifevent->role); ++ ++ /* The P2P Device interface event must not be ignored ++- * contrary to what firmware tells us. The only way to ++- * distinguish the P2P Device is by looking at the ifidx ++- * and bssidx received. +++ * contrary to what firmware tells us. ++ */ ++- if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) && ++- (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { +++ is_p2pdev = (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) && +++ ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT; +++ if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { ++ brcmf_dbg(EVENT, "event can be ignored\n"); ++ return; ++ } ++ if (ifevent->ifidx >= BRCMF_MAX_IFS) { ++- brcmf_err("invalid interface index: %u\n", ++- ifevent->ifidx); +++ brcmf_err("invalid interface index: %u\n", ifevent->ifidx); ++ return; ++ } ++ ++@@ -207,7 +206,7 @@ static void brcmf_fweh_handle_if_event(s ++ brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname, ++ emsg->addr); ++ ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx, ++- emsg->ifname, emsg->addr); +++ is_p2pdev, emsg->ifname, emsg->addr); ++ if (IS_ERR(ifp)) ++ return; ++ brcmf_fws_add_interface(ifp); +diff --git a/package/kernel/mac80211/patches/324-ath9k-add-new-function-ath9k_hw_read_array.patch b/package/kernel/mac80211/patches/324-ath9k-add-new-function-ath9k_hw_read_array.patch +deleted file mode 100644 +index 2eda1c9..0000000 +--- a/package/kernel/mac80211/patches/324-ath9k-add-new-function-ath9k_hw_read_array.patch ++++ /dev/null +@@ -1,69 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:51 +0100 +-Subject: [PATCH] ath9k: add new function ath9k_hw_read_array +- +-REG_READ generate most overhead on usb bus. It send and read micro packages +-and reduce usb bandwidth. To reduce this overhead we should read in batches. +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/hw.c +-+++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -121,6 +121,36 @@ void ath9k_hw_write_array(struct ath_hw +- REGWRITE_BUFFER_FLUSH(ah); +- } +- +-+void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size) +-+{ +-+ u32 *tmp_reg_list, *tmp_data; +-+ int i; +-+ +-+ tmp_reg_list = kmalloc(size * sizeof(u32), GFP_KERNEL); +-+ if (!tmp_reg_list) { +-+ dev_err(ah->dev, "%s: tmp_reg_list: alloc filed\n", __func__); +-+ return; +-+ } +-+ +-+ tmp_data = kmalloc(size * sizeof(u32), GFP_KERNEL); +-+ if (!tmp_data) { +-+ dev_err(ah->dev, "%s tmp_data: alloc filed\n", __func__); +-+ goto error_tmp_data; +-+ } +-+ +-+ for (i = 0; i < size; i++) +-+ tmp_reg_list[i] = array[i][0]; +-+ +-+ REG_READ_MULTI(ah, tmp_reg_list, tmp_data, size); +-+ +-+ for (i = 0; i < size; i++) +-+ array[i][1] = tmp_data[i]; +-+ +-+ kfree(tmp_data); +-+error_tmp_data: +-+ kfree(tmp_reg_list); +-+} +-+ +- u32 ath9k_hw_reverse_bits(u32 val, u32 n) +- { +- u32 retval; +---- a/drivers/net/wireless/ath/ath9k/hw.h +-+++ b/drivers/net/wireless/ath/ath9k/hw.h +-@@ -138,6 +138,8 @@ +- +- #define REG_WRITE_ARRAY(iniarray, column, regWr) \ +- ath9k_hw_write_array(ah, iniarray, column, &(regWr)) +-+#define REG_READ_ARRAY(ah, array, size) \ +-+ ath9k_hw_read_array(ah, array, size) +- +- #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 +- #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 +-@@ -1020,6 +1022,7 @@ void ath9k_hw_synth_delay(struct ath_hw +- bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); +- void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array, +- int column, unsigned int *writecnt); +-+void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size); +- u32 ath9k_hw_reverse_bits(u32 val, u32 n); +- u16 ath9k_hw_computetxtime(struct ath_hw *ah, +- u8 phy, int kbps, +diff --git a/package/kernel/mac80211/patches/324-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch b/package/kernel/mac80211/patches/324-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch +new file mode 100644 +index 0000000..abd6681 +--- /dev/null ++++ b/package/kernel/mac80211/patches/324-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch +@@ -0,0 +1,126 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:14:58 +0200 ++Subject: [PATCH] brcmfmac: use brcmf_get_ifp() to map ifidx to struct ++ brcmf_if instance ++ ++The knowledge on how to map the interface index to a struct brcmf_if ++instance is in brcmf_get_ifp() so use that function when only the ++interface index is known instead of accessing brcmf_pub::iflist ++directly. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c ++@@ -149,7 +149,7 @@ static s32 brcmf_btcoex_params_read(stru ++ static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci, ++ bool trump_sco) ++ { ++- struct brcmf_if *ifp = btci->cfg->pub->iflist[0]; +++ struct brcmf_if *ifp = brcmf_get_ifp(btci->cfg->pub, 0); ++ ++ if (trump_sco && !btci->saved_regs_part2) { ++ /* this should reduce eSCO agressive ++@@ -468,7 +468,7 @@ int brcmf_btcoex_set_mode(struct brcmf_c ++ { ++ struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy); ++ struct brcmf_btcoex_info *btci = cfg->btcoex; ++- struct brcmf_if *ifp = cfg->pub->iflist[0]; +++ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); ++ ++ switch (mode) { ++ case BRCMF_BTCOEX_DISABLED: ++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++@@ -6213,7 +6213,7 @@ static void brcmf_free_wiphy(struct wiph ++ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, ++ struct device *busdev) ++ { ++- struct net_device *ndev = drvr->iflist[0]->ndev; +++ struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev; ++ struct brcmf_cfg80211_info *cfg; ++ struct wiphy *wiphy; ++ struct brcmf_cfg80211_vif *vif; ++--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c ++@@ -121,7 +121,7 @@ static void brcmf_feat_iovar_int_set(str ++ ++ void brcmf_feat_attach(struct brcmf_pub *drvr) ++ { ++- struct brcmf_if *ifp = drvr->iflist[0]; +++ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); ++ ++ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan"); ++ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn"); ++--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c ++@@ -221,7 +221,7 @@ static void brcmf_flowring_block(struct ++ ++ bus_if = dev_get_drvdata(flow->dev); ++ drvr = bus_if->drvr; ++- ifp = drvr->iflist[ifidx]; +++ ifp = brcmf_get_ifp(drvr, ifidx); ++ brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked); ++ ++ spin_unlock_irqrestore(&flow->block_lock, flags); ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c ++@@ -334,7 +334,7 @@ void brcmf_fweh_attach(struct brcmf_pub ++ void brcmf_fweh_detach(struct brcmf_pub *drvr) ++ { ++ struct brcmf_fweh_info *fweh = &drvr->fweh; ++- struct brcmf_if *ifp = drvr->iflist[0]; +++ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); ++ s8 eventmask[BRCMF_EVENTING_MASK_LEN]; ++ ++ if (ifp) { ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c ++@@ -972,7 +972,7 @@ static void ++ brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq, ++ u8 if_id) ++ { ++- struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1]; +++ struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id); ++ ++ if (WARN_ON(!ifp)) ++ return; ++@@ -2118,6 +2118,7 @@ static int brcmf_debugfs_fws_stats_read( ++ int brcmf_fws_init(struct brcmf_pub *drvr) ++ { ++ struct brcmf_fws_info *fws; +++ struct brcmf_if *ifp; ++ u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; ++ int rc; ++ u32 mode; ++@@ -2177,21 +2178,22 @@ int brcmf_fws_init(struct brcmf_pub *drv ++ * continue. Set mode back to none indicating not enabled. ++ */ ++ fws->fw_signals = true; ++- if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) { +++ ifp = brcmf_get_ifp(drvr, 0); +++ if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) { ++ brcmf_err("failed to set bdcv2 tlv signaling\n"); ++ fws->fcmode = BRCMF_FWS_FCMODE_NONE; ++ fws->fw_signals = false; ++ } ++ ++- if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1)) +++ if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1)) ++ brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n"); ++ ++ /* Enable seq number reuse, if supported */ ++- if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) { +++ if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) { ++ if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) { ++ mode = 0; ++ BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1); ++- if (brcmf_fil_iovar_int_set(drvr->iflist[0], +++ if (brcmf_fil_iovar_int_set(ifp, ++ "wlfc_mode", mode) == 0) { ++ BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1); ++ } +diff --git a/package/kernel/mac80211/patches/325-ath9k-ar9271_hw_pa_cal-use-REG_READ_ARRAY.patch b/package/kernel/mac80211/patches/325-ath9k-ar9271_hw_pa_cal-use-REG_READ_ARRAY.patch +deleted file mode 100644 +index 4e4888f..0000000 +--- a/package/kernel/mac80211/patches/325-ath9k-ar9271_hw_pa_cal-use-REG_READ_ARRAY.patch ++++ /dev/null +@@ -1,24 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:52 +0100 +-Subject: [PATCH] ath9k: ar9271_hw_pa_cal: use REG_READ_ARRAY +- +-insted of reading each register separatly +-and waste 4ms on each operation, we can +-use one shot read. +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c +-@@ -440,8 +440,7 @@ static void ar9271_hw_pa_cal(struct ath_ +- { AR9285_AN_RF2G3, 0 }, +- }; +- +-- for (i = 0; i < ARRAY_SIZE(regList); i++) +-- regList[i][1] = REG_READ(ah, regList[i][0]); +-+ REG_READ_ARRAY(ah, regList, ARRAY_SIZE(regList)); +- +- ENABLE_REG_RMW_BUFFER(ah); +- /* 7834, b1=0 */ +diff --git a/package/kernel/mac80211/patches/325-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch b/package/kernel/mac80211/patches/325-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch +new file mode 100644 +index 0000000..23a7b6f +--- /dev/null ++++ b/package/kernel/mac80211/patches/325-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch +@@ -0,0 +1,122 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:14:59 +0200 ++Subject: [PATCH] brcmfmac: pass struct brcmf_if instance in ++ brcmf_txfinalize() ++ ++Most call sites of brcmf_txfinalize already have struct brcmf_if ++instance so pass that to brcmf_txfinalize() as the function ++needs it anyway. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c ++@@ -560,17 +560,11 @@ void brcmf_rx_frame(struct device *dev, ++ brcmf_netif_rx(ifp, skb); ++ } ++ ++-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, ++- bool success) +++void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success) ++ { ++- struct brcmf_if *ifp; ++ struct ethhdr *eh; ++ u16 type; ++ ++- ifp = drvr->iflist[ifidx]; ++- if (!ifp) ++- goto done; ++- ++ eh = (struct ethhdr *)(txp->data); ++ type = ntohs(eh->h_proto); ++ ++@@ -582,7 +576,7 @@ void brcmf_txfinalize(struct brcmf_pub * ++ ++ if (!success) ++ ifp->stats.tx_errors++; ++-done: +++ ++ brcmu_pkt_buf_free_skb(txp); ++ } ++ ++@@ -600,7 +594,7 @@ void brcmf_txcomplete(struct device *dev ++ if (brcmf_proto_hdrpull(drvr, false, txp, &ifp)) ++ brcmu_pkt_buf_free_skb(txp); ++ else ++- brcmf_txfinalize(drvr, txp, ifp->ifidx, success); +++ brcmf_txfinalize(ifp, txp, success); ++ } ++ } ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h ++@@ -210,8 +210,7 @@ void brcmf_remove_interface(struct brcmf ++ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); ++ void brcmf_txflowblock_if(struct brcmf_if *ifp, ++ enum brcmf_netif_stop_reason reason, bool state); ++-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, ++- bool success); +++void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); ++ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); ++ ++ /* Sets dongle media info (drv_version, mac address). */ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c ++@@ -1506,7 +1506,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i ++ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx, ++ genbit, seq); ++ if (remove_from_hanger || ret) ++- brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true); +++ brcmf_txfinalize(ifp, skb, true); ++ ++ return 0; ++ } ++@@ -1905,7 +1905,7 @@ int brcmf_fws_process_skb(struct brcmf_i ++ if (fws->avoid_queueing) { ++ rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb); ++ if (rc < 0) ++- brcmf_txfinalize(drvr, skb, ifp->ifidx, false); +++ brcmf_txfinalize(ifp, skb, false); ++ return rc; ++ } ++ ++@@ -1929,7 +1929,7 @@ int brcmf_fws_process_skb(struct brcmf_i ++ brcmf_fws_schedule_deq(fws); ++ } else { ++ brcmf_err("drop skb: no hanger slot\n"); ++- brcmf_txfinalize(drvr, skb, ifp->ifidx, false); +++ brcmf_txfinalize(ifp, skb, false); ++ rc = -ENOMEM; ++ } ++ brcmf_fws_unlock(fws); ++@@ -2009,8 +2009,9 @@ static void brcmf_fws_dequeue_worker(str ++ ret = brcmf_proto_txdata(drvr, ifidx, 0, skb); ++ brcmf_fws_lock(fws); ++ if (ret < 0) ++- brcmf_txfinalize(drvr, skb, ifidx, ++- false); +++ brcmf_txfinalize(brcmf_get_ifp(drvr, +++ ifidx), +++ skb, false); ++ if (fws->bus_flow_blocked) ++ break; ++ } ++--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c ++@@ -873,7 +873,11 @@ brcmf_msgbuf_process_txstatus(struct brc ++ commonring = msgbuf->flowrings[flowid]; ++ atomic_dec(&commonring->outstanding_tx); ++ ++- brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true); +++ /* Hante: i believe this was a bug as tx_status->msg.ifidx was used +++ * in brcmf_txfinalize as index in drvr->iflist. Can you confirm/deny? +++ */ +++ brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx), +++ skb, true); ++ } ++ ++ +diff --git a/package/kernel/mac80211/patches/326-ath9k-use-one-shot-read-in-ath9k_hw_update_mibstats.patch b/package/kernel/mac80211/patches/326-ath9k-use-one-shot-read-in-ath9k_hw_update_mibstats.patch +deleted file mode 100644 +index a22cd1d..0000000 +--- a/package/kernel/mac80211/patches/326-ath9k-use-one-shot-read-in-ath9k_hw_update_mibstats.patch ++++ /dev/null +@@ -1,39 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:53 +0100 +-Subject: [PATCH] ath9k: use one shot read in ath9k_hw_update_mibstats +- +-this will reduce some overhead on usb bus. +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/ani.c +-+++ b/drivers/net/wireless/ath/ath9k/ani.c +-@@ -107,11 +107,21 @@ static const struct ani_cck_level_entry +- static void ath9k_hw_update_mibstats(struct ath_hw *ah, +- struct ath9k_mib_stats *stats) +- { +-- stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL); +-- stats->rts_bad += REG_READ(ah, AR_RTS_FAIL); +-- stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL); +-- stats->rts_good += REG_READ(ah, AR_RTS_OK); +-- stats->beacons += REG_READ(ah, AR_BEACON_CNT); +-+ u32 addr[5] = {AR_RTS_OK, AR_RTS_FAIL, AR_ACK_FAIL, +-+ AR_FCS_FAIL, AR_BEACON_CNT}; +-+ u32 data[5]; +-+ +-+ REG_READ_MULTI(ah, &addr[0], &data[0], 5); +-+ /* AR_RTS_OK */ +-+ stats->rts_good += data[0]; +-+ /* AR_RTS_FAIL */ +-+ stats->rts_bad += data[1]; +-+ /* AR_ACK_FAIL */ +-+ stats->ackrcv_bad += data[2]; +-+ /* AR_FCS_FAIL */ +-+ stats->fcs_bad += data[3]; +-+ /* AR_BEACON_CNT */ +-+ stats->beacons += data[4]; +- } +- +- static void ath9k_ani_restart(struct ath_hw *ah) +diff --git a/package/kernel/mac80211/patches/326-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch b/package/kernel/mac80211/patches/326-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch +new file mode 100644 +index 0000000..8ddc0a6 +--- /dev/null ++++ b/package/kernel/mac80211/patches/326-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch +@@ -0,0 +1,92 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:15:00 +0200 ++Subject: [PATCH] brcmfmac: add mapping for interface index to bsscfg ++ index ++ ++Because the P2P Device interface in firmware uses the same interface ++index as the primary interface we use the bsscfg index as index in the ++struct brcmf_pub::iflist. However, in the data path we get the interface ++index and not the bsscfg index. So we need a mapping of interface index ++to bsscfg index, which can be determined upon handle adding the interface. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c ++@@ -85,21 +85,20 @@ char *brcmf_ifname(struct brcmf_pub *drv ++ ++ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) ++ { +++ struct brcmf_if *ifp; +++ s32 bssidx; +++ ++ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { ++ brcmf_err("ifidx %d out of range\n", ifidx); ++ return NULL; ++ } ++ ++- /* The ifidx is the idx to map to matching netdev/ifp. When receiving ++- * events this is easy because it contains the bssidx which maps ++- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. ++- * bssidx 1 is used for p2p0 and no data can be received or ++- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 ++- */ ++- if (ifidx) ++- ifidx++; +++ ifp = NULL; +++ bssidx = drvr->if2bss[ifidx]; +++ if (bssidx >= 0) +++ ifp = drvr->iflist[bssidx]; ++ ++- return drvr->iflist[ifidx]; +++ return ifp; ++ } ++ ++ static void _brcmf_set_multicast_list(struct work_struct *work) ++@@ -831,6 +830,8 @@ struct brcmf_if *brcmf_add_if(struct brc ++ ++ ifp = netdev_priv(ndev); ++ ifp->ndev = ndev; +++ /* store mapping ifidx to bssidx */ +++ drvr->if2bss[ifidx] = bssidx; ++ } ++ ++ ifp->drvr = drvr; ++@@ -855,6 +856,7 @@ static void brcmf_del_if(struct brcmf_pu ++ struct brcmf_if *ifp; ++ ++ ifp = drvr->iflist[bssidx]; +++ drvr->if2bss[ifp->ifidx] = -1; ++ drvr->iflist[bssidx] = NULL; ++ if (!ifp) { ++ brcmf_err("Null interface, idx=%d\n", bssidx); ++@@ -862,6 +864,7 @@ static void brcmf_del_if(struct brcmf_pu ++ } ++ brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx); ++ if (ifp->ndev) { +++ drvr->if2bss[ifp->ifidx] = -1; ++ if (bssidx == 0) { ++ if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { ++ rtnl_lock(); ++@@ -926,6 +929,7 @@ int brcmf_attach(struct device *dev) ++ if (!drvr) ++ return -ENOMEM; ++ +++ memset(drvr->if2bss, 0xFF, sizeof(drvr->if2bss)); ++ mutex_init(&drvr->proto_block); ++ ++ /* Link to bus module */ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h ++@@ -122,6 +122,7 @@ struct brcmf_pub { ++ struct mac_address addresses[BRCMF_MAX_IFS]; ++ ++ struct brcmf_if *iflist[BRCMF_MAX_IFS]; +++ s32 if2bss[BRCMF_MAX_IFS]; ++ ++ struct mutex proto_block; ++ unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; +diff --git a/package/kernel/mac80211/patches/327-ath9k-ath9k_hw_loadnf-use-REG_RMW.patch b/package/kernel/mac80211/patches/327-ath9k-ath9k_hw_loadnf-use-REG_RMW.patch +deleted file mode 100644 +index e5a362f..0000000 +--- a/package/kernel/mac80211/patches/327-ath9k-ath9k_hw_loadnf-use-REG_RMW.patch ++++ /dev/null +@@ -1,71 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:54 +0100 +-Subject: [PATCH] ath9k: ath9k_hw_loadnf: use REG_RMW +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/calib.c +-+++ b/drivers/net/wireless/ath/ath9k/calib.c +-@@ -238,7 +238,6 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s +- { +- struct ath9k_nfcal_hist *h = NULL; +- unsigned i, j; +-- int32_t val; +- u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; +- struct ath_common *common = ath9k_hw_common(ah); +- s16 default_nf = ath9k_hw_get_default_nf(ah, chan); +-@@ -246,6 +245,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s +- if (ah->caldata) +- h = ah->caldata->nfCalHist; +- +-+ ENABLE_REG_RMW_BUFFER(ah); +- for (i = 0; i < NUM_NF_READINGS; i++) { +- if (chainmask & (1 << i)) { +- s16 nfval; +-@@ -258,10 +258,8 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s +- else +- nfval = default_nf; +- +-- val = REG_READ(ah, ah->nf_regs[i]); +-- val &= 0xFFFFFE00; +-- val |= (((u32) nfval << 1) & 0x1ff); +-- REG_WRITE(ah, ah->nf_regs[i], val); +-+ REG_RMW(ah, ah->nf_regs[i], +-+ (((u32) nfval << 1) & 0x1ff), 0x1ff); +- } +- } +- +-@@ -274,6 +272,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s +- REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, +- AR_PHY_AGC_CONTROL_NO_UPDATE_NF); +- REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); +-+ REG_RMW_BUFFER_FLUSH(ah); +- +- /* +- * Wait for load to complete, should be fast, a few 10s of us. +-@@ -309,19 +308,17 @@ int ath9k_hw_loadnf(struct ath_hw *ah, s +- * by the median we just loaded. This will be initial (and max) value +- * of next noise floor calibration the baseband does. +- */ +-- ENABLE_REGWRITE_BUFFER(ah); +-+ ENABLE_REG_RMW_BUFFER(ah); +- for (i = 0; i < NUM_NF_READINGS; i++) { +- if (chainmask & (1 << i)) { +- if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan)) +- continue; +- +-- val = REG_READ(ah, ah->nf_regs[i]); +-- val &= 0xFFFFFE00; +-- val |= (((u32) (-50) << 1) & 0x1ff); +-- REG_WRITE(ah, ah->nf_regs[i], val); +-+ REG_RMW(ah, ah->nf_regs[i], +-+ (((u32) (-50) << 1) & 0x1ff), 0x1ff); +- } +- } +-- REGWRITE_BUFFER_FLUSH(ah); +-+ REG_RMW_BUFFER_FLUSH(ah); +- +- return 0; +- } +diff --git a/package/kernel/mac80211/patches/327-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch b/package/kernel/mac80211/patches/327-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch +new file mode 100644 +index 0000000..a0a798b +--- /dev/null ++++ b/package/kernel/mac80211/patches/327-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch +@@ -0,0 +1,103 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:15:01 +0200 ++Subject: [PATCH] brcmfmac: add dedicated debug level for firmware ++ console logging ++ ++Both PCIe and SDIO devices have the possibility to log the firmware ++console output in kernel log. For PCIe it is logged when PCIE debug ++level is enabled. For SDIO it is logged when user specifies a non-zero ++console interval through debugfs. This patch tries to make it a ++bit more consistent. The firmware console output is only logged when ++FWCON debug level is enabled. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Reviewed-by: Pontus Fuchs ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h ++@@ -37,6 +37,7 @@ ++ #define BRCMF_SDIO_VAL 0x00020000 ++ #define BRCMF_MSGBUF_VAL 0x00040000 ++ #define BRCMF_PCIE_VAL 0x00080000 +++#define BRCMF_FWCON_VAL 0x00100000 ++ ++ /* set default print format */ ++ #undef pr_fmt ++@@ -78,6 +79,7 @@ do { \ ++ #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) ++ #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) ++ #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) +++#define BRCMF_FWCON_ON() (brcmf_msg_level & BRCMF_FWCON_VAL) ++ ++ #else /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */ ++ ++@@ -90,6 +92,7 @@ do { \ ++ #define BRCMF_GLOM_ON() 0 ++ #define BRCMF_EVENT_ON() 0 ++ #define BRCMF_FIL_ON() 0 +++#define BRCMF_FWCON_ON() 0 ++ ++ #endif /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */ ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c ++@@ -644,7 +644,7 @@ static void brcmf_pcie_bus_console_init( ++ addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET; ++ console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr); ++ ++- brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n", +++ brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n", ++ console->base_addr, console->buf_addr, console->bufsize); ++ } ++ ++@@ -656,6 +656,9 @@ static void brcmf_pcie_bus_console_read( ++ u8 ch; ++ u32 newidx; ++ +++ if (!BRCMF_FWCON_ON()) +++ return; +++ ++ console = &devinfo->shared.console; ++ addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET; ++ newidx = brcmf_pcie_read_tcm32(devinfo, addr); ++@@ -677,7 +680,7 @@ static void brcmf_pcie_bus_console_read( ++ } ++ if (ch == '\n') { ++ console->log_str[console->log_idx] = 0; ++- brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str); +++ pr_debug("CONSOLE: %s", console->log_str); ++ console->log_idx = 0; ++ } ++ } ++--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c ++@@ -123,6 +123,7 @@ struct rte_console { ++ ++ #define BRCMF_FIRSTREAD (1 << 6) ++ +++#define BRCMF_CONSOLE 10 /* watchdog interval to poll console */ ++ ++ /* SBSDIO_DEVICE_CTL */ ++ ++@@ -3204,6 +3205,8 @@ static void brcmf_sdio_debugfs_create(st ++ if (IS_ERR_OR_NULL(dentry)) ++ return; ++ +++ bus->console_interval = BRCMF_CONSOLE; +++ ++ brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read); ++ brcmf_debugfs_add_entry(drvr, "counters", ++ brcmf_debugfs_sdio_count_read); ++@@ -3613,7 +3616,7 @@ static void brcmf_sdio_bus_watchdog(stru ++ } ++ #ifdef DEBUG ++ /* Poll for console output periodically */ ++- if (bus->sdiodev->state == BRCMF_SDIOD_DATA && +++ if (bus->sdiodev->state == BRCMF_SDIOD_DATA && BRCMF_FWCON_ON() && ++ bus->console_interval != 0) { ++ bus->console.count += BRCMF_WD_POLL_MS; ++ if (bus->console.count >= bus->console_interval) { +diff --git a/package/kernel/mac80211/patches/328-ath9k-write-buffer-related-optimisation-in-ar5008_hw.patch b/package/kernel/mac80211/patches/328-ath9k-write-buffer-related-optimisation-in-ar5008_hw.patch +deleted file mode 100644 +index 01c8011..0000000 +--- a/package/kernel/mac80211/patches/328-ath9k-write-buffer-related-optimisation-in-ar5008_hw.patch ++++ /dev/null +@@ -1,27 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:55 +0100 +-Subject: [PATCH] ath9k: write buffer related optimisation in +- ar5008_hw_set_channel_regs +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +-@@ -681,12 +681,13 @@ static void ar5008_hw_set_channel_regs(s +- phymode |= AR_PHY_FC_DYN2040_PRI_CH; +- +- } +-+ ENABLE_REGWRITE_BUFFER(ah); +- REG_WRITE(ah, AR_PHY_TURBO, phymode); +- +-+ /* This function do only REG_WRITE, so +-+ * we can include it to REGWRITE_BUFFER. */ +- ath9k_hw_set11nmac2040(ah, chan); +- +-- ENABLE_REGWRITE_BUFFER(ah); +-- +- REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); +- REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); +- +diff --git a/package/kernel/mac80211/patches/328-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch b/package/kernel/mac80211/patches/328-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch +new file mode 100644 +index 0000000..53e7ede +--- /dev/null ++++ b/package/kernel/mac80211/patches/328-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch +@@ -0,0 +1,34 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:15:02 +0200 ++Subject: [PATCH] brcmfmac: remove ifidx parameter from ++ brcmf_fws_txstatus_suppressed() ++ ++The brcmf_fws_txstatus_suppressed() function prototype specifies an ++ifidx parameter which is not used within the function implementation. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c ++@@ -1398,7 +1398,7 @@ done: ++ } ++ ++ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, ++- struct sk_buff *skb, u8 ifidx, +++ struct sk_buff *skb, ++ u32 genbit, u16 seq) ++ { ++ struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; ++@@ -1503,7 +1503,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i ++ return -EINVAL; ++ } ++ if (!remove_from_hanger) ++- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx, +++ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ++ genbit, seq); ++ if (remove_from_hanger || ret) ++ brcmf_txfinalize(ifp, skb, true); +diff --git a/package/kernel/mac80211/patches/329-ath9k-ath9k_hw_set_4k_power_cal_tabl-use-rmw-buffer.patch b/package/kernel/mac80211/patches/329-ath9k-ath9k_hw_set_4k_power_cal_tabl-use-rmw-buffer.patch +deleted file mode 100644 +index e5219f2..0000000 +--- a/package/kernel/mac80211/patches/329-ath9k-ath9k_hw_set_4k_power_cal_tabl-use-rmw-buffer.patch ++++ /dev/null +@@ -1,26 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:56 +0100 +-Subject: [PATCH] ath9k: ath9k_hw_set_4k_power_cal_tabl: use rmw buffer +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +-@@ -389,6 +389,7 @@ static void ath9k_hw_set_4k_power_cal_ta +- } +- } +- +-+ ENABLE_REG_RMW_BUFFER(ah); +- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, +- (numXpdGain - 1) & 0x3); +- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, +-@@ -396,6 +397,7 @@ static void ath9k_hw_set_4k_power_cal_ta +- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, +- xpdGainValues[1]); +- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); +-+ REG_RMW_BUFFER_FLUSH(ah); +- +- for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { +- regChainOffset = i * 0x1000; +diff --git a/package/kernel/mac80211/patches/329-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch b/package/kernel/mac80211/patches/329-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch +new file mode 100644 +index 0000000..bb05235 +--- /dev/null ++++ b/package/kernel/mac80211/patches/329-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch +@@ -0,0 +1,97 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:15:03 +0200 ++Subject: [PATCH] brcmfmac: change prototype for brcmf_fws_hdrpull() ++ ++Instead of passing ifidx and drvr just pass struct brcmf_if pointer ++which holds both parameters. ++ ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c ++@@ -312,8 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu ++ ++ skb_pull(pktbuf, BCDC_HEADER_LEN); ++ if (do_fws) ++- brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2, ++- pktbuf); +++ brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf); ++ else ++ skb_pull(pktbuf, h->data_offset << 2); ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c ++@@ -1616,11 +1616,10 @@ static int brcmf_fws_notify_bcmc_credit_ ++ return 0; ++ } ++ ++-int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, ++- struct sk_buff *skb) +++void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb) ++ { ++ struct brcmf_skb_reorder_data *rd; ++- struct brcmf_fws_info *fws = drvr->fws; +++ struct brcmf_fws_info *fws = ifp->drvr->fws; ++ u8 *signal_data; ++ s16 data_len; ++ u8 type; ++@@ -1630,20 +1629,20 @@ int brcmf_fws_hdrpull(struct brcmf_pub * ++ s32 err; ++ ++ brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n", ++- ifidx, skb->len, signal_len); +++ ifp->ifidx, skb->len, siglen); ++ ++- WARN_ON(signal_len > skb->len); +++ WARN_ON(siglen > skb->len); ++ ++- if (!signal_len) ++- return 0; +++ if (!siglen) +++ return; ++ /* if flow control disabled, skip to packet data and leave */ ++ if ((!fws) || (!fws->fw_signals)) { ++- skb_pull(skb, signal_len); ++- return 0; +++ skb_pull(skb, siglen); +++ return; ++ } ++ ++ fws->stats.header_pulls++; ++- data_len = signal_len; +++ data_len = siglen; ++ signal_data = skb->data; ++ ++ status = BRCMF_FWS_RET_OK_NOSCHEDULE; ++@@ -1731,14 +1730,12 @@ int brcmf_fws_hdrpull(struct brcmf_pub * ++ /* signalling processing result does ++ * not affect the actual ethernet packet. ++ */ ++- skb_pull(skb, signal_len); +++ skb_pull(skb, siglen); ++ ++ /* this may be a signal-only packet ++ */ ++ if (skb->len == 0) ++ fws->stats.header_only_pkt++; ++- ++- return 0; ++ } ++ ++ static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, ++--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h ++@@ -21,8 +21,7 @@ ++ int brcmf_fws_init(struct brcmf_pub *drvr); ++ void brcmf_fws_deinit(struct brcmf_pub *drvr); ++ bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); ++-int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, ++- struct sk_buff *skb); +++void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb); ++ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb); ++ ++ void brcmf_fws_reset_interface(struct brcmf_if *ifp); +diff --git a/package/kernel/mac80211/patches/330-ath9k-use-rmw-buffer-in-ath9k_hw_set_operating_mode-.patch b/package/kernel/mac80211/patches/330-ath9k-use-rmw-buffer-in-ath9k_hw_set_operating_mode-.patch +deleted file mode 100644 +index 6ce3f40..0000000 +--- a/package/kernel/mac80211/patches/330-ath9k-use-rmw-buffer-in-ath9k_hw_set_operating_mode-.patch ++++ /dev/null +@@ -1,43 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:57 +0100 +-Subject: [PATCH] ath9k: use rmw buffer in ath9k_hw_set_operating_mode +- and ath9k_hw_reset +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/hw.c +-+++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -1227,6 +1227,7 @@ static void ath9k_hw_set_operating_mode( +- u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; +- u32 set = AR_STA_ID1_KSRCH_MODE; +- +-+ ENABLE_REG_RMW_BUFFER(ah); +- switch (opmode) { +- case NL80211_IFTYPE_ADHOC: +- if (!AR_SREV_9340_13(ah)) { +-@@ -1248,6 +1249,7 @@ static void ath9k_hw_set_operating_mode( +- break; +- } +- REG_RMW(ah, AR_STA_ID1, set, mask); +-+ REG_RMW_BUFFER_FLUSH(ah); +- } +- +- void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, +-@@ -1960,6 +1962,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st +- if (!ath9k_hw_mci_is_enabled(ah)) +- REG_WRITE(ah, AR_OBS, 8); +- +-+ ENABLE_REG_RMW_BUFFER(ah); +- if (ah->config.rx_intr_mitigation) { +- REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, ah->config.rimt_last); +- REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, ah->config.rimt_first); +-@@ -1969,6 +1972,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st +- REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300); +- REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750); +- } +-+ REG_RMW_BUFFER_FLUSH(ah); +- +- ath9k_hw_init_bb(ah, chan); +- +diff --git a/package/kernel/mac80211/patches/330-brcmfmac-introduce-brcmf_net_detach-function.patch b/package/kernel/mac80211/patches/330-brcmfmac-introduce-brcmf_net_detach-function.patch +new file mode 100644 +index 0000000..0651a2f +--- /dev/null ++++ b/package/kernel/mac80211/patches/330-brcmfmac-introduce-brcmf_net_detach-function.patch +@@ -0,0 +1,99 @@ ++From: Arend van Spriel ++Date: Wed, 26 Aug 2015 22:15:04 +0200 ++Subject: [PATCH] brcmfmac: introduce brcmf_net_detach() function ++ ++In case of error during brcmf_bus_start() the network interfaces were ++freed using free_netdev(). However, the interfaces may have additional ++memory allocated which is not freed. The netdev has destructor set to ++brcmf_cfg80211_free_netdev() which frees the additional memory if ++allocated and call free_netdev(). The brcmf_net_detach() either calls ++brcmf_cfg80211_free_netdev() directly or uses unregister_netdev() when ++struct net_device::reg_state indicates the netdev was registered. ++ ++Reported-by: Daniel (Deognyoun) Kim ++Reviewed-by: Hante Meuleman ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++@@ -4747,7 +4747,8 @@ void brcmf_cfg80211_free_netdev(struct n ++ ifp = netdev_priv(ndev); ++ vif = ifp->vif; ++ ++- brcmf_free_vif(vif); +++ if (vif) +++ brcmf_free_vif(vif); ++ free_netdev(ndev); ++ } ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c ++@@ -718,8 +718,6 @@ int brcmf_net_attach(struct brcmf_if *if ++ } ++ ++ brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); ++- ++- ndev->destructor = brcmf_cfg80211_free_netdev; ++ return 0; ++ ++ fail: ++@@ -729,6 +727,14 @@ fail: ++ return -EBADE; ++ } ++ +++static void brcmf_net_detach(struct net_device *ndev) +++{ +++ if (ndev->reg_state == NETREG_REGISTERED) +++ unregister_netdev(ndev); +++ else +++ brcmf_cfg80211_free_netdev(ndev); +++} +++ ++ static int brcmf_net_p2p_open(struct net_device *ndev) ++ { ++ brcmf_dbg(TRACE, "Enter\n"); ++@@ -805,8 +811,7 @@ struct brcmf_if *brcmf_add_if(struct brc ++ ifp->ndev->name); ++ if (ifidx) { ++ netif_stop_queue(ifp->ndev); ++- unregister_netdev(ifp->ndev); ++- free_netdev(ifp->ndev); +++ brcmf_net_detach(ifp->ndev); ++ drvr->iflist[bssidx] = NULL; ++ } else { ++ brcmf_err("ignore IF event\n"); ++@@ -828,6 +833,7 @@ struct brcmf_if *brcmf_add_if(struct brc ++ if (!ndev) ++ return ERR_PTR(-ENOMEM); ++ +++ ndev->destructor = brcmf_cfg80211_free_netdev; ++ ifp = netdev_priv(ndev); ++ ifp->ndev = ndev; ++ /* store mapping ifidx to bssidx */ ++@@ -879,8 +885,7 @@ static void brcmf_del_if(struct brcmf_pu ++ cancel_work_sync(&ifp->setmacaddr_work); ++ cancel_work_sync(&ifp->multicast_work); ++ } ++- /* unregister will take care of freeing it */ ++- unregister_netdev(ifp->ndev); +++ brcmf_net_detach(ifp->ndev); ++ } ++ } ++ ++@@ -1056,11 +1061,11 @@ fail: ++ brcmf_fws_deinit(drvr); ++ } ++ if (drvr->iflist[0]) { ++- free_netdev(ifp->ndev); +++ brcmf_net_detach(ifp->ndev); ++ drvr->iflist[0] = NULL; ++ } ++ if (p2p_ifp) { ++- free_netdev(p2p_ifp->ndev); +++ brcmf_net_detach(p2p_ifp->ndev); ++ drvr->iflist[1] = NULL; ++ } ++ return ret; +diff --git a/package/kernel/mac80211/patches/331-ath9k-ath9k_hw_4k_set_board_values-use-rmw-buffer.patch b/package/kernel/mac80211/patches/331-ath9k-ath9k_hw_4k_set_board_values-use-rmw-buffer.patch +deleted file mode 100644 +index edd6160..0000000 +--- a/package/kernel/mac80211/patches/331-ath9k-ath9k_hw_4k_set_board_values-use-rmw-buffer.patch ++++ /dev/null +@@ -1,26 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:58 +0100 +-Subject: [PATCH] ath9k: ath9k_hw_4k_set_board_values: use rmw buffer +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +-@@ -1082,6 +1082,7 @@ static void ath9k_hw_4k_set_board_values +- mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); +- pwrctrl = mask * bb_desired_scale; +- clr = mask * 0x1f; +-+ ENABLE_REG_RMW_BUFFER(ah); +- REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); +- REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); +- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); +-@@ -1096,6 +1097,7 @@ static void ath9k_hw_4k_set_board_values +- clr = mask * 0x1f; +- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); +- REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); +-+ REG_RMW_BUFFER_FLUSH(ah); +- } +- } +- +diff --git a/package/kernel/mac80211/patches/331-brcmfmac-Reset-PCIE-devices-after-recognition.patch b/package/kernel/mac80211/patches/331-brcmfmac-Reset-PCIE-devices-after-recognition.patch +new file mode 100644 +index 0000000..5a7e447 +--- /dev/null ++++ b/package/kernel/mac80211/patches/331-brcmfmac-Reset-PCIE-devices-after-recognition.patch +@@ -0,0 +1,193 @@ ++From: Hante Meuleman ++Date: Thu, 27 Aug 2015 16:14:06 +0200 ++Subject: [PATCH] brcmfmac: Reset PCIE devices after recognition. ++ ++When PCIE type devices are being FW reloaded without being properly ++reset then the device ends up in a locked state, requiring the ++device to be completely powered down. This patch adds a reset ++through watchdog at the moment the device (cores) has been ++recognized. This will solve warm reboot issues. ++ ++Cc: Rafal Milecki ++Reviewed-by: Arend Van Spriel ++Reviewed-by: Franky (Zhenhui) Lin ++Reviewed-by: Pieter-Paul Giesberts ++Signed-off-by: Hante Meuleman ++Signed-off-by: Arend van Spriel ++--- ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c ++@@ -101,6 +101,9 @@ ++ /* ARM Cortex M3 core, ID 0x82a */ ++ #define BCM4329_CORE_ARM_BASE 0x18002000 ++ +++/* Max possibly supported memory size (limited by IO mapped memory) */ +++#define BRCMF_CHIP_MAX_MEMSIZE (4 * 1024 * 1024) +++ ++ #define CORE_SB(base, field) \ ++ (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) ++ #define SBCOREREV(sbidh) \ ++@@ -687,6 +690,12 @@ static int brcmf_chip_get_raminfo(struct ++ brcmf_err("RAM size is undetermined\n"); ++ return -ENOMEM; ++ } +++ +++ if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) { +++ brcmf_err("RAM size is incorrect\n"); +++ return -ENOMEM; +++ } +++ ++ return 0; ++ } ++ ++@@ -899,6 +908,15 @@ static int brcmf_chip_recognition(struct ++ ++ /* assure chip is passive for core access */ ++ brcmf_chip_set_passive(&ci->pub); +++ +++ /* Call bus specific reset function now. Cores have been determined +++ * but further access may require a chip specific reset at this point. +++ */ +++ if (ci->ops->reset) { +++ ci->ops->reset(ci->ctx, &ci->pub); +++ brcmf_chip_set_passive(&ci->pub); +++ } +++ ++ return brcmf_chip_get_raminfo(ci); ++ } ++ ++--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h +++++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h ++@@ -73,6 +73,7 @@ struct brcmf_buscore_ops { ++ u32 (*read32)(void *ctx, u32 addr); ++ void (*write32)(void *ctx, u32 addr, u32 value); ++ int (*prepare)(void *ctx); +++ int (*reset)(void *ctx, struct brcmf_chip *chip); ++ int (*setup)(void *ctx, struct brcmf_chip *chip); ++ void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec); ++ }; ++--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c ++@@ -74,6 +74,8 @@ enum brcmf_pcie_state { ++ #define BRCMF_PCIE_REG_INTMASK 0x94 ++ #define BRCMF_PCIE_REG_SBMBX 0x98 ++ +++#define BRCMF_PCIE_REG_LINK_STATUS_CTRL 0xBC +++ ++ #define BRCMF_PCIE_PCIE2REG_INTMASK 0x24 ++ #define BRCMF_PCIE_PCIE2REG_MAILBOXINT 0x48 ++ #define BRCMF_PCIE_PCIE2REG_MAILBOXMASK 0x4C ++@@ -466,6 +468,7 @@ brcmf_pcie_select_core(struct brcmf_pcie ++ ++ static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo) ++ { +++ struct brcmf_core *core; ++ u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD, ++ BRCMF_PCIE_CFGREG_PM_CSR, ++ BRCMF_PCIE_CFGREG_MSI_CAP, ++@@ -484,32 +487,38 @@ static void brcmf_pcie_reset_device(stru ++ if (!devinfo->ci) ++ return; ++ +++ /* Disable ASPM */ ++ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); ++- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, ++- BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL); ++- lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA); +++ pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, +++ &lsc); ++ val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB); ++- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val); +++ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, +++ val); ++ +++ /* Watchdog reset */ ++ brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON); ++ WRITECC32(devinfo, watchdog, 4); ++ msleep(100); ++ +++ /* Restore ASPM */ ++ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); ++- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, ++- BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL); ++- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc); +++ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, +++ lsc); ++ ++- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); ++- for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) { ++- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, ++- cfg_offset[i]); ++- val = brcmf_pcie_read_reg32(devinfo, ++- BRCMF_PCIE_PCIE2REG_CONFIGDATA); ++- brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n", ++- cfg_offset[i], val); ++- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, ++- val); +++ core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); +++ if (core->rev <= 13) { +++ for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) { +++ brcmf_pcie_write_reg32(devinfo, +++ BRCMF_PCIE_PCIE2REG_CONFIGADDR, +++ cfg_offset[i]); +++ val = brcmf_pcie_read_reg32(devinfo, +++ BRCMF_PCIE_PCIE2REG_CONFIGDATA); +++ brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n", +++ cfg_offset[i], val); +++ brcmf_pcie_write_reg32(devinfo, +++ BRCMF_PCIE_PCIE2REG_CONFIGDATA, +++ val); +++ } ++ } ++ } ++ ++@@ -519,8 +528,6 @@ static void brcmf_pcie_attach(struct brc ++ u32 config; ++ ++ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); ++- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) ++- brcmf_pcie_reset_device(devinfo); ++ /* BAR1 window may not be sized properly */ ++ brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); ++ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0); ++@@ -1636,6 +1643,23 @@ static int brcmf_pcie_buscoreprep(void * ++ } ++ ++ +++static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip) +++{ +++ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; +++ u32 val; +++ +++ devinfo->ci = chip; +++ brcmf_pcie_reset_device(devinfo); +++ +++ val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT); +++ if (val != 0xffffffff) +++ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, +++ val); +++ +++ return 0; +++} +++ +++ ++ static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip, ++ u32 rstvec) ++ { ++@@ -1647,6 +1671,7 @@ static void brcmf_pcie_buscore_activate( ++ ++ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { ++ .prepare = brcmf_pcie_buscoreprep, +++ .reset = brcmf_pcie_buscore_reset, ++ .activate = brcmf_pcie_buscore_activate, ++ .read32 = brcmf_pcie_buscore_read32, ++ .write32 = brcmf_pcie_buscore_write32, ++@@ -1814,7 +1839,6 @@ brcmf_pcie_remove(struct pci_dev *pdev) ++ brcmf_pcie_intr_disable(devinfo); ++ ++ brcmf_detach(&pdev->dev); ++- brcmf_pcie_reset_device(devinfo); ++ ++ kfree(bus->bus_priv.pcie); ++ kfree(bus->msgbuf->flowrings); +diff --git a/package/kernel/mac80211/patches/332-ath9k-ath9k_hw_analog_shift_rmw-use-REG_RMW.patch b/package/kernel/mac80211/patches/332-ath9k-ath9k_hw_analog_shift_rmw-use-REG_RMW.patch +deleted file mode 100644 +index 3ce4428..0000000 +--- a/package/kernel/mac80211/patches/332-ath9k-ath9k_hw_analog_shift_rmw-use-REG_RMW.patch ++++ /dev/null +@@ -1,27 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:29:59 +0100 +-Subject: [PATCH] ath9k: ath9k_hw_analog_shift_rmw: use REG_RMW +- +-use REG_RMW in ath9k_hw_analog_shift_rmw. +-It will double execution speed on usb bus. +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/eeprom.c +-+++ b/drivers/net/wireless/ath/ath9k/eeprom.c +-@@ -27,12 +27,7 @@ void ath9k_hw_analog_shift_regwrite(stru +- void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, +- u32 shift, u32 val) +- { +-- u32 regVal; +-- +-- regVal = REG_READ(ah, reg) & ~mask; +-- regVal |= (val << shift) & mask; +-- +-- REG_WRITE(ah, reg, regVal); +-+ REG_RMW(ah, reg, ((val << shift) & mask), mask); +- +- if (ah->config.analog_shiftreg) +- udelay(100); +diff --git a/package/kernel/mac80211/patches/333-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_4k_set_.patch b/package/kernel/mac80211/patches/333-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_4k_set_.patch +deleted file mode 100644 +index 8f12b36..0000000 +--- a/package/kernel/mac80211/patches/333-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_4k_set_.patch ++++ /dev/null +@@ -1,47 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:30:01 +0100 +-Subject: [PATCH] ath9k: use REG_RMW and rmw buffer in +- ath9k_hw_4k_set_gain +- +-it is possible to reduce time needed for this function +-by rplacing REG_WRITE with REG_RMW (plus dummy 0) and putt all commands +-in same buffer. +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +-+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c +-@@ -772,15 +772,14 @@ static void ath9k_hw_4k_set_gain(struct +- struct ar5416_eeprom_4k *eep, +- u8 txRxAttenLocal) +- { +-- REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0, +-- pModal->antCtrlChain[0]); +-- +-- REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), +-- (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & +-- ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | +-- AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | +-- SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | +-- SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); +-+ ENABLE_REG_RMW_BUFFER(ah); +-+ REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, +-+ pModal->antCtrlChain[0], 0); +-+ +-+ REG_RMW(ah, AR_PHY_TIMING_CTRL4(0), +-+ SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | +-+ SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF), +-+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF); +- +- if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= +- AR5416_EEP_MINOR_VER_3) { +-@@ -819,6 +818,7 @@ static void ath9k_hw_4k_set_gain(struct +- AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); +- REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, +- AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); +-+ REG_RMW_BUFFER_FLUSH(ah); +- } +- +- /* +diff --git a/package/kernel/mac80211/patches/334-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_def_set.patch b/package/kernel/mac80211/patches/334-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_def_set.patch +deleted file mode 100644 +index f26e059..0000000 +--- a/package/kernel/mac80211/patches/334-ath9k-use-REG_RMW-and-rmw-buffer-in-ath9k_hw_def_set.patch ++++ /dev/null +@@ -1,67 +0,0 @@ +-From: Oleksij Rempel +-Date: Sun, 22 Mar 2015 19:30:03 +0100 +-Subject: [PATCH] ath9k: use REG_RMW and rmw buffer in +- ath9k_hw_def_set_gain +- +-Signed-off-by: Oleksij Rempel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +-+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c +-@@ -466,6 +466,7 @@ static void ath9k_hw_def_set_gain(struct +- struct ar5416_eeprom_def *eep, +- u8 txRxAttenLocal, int regChainOffset, int i) +- { +-+ ENABLE_REG_RMW_BUFFER(ah); +- if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { +- txRxAttenLocal = pModal->txRxAttenCh[i]; +- +-@@ -483,16 +484,12 @@ static void ath9k_hw_def_set_gain(struct +- AR_PHY_GAIN_2GHZ_XATTEN2_DB, +- pModal->xatten2Db[i]); +- } else { +-- REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, +-- (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & +-- ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) +-- | SM(pModal-> bswMargin[i], +-- AR_PHY_GAIN_2GHZ_BSW_MARGIN)); +-- REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, +-- (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & +-- ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) +-- | SM(pModal->bswAtten[i], +-- AR_PHY_GAIN_2GHZ_BSW_ATTEN)); +-+ REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset, +-+ SM(pModal-> bswMargin[i], AR_PHY_GAIN_2GHZ_BSW_MARGIN), +-+ AR_PHY_GAIN_2GHZ_BSW_MARGIN); +-+ REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset, +-+ SM(pModal->bswAtten[i], AR_PHY_GAIN_2GHZ_BSW_ATTEN), +-+ AR_PHY_GAIN_2GHZ_BSW_ATTEN); +- } +- } +- +-@@ -504,17 +501,14 @@ static void ath9k_hw_def_set_gain(struct +- AR_PHY_RXGAIN + regChainOffset, +- AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); +- } else { +-- REG_WRITE(ah, +-- AR_PHY_RXGAIN + regChainOffset, +-- (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & +-- ~AR_PHY_RXGAIN_TXRX_ATTEN) +-- | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN)); +-- REG_WRITE(ah, +-- AR_PHY_GAIN_2GHZ + regChainOffset, +-- (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & +-- ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | +-- SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); +-+ REG_RMW(ah, AR_PHY_RXGAIN + regChainOffset, +-+ SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN), +-+ AR_PHY_RXGAIN_TXRX_ATTEN); +-+ REG_RMW(ah, AR_PHY_GAIN_2GHZ + regChainOffset, +-+ SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN), +-+ AR_PHY_GAIN_2GHZ_RXTX_MARGIN); +- } +-+ REG_RMW_BUFFER_FLUSH(ah); +- } +- +- static void ath9k_hw_def_set_board_values(struct ath_hw *ah, +diff --git a/package/kernel/mac80211/patches/335-brcmfmac-Fix-oops-when-SDIO-device-is-removed.patch b/package/kernel/mac80211/patches/335-brcmfmac-Fix-oops-when-SDIO-device-is-removed.patch +deleted file mode 100644 +index 5e63a80..0000000 +--- a/package/kernel/mac80211/patches/335-brcmfmac-Fix-oops-when-SDIO-device-is-removed.patch ++++ /dev/null +@@ -1,44 +0,0 @@ +-From: Hante Meuleman +-Date: Fri, 6 Mar 2015 18:40:38 +0100 +-Subject: [PATCH] brcmfmac: Fix oops when SDIO device is removed. +- +-On removal of SDIO card both functions of card will be getting +-a remove call. When the first is hanging in ctrl frame xmit then +-the second will cause oops. This patch fixes the xmit ctrl +-handling in case of serious errors and also limits the handling +-for remove to function 1 only. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Daniel (Deognyoun) Kim +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-@@ -1194,7 +1194,7 @@ static void brcmf_ops_sdio_remove(struct +- brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); +- brcmf_dbg(SDIO, "Function: %d\n", func->num); +- +-- if (func->num != 1 && func->num != 2) +-+ if (func->num != 1) +- return; +- +- bus_if = dev_get_drvdata(&func->dev); +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -2740,6 +2740,11 @@ static void brcmf_sdio_dpc(struct brcmf_ +- if ((bus->sdiodev->state != BRCMF_SDIOD_DATA) || (err != 0)) { +- brcmf_err("failed backplane access over SDIO, halting operation\n"); +- atomic_set(&bus->intstatus, 0); +-+ if (bus->ctrl_frame_stat) { +-+ bus->ctrl_frame_err = -ENODEV; +-+ bus->ctrl_frame_stat = false; +-+ brcmf_sdio_wait_event_wakeup(bus); +-+ } +- } else if (atomic_read(&bus->intstatus) || +- atomic_read(&bus->ipend) > 0 || +- (!atomic_read(&bus->fcstate) && +diff --git a/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch b/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch +deleted file mode 100644 +index 201da75..0000000 +--- a/package/kernel/mac80211/patches/336-brcmfmac-Simplify-watchdog-sleep.patch ++++ /dev/null +@@ -1,157 +0,0 @@ +-From: Hante Meuleman +-Date: Fri, 6 Mar 2015 18:40:39 +0100 +-Subject: [PATCH] brcmfmac: Simplify watchdog sleep. +- +-The watchdog thread is used to put the SDIO bus to sleep when the +-system is idling. This patch simplifies the way it is determined +-when sleep can be entered. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Daniel (Deognyoun) Kim +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -485,10 +485,9 @@ struct brcmf_sdio { +- #endif /* DEBUG */ +- +- uint clkstate; /* State of sd and backplane clock(s) */ +-- bool activity; /* Activity flag for clock down */ +- s32 idletime; /* Control for activity timeout */ +-- s32 idlecount; /* Activity timeout counter */ +-- s32 idleclock; /* How to set bus driver when idle */ +-+ s32 idlecount; /* Activity timeout counter */ +-+ s32 idleclock; /* How to set bus driver when idle */ +- bool rxflow_mode; /* Rx flow control mode */ +- bool rxflow; /* Is rx flow control on */ +- bool alp_only; /* Don't use HT clock (ALP only) */ +-@@ -511,6 +510,7 @@ struct brcmf_sdio { +- struct workqueue_struct *brcmf_wq; +- struct work_struct datawork; +- atomic_t dpc_tskcnt; +-+ atomic_t dpc_running; +- +- bool txoff; /* Transmit flow-controlled */ +- struct brcmf_sdio_count sdcnt; +-@@ -959,13 +959,8 @@ static int brcmf_sdio_clkctl(struct brcm +- brcmf_dbg(SDIO, "Enter\n"); +- +- /* Early exit if we're already there */ +-- if (bus->clkstate == target) { +-- if (target == CLK_AVAIL) { +-- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); +-- bus->activity = true; +-- } +-+ if (bus->clkstate == target) +- return 0; +-- } +- +- switch (target) { +- case CLK_AVAIL: +-@@ -975,7 +970,6 @@ static int brcmf_sdio_clkctl(struct brcm +- /* Now request HT Avail on the backplane */ +- brcmf_sdio_htclk(bus, true, pendok); +- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); +-- bus->activity = true; +- break; +- +- case CLK_SDONLY: +-@@ -1024,17 +1018,6 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio * +- +- /* Going to sleep */ +- if (sleep) { +-- /* Don't sleep if something is pending */ +-- if (atomic_read(&bus->intstatus) || +-- atomic_read(&bus->ipend) > 0 || +-- bus->ctrl_frame_stat || +-- (!atomic_read(&bus->fcstate) && +-- brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && +-- data_ok(bus))) { +-- err = -EBUSY; +-- goto done; +-- } +-- +- clkcsr = brcmf_sdiod_regrb(bus->sdiodev, +- SBSDIO_FUNC1_CHIPCLKCSR, +- &err); +-@@ -1045,11 +1028,7 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio * +- SBSDIO_ALP_AVAIL_REQ, &err); +- } +- err = brcmf_sdio_kso_control(bus, false); +-- /* disable watchdog */ +-- if (!err) +-- brcmf_sdio_wd_timer(bus, 0); +- } else { +-- bus->idlecount = 0; +- err = brcmf_sdio_kso_control(bus, true); +- } +- if (err) { +-@@ -3566,7 +3545,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b +- queue_work(bus->brcmf_wq, &bus->datawork); +- } +- +--static bool brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) +-+static void brcmf_sdio_bus_watchdog(struct brcmf_sdio *bus) +- { +- brcmf_dbg(TIMER, "Enter\n"); +- +-@@ -3627,22 +3606,21 @@ static bool brcmf_sdio_bus_watchdog(stru +- #endif /* DEBUG */ +- +- /* On idle timeout clear activity flag and/or turn off clock */ +-- if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { +-- if (++bus->idlecount >= bus->idletime) { +-+ if ((atomic_read(&bus->dpc_tskcnt) == 0) && +-+ (atomic_read(&bus->dpc_running) == 0) && +-+ (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { +-+ bus->idlecount++; +-+ if (bus->idlecount > bus->idletime) { +-+ brcmf_dbg(SDIO, "idle\n"); +-+ sdio_claim_host(bus->sdiodev->func[1]); +-+ brcmf_sdio_wd_timer(bus, 0); +- bus->idlecount = 0; +-- if (bus->activity) { +-- bus->activity = false; +-- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); +-- } else { +-- brcmf_dbg(SDIO, "idle\n"); +-- sdio_claim_host(bus->sdiodev->func[1]); +-- brcmf_sdio_bus_sleep(bus, true, false); +-- sdio_release_host(bus->sdiodev->func[1]); +-- } +-+ brcmf_sdio_bus_sleep(bus, true, false); +-+ sdio_release_host(bus->sdiodev->func[1]); +- } +-+ } else { +-+ bus->idlecount = 0; +- } +-- +-- return (atomic_read(&bus->ipend) > 0); +- } +- +- static void brcmf_sdio_dataworker(struct work_struct *work) +-@@ -3651,8 +3629,11 @@ static void brcmf_sdio_dataworker(struct +- datawork); +- +- while (atomic_read(&bus->dpc_tskcnt)) { +-+ atomic_set(&bus->dpc_running, 1); +- atomic_set(&bus->dpc_tskcnt, 0); +- brcmf_sdio_dpc(bus); +-+ bus->idlecount = 0; +-+ atomic_set(&bus->dpc_running, 0); +- } +- if (brcmf_sdiod_freezing(bus->sdiodev)) { +- brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN); +-@@ -4154,6 +4135,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru +- } +- /* Initialize DPC thread */ +- atomic_set(&bus->dpc_tskcnt, 0); +-+ atomic_set(&bus->dpc_running, 0); +- +- /* Assign bus interface call back */ +- bus->sdiodev->bus_if->dev = bus->sdiodev->dev; +diff --git a/package/kernel/mac80211/patches/337-brcmfmac-Fix-possible-race-condition.patch b/package/kernel/mac80211/patches/337-brcmfmac-Fix-possible-race-condition.patch +deleted file mode 100644 +index 3a2de7a..0000000 +--- a/package/kernel/mac80211/patches/337-brcmfmac-Fix-possible-race-condition.patch ++++ /dev/null +@@ -1,83 +0,0 @@ +-From: Hante Meuleman +-Date: Fri, 6 Mar 2015 18:40:40 +0100 +-Subject: [PATCH] brcmfmac: Fix possible race-condition. +- +-SDIO is using a "shared" variable to handoff ctl frames to DPC +-and to see when they are done. In a timeout situation this can +-lead to erroneous situation where DPC started to handle the ctl +-frame while the timeout expired. This patch will fix this by +-adding locking around the shared variable. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Daniel (Deognyoun) Kim +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -2700,11 +2700,13 @@ static void brcmf_sdio_dpc(struct brcmf_ +- if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && +- data_ok(bus)) { +- sdio_claim_host(bus->sdiodev->func[1]); +-- err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, +-- bus->ctrl_frame_len); +-+ if (bus->ctrl_frame_stat) { +-+ err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, +-+ bus->ctrl_frame_len); +-+ bus->ctrl_frame_err = err; +-+ bus->ctrl_frame_stat = false; +-+ } +- sdio_release_host(bus->sdiodev->func[1]); +-- bus->ctrl_frame_err = err; +-- bus->ctrl_frame_stat = false; +- brcmf_sdio_wait_event_wakeup(bus); +- } +- /* Send queued frames (limit 1 if rx may still be pending) */ +-@@ -2720,9 +2722,13 @@ static void brcmf_sdio_dpc(struct brcmf_ +- brcmf_err("failed backplane access over SDIO, halting operation\n"); +- atomic_set(&bus->intstatus, 0); +- if (bus->ctrl_frame_stat) { +-- bus->ctrl_frame_err = -ENODEV; +-- bus->ctrl_frame_stat = false; +-- brcmf_sdio_wait_event_wakeup(bus); +-+ sdio_claim_host(bus->sdiodev->func[1]); +-+ if (bus->ctrl_frame_stat) { +-+ bus->ctrl_frame_err = -ENODEV; +-+ bus->ctrl_frame_stat = false; +-+ brcmf_sdio_wait_event_wakeup(bus); +-+ } +-+ sdio_release_host(bus->sdiodev->func[1]); +- } +- } else if (atomic_read(&bus->intstatus) || +- atomic_read(&bus->ipend) > 0 || +-@@ -2930,15 +2936,20 @@ brcmf_sdio_bus_txctl(struct device *dev, +- brcmf_sdio_trigger_dpc(bus); +- wait_event_interruptible_timeout(bus->ctrl_wait, !bus->ctrl_frame_stat, +- msecs_to_jiffies(CTL_DONE_TIMEOUT)); +-- +-- if (!bus->ctrl_frame_stat) { +-+ ret = 0; +-+ if (bus->ctrl_frame_stat) { +-+ sdio_claim_host(bus->sdiodev->func[1]); +-+ if (bus->ctrl_frame_stat) { +-+ brcmf_dbg(SDIO, "ctrl_frame timeout\n"); +-+ bus->ctrl_frame_stat = false; +-+ ret = -ETIMEDOUT; +-+ } +-+ sdio_release_host(bus->sdiodev->func[1]); +-+ } +-+ if (!ret) { +- brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", +- bus->ctrl_frame_err); +- ret = bus->ctrl_frame_err; +-- } else { +-- brcmf_dbg(SDIO, "ctrl_frame timeout\n"); +-- bus->ctrl_frame_stat = false; +-- ret = -ETIMEDOUT; +- } +- +- if (ret) +diff --git a/package/kernel/mac80211/patches/338-brcmfmac-Add-support-for-BCM4345-SDIO-chipset.patch b/package/kernel/mac80211/patches/338-brcmfmac-Add-support-for-BCM4345-SDIO-chipset.patch +deleted file mode 100644 +index c9eb900..0000000 +--- a/package/kernel/mac80211/patches/338-brcmfmac-Add-support-for-BCM4345-SDIO-chipset.patch ++++ /dev/null +@@ -1,86 +0,0 @@ +-From: Syed Asifful Dayyan +-Date: Fri, 6 Mar 2015 18:40:42 +0100 +-Subject: [PATCH] brcmfmac: Add support for BCM4345 SDIO chipset. +- +-These changes add support for BCM4345 SDIO chipset. +- +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Hante Meuleman +-Reviewed-by: Daniel (Deognyoun) Kim +-Signed-off-by: Syed Asifful Dayyan +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-@@ -1096,6 +1096,7 @@ static const struct sdio_device_id brcmf +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341), +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362), +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339), +-+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345), +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), +- { /* end: all zeroes */ } +- }; +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-@@ -491,6 +491,10 @@ static void brcmf_chip_get_raminfo(struc +- case BRCM_CC_43362_CHIP_ID: +- ci->pub.ramsize = 0x3c000; +- break; +-+ case BRCM_CC_4345_CHIP_ID: +-+ ci->pub.ramsize = 0xc8000; +-+ ci->pub.rambase = 0x198000; +-+ break; +- case BRCM_CC_4339_CHIP_ID: +- case BRCM_CC_4354_CHIP_ID: +- case BRCM_CC_4356_CHIP_ID: +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -617,6 +617,8 @@ static const struct sdiod_drive_str sdio +- #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt" +- #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" +- #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" +-+#define BCM4345_FIRMWARE_NAME "brcm/brcmfmac4345-sdio.bin" +-+#define BCM4345_NVRAM_NAME "brcm/brcmfmac4345-sdio.txt" +- #define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin" +- #define BCM4354_NVRAM_NAME "brcm/brcmfmac4354-sdio.txt" +- +-@@ -640,6 +642,8 @@ MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM43362_NVRAM_NAME); +- MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM4339_NVRAM_NAME); +-+MODULE_FIRMWARE(BCM4345_FIRMWARE_NAME); +-+MODULE_FIRMWARE(BCM4345_NVRAM_NAME); +- MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM4354_NVRAM_NAME); +- +-@@ -669,6 +673,7 @@ static const struct brcmf_firmware_names +- { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, +- { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, +- { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, +-+ { BRCM_CC_4345_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4345) }, +- { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } +- }; +- +---- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +-+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +-@@ -37,6 +37,7 @@ +- #define BRCM_CC_43362_CHIP_ID 43362 +- #define BRCM_CC_4335_CHIP_ID 0x4335 +- #define BRCM_CC_4339_CHIP_ID 0x4339 +-+#define BRCM_CC_4345_CHIP_ID 0x4345 +- #define BRCM_CC_4354_CHIP_ID 0x4354 +- #define BRCM_CC_4356_CHIP_ID 0x4356 +- #define BRCM_CC_43566_CHIP_ID 43566 +---- a/include/linux/mmc/sdio_ids.h +-+++ b/include/linux/mmc/sdio_ids.h +-@@ -33,6 +33,7 @@ +- #define SDIO_DEVICE_ID_BROADCOM_43341 0xa94d +- #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 +- #define SDIO_DEVICE_ID_BROADCOM_43362 0xa962 +-+#define SDIO_DEVICE_ID_BROADCOM_4345 0x4345 +- #define SDIO_DEVICE_ID_BROADCOM_4354 0x4354 +- +- #define SDIO_VENDOR_ID_INTEL 0x0089 +diff --git a/package/kernel/mac80211/patches/339-brcmfmac-remove-duplication-of-ramsize-info.patch b/package/kernel/mac80211/patches/339-brcmfmac-remove-duplication-of-ramsize-info.patch +deleted file mode 100644 +index 7a688c4..0000000 +--- a/package/kernel/mac80211/patches/339-brcmfmac-remove-duplication-of-ramsize-info.patch ++++ /dev/null +@@ -1,48 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 11 Mar 2015 16:11:27 +0100 +-Subject: [PATCH] brcmfmac: remove duplication of ramsize info +- +-Removing the ramsize from the brcmf_sdio structure to avoid +-duplication. The information is available in brcmf_chip +-structure. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -432,8 +432,6 @@ struct brcmf_sdio { +- struct brcmf_sdio_dev *sdiodev; /* sdio device handler */ +- struct brcmf_chip *ci; /* Chip info struct */ +- +-- u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ +-- +- u32 hostintmask; /* Copy of Host Interrupt Mask */ +- atomic_t intstatus; /* Intstatus bits (events) pending */ +- atomic_t fcstate; /* State of dongle flow-control */ +-@@ -1075,7 +1073,7 @@ static int brcmf_sdio_readshared(struct +- struct sdpcm_shared_le sh_le; +- __le32 addr_le; +- +-- shaddr = bus->ci->rambase + bus->ramsize - 4; +-+ shaddr = bus->ci->rambase + bus->ci->ramsize - 4; +- +- /* +- * Read last word in socram to determine +-@@ -3871,13 +3869,6 @@ brcmf_sdio_probe_attach(struct brcmf_sdi +- drivestrength = DEFAULT_SDIO_DRIVE_STRENGTH; +- brcmf_sdio_drivestrengthinit(bus->sdiodev, bus->ci, drivestrength); +- +-- /* Get info on the SOCRAM cores... */ +-- bus->ramsize = bus->ci->ramsize; +-- if (!(bus->ramsize)) { +-- brcmf_err("failed to find SOCRAM memory!\n"); +-- goto fail; +-- } +-- +- /* Set card control so an SDIO card reset does a WLAN backplane reset */ +- reg_val = brcmf_sdiod_regrb(bus->sdiodev, +- SDIO_CCCR_BRCM_CARDCTRL, &err); +diff --git a/package/kernel/mac80211/patches/340-brcmfmac-always-perform-cores-checks.patch b/package/kernel/mac80211/patches/340-brcmfmac-always-perform-cores-checks.patch +deleted file mode 100644 +index e2a2074..0000000 +--- a/package/kernel/mac80211/patches/340-brcmfmac-always-perform-cores-checks.patch ++++ /dev/null +@@ -1,74 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 11 Mar 2015 16:11:28 +0100 +-Subject: [PATCH] brcmfmac: always perform cores checks +- +-Instead of checking the cores in the chip only if CONFIG_BRCMDBG +-is selected perform the check always and extend it with more sanity +-checking. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-@@ -419,13 +419,13 @@ static struct brcmf_core *brcmf_chip_add +- return &core->pub; +- } +- +--#ifdef DEBUG +- /* safety check for chipinfo */ +- static int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) +- { +- struct brcmf_core_priv *core; +- bool need_socram = false; +- bool has_socram = false; +-+ bool cpu_found = false; +- int idx = 1; +- +- list_for_each_entry(core, &ci->cores, list) { +-@@ -435,12 +435,14 @@ static int brcmf_chip_cores_check(struct +- +- switch (core->pub.id) { +- case BCMA_CORE_ARM_CM3: +-+ cpu_found = true; +- need_socram = true; +- break; +- case BCMA_CORE_INTERNAL_MEM: +- has_socram = true; +- break; +- case BCMA_CORE_ARM_CR4: +-+ cpu_found = true; +- if (ci->pub.rambase == 0) { +- brcmf_err("RAM base not provided with ARM CR4 core\n"); +- return -ENOMEM; +-@@ -451,19 +453,21 @@ static int brcmf_chip_cores_check(struct +- } +- } +- +-+ if (!cpu_found) { +-+ brcmf_err("CPU core not detected\n"); +-+ return -ENXIO; +-+ } +- /* check RAM core presence for ARM CM3 core */ +- if (need_socram && !has_socram) { +- brcmf_err("RAM core not provided with ARM CM3 core\n"); +- return -ENODEV; +- } +-+ if (!ci->pub.ramsize) { +-+ brcmf_err("RAM size is undetermined\n"); +-+ return -ENOMEM; +-+ } +- return 0; +- } +--#else /* DEBUG */ +--static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) +--{ +-- return 0; +--} +--#endif +- +- static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) +- { +diff --git a/package/kernel/mac80211/patches/341-brcmfmac-rename-chip-download-functions.patch b/package/kernel/mac80211/patches/341-brcmfmac-rename-chip-download-functions.patch +deleted file mode 100644 +index a272800..0000000 +--- a/package/kernel/mac80211/patches/341-brcmfmac-rename-chip-download-functions.patch ++++ /dev/null +@@ -1,240 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 11 Mar 2015 16:11:29 +0100 +-Subject: [PATCH] brcmfmac: rename chip download functions +- +-The functions brcmf_chip_[enter/exit]_download() are not exclusively +-used for firmware download so rename these more appropriate. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-@@ -807,7 +807,7 @@ struct brcmf_chip *brcmf_chip_attach(voi +- err = -EINVAL; +- if (WARN_ON(!ops->prepare)) +- err = -EINVAL; +-- if (WARN_ON(!ops->exit_dl)) +-+ if (WARN_ON(!ops->activate)) +- err = -EINVAL; +- if (err < 0) +- return ERR_PTR(-EINVAL); +-@@ -905,7 +905,7 @@ void brcmf_chip_resetcore(struct brcmf_c +- } +- +- static void +--brcmf_chip_cm3_enterdl(struct brcmf_chip_priv *chip) +-+brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip) +- { +- struct brcmf_core *core; +- +-@@ -919,7 +919,7 @@ brcmf_chip_cm3_enterdl(struct brcmf_chip +- brcmf_chip_resetcore(core, 0, 0, 0); +- } +- +--static bool brcmf_chip_cm3_exitdl(struct brcmf_chip_priv *chip) +-+static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip) +- { +- struct brcmf_core *core; +- +-@@ -929,7 +929,7 @@ static bool brcmf_chip_cm3_exitdl(struct +- return false; +- } +- +-- chip->ops->exit_dl(chip->ctx, &chip->pub, 0); +-+ chip->ops->activate(chip->ctx, &chip->pub, 0); +- +- core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CM3); +- brcmf_chip_resetcore(core, 0, 0, 0); +-@@ -938,7 +938,7 @@ static bool brcmf_chip_cm3_exitdl(struct +- } +- +- static inline void +--brcmf_chip_cr4_enterdl(struct brcmf_chip_priv *chip) +-+brcmf_chip_cr4_set_passive(struct brcmf_chip_priv *chip) +- { +- struct brcmf_core *core; +- +-@@ -951,11 +951,11 @@ brcmf_chip_cr4_enterdl(struct brcmf_chip +- D11_BCMA_IOCTL_PHYCLOCKEN); +- } +- +--static bool brcmf_chip_cr4_exitdl(struct brcmf_chip_priv *chip, u32 rstvec) +-+static bool brcmf_chip_cr4_set_active(struct brcmf_chip_priv *chip, u32 rstvec) +- { +- struct brcmf_core *core; +- +-- chip->ops->exit_dl(chip->ctx, &chip->pub, rstvec); +-+ chip->ops->activate(chip->ctx, &chip->pub, rstvec); +- +- /* restore ARM */ +- core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_ARM_CR4); +-@@ -964,7 +964,7 @@ static bool brcmf_chip_cr4_exitdl(struct +- return true; +- } +- +--void brcmf_chip_enter_download(struct brcmf_chip *pub) +-+void brcmf_chip_set_passive(struct brcmf_chip *pub) +- { +- struct brcmf_chip_priv *chip; +- struct brcmf_core *arm; +-@@ -974,14 +974,14 @@ void brcmf_chip_enter_download(struct br +- chip = container_of(pub, struct brcmf_chip_priv, pub); +- arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); +- if (arm) { +-- brcmf_chip_cr4_enterdl(chip); +-+ brcmf_chip_cr4_set_passive(chip); +- return; +- } +- +-- brcmf_chip_cm3_enterdl(chip); +-+ brcmf_chip_cm3_set_passive(chip); +- } +- +--bool brcmf_chip_exit_download(struct brcmf_chip *pub, u32 rstvec) +-+bool brcmf_chip_set_active(struct brcmf_chip *pub, u32 rstvec) +- { +- struct brcmf_chip_priv *chip; +- struct brcmf_core *arm; +-@@ -991,9 +991,9 @@ bool brcmf_chip_exit_download(struct brc +- chip = container_of(pub, struct brcmf_chip_priv, pub); +- arm = brcmf_chip_get_core(pub, BCMA_CORE_ARM_CR4); +- if (arm) +-- return brcmf_chip_cr4_exitdl(chip, rstvec); +-+ return brcmf_chip_cr4_set_active(chip, rstvec); +- +-- return brcmf_chip_cm3_exitdl(chip); +-+ return brcmf_chip_cm3_set_active(chip); +- } +- +- bool brcmf_chip_sr_capable(struct brcmf_chip *pub) +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h +-@@ -64,7 +64,7 @@ struct brcmf_core { +- * @write32: write 32-bit value over bus. +- * @prepare: prepare bus for core configuration. +- * @setup: bus-specific core setup. +-- * @exit_dl: exit download state. +-+ * @active: chip becomes active. +- * The callback should use the provided @rstvec when non-zero. +- */ +- struct brcmf_buscore_ops { +-@@ -72,7 +72,7 @@ struct brcmf_buscore_ops { +- void (*write32)(void *ctx, u32 addr, u32 value); +- int (*prepare)(void *ctx); +- int (*setup)(void *ctx, struct brcmf_chip *chip); +-- void (*exit_dl)(void *ctx, struct brcmf_chip *chip, u32 rstvec); +-+ void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec); +- }; +- +- struct brcmf_chip *brcmf_chip_attach(void *ctx, +-@@ -84,8 +84,8 @@ bool brcmf_chip_iscoreup(struct brcmf_co +- void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset); +- void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset, +- u32 postreset); +--void brcmf_chip_enter_download(struct brcmf_chip *ci); +--bool brcmf_chip_exit_download(struct brcmf_chip *ci, u32 rstvec); +-+void brcmf_chip_set_passive(struct brcmf_chip *ci); +-+bool brcmf_chip_set_active(struct brcmf_chip *ci, u32 rstvec); +- bool brcmf_chip_sr_capable(struct brcmf_chip *pub); +- +- #endif /* BRCMF_AXIDMP_H */ +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -509,7 +509,7 @@ static void brcmf_pcie_attach(struct brc +- +- static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo) +- { +-- brcmf_chip_enter_download(devinfo->ci); +-+ brcmf_chip_set_passive(devinfo->ci); +- +- if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) { +- brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4); +-@@ -536,7 +536,7 @@ static int brcmf_pcie_exit_download_stat +- brcmf_chip_resetcore(core, 0, 0, 0); +- } +- +-- return !brcmf_chip_exit_download(devinfo->ci, resetintr); +-+ return !brcmf_chip_set_active(devinfo->ci, resetintr); +- } +- +- +-@@ -1566,8 +1566,8 @@ static int brcmf_pcie_buscoreprep(void * +- } +- +- +--static void brcmf_pcie_buscore_exitdl(void *ctx, struct brcmf_chip *chip, +-- u32 rstvec) +-+static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip, +-+ u32 rstvec) +- { +- struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; +- +-@@ -1577,7 +1577,7 @@ static void brcmf_pcie_buscore_exitdl(vo +- +- static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { +- .prepare = brcmf_pcie_buscoreprep, +-- .exit_dl = brcmf_pcie_buscore_exitdl, +-+ .activate = brcmf_pcie_buscore_activate, +- .read32 = brcmf_pcie_buscore_read32, +- .write32 = brcmf_pcie_buscore_write32, +- }; +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -3357,7 +3357,7 @@ static int brcmf_sdio_download_firmware( +- brcmf_sdio_clkctl(bus, CLK_AVAIL, false); +- +- /* Keep arm in reset */ +-- brcmf_chip_enter_download(bus->ci); +-+ brcmf_chip_set_passive(bus->ci); +- +- rstvec = get_unaligned_le32(fw->data); +- brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec); +-@@ -3378,7 +3378,7 @@ static int brcmf_sdio_download_firmware( +- } +- +- /* Take arm out of reset */ +-- if (!brcmf_chip_exit_download(bus->ci, rstvec)) { +-+ if (!brcmf_chip_set_active(bus->ci, rstvec)) { +- brcmf_err("error getting out of ARM core reset\n"); +- goto err; +- } +-@@ -3771,8 +3771,8 @@ static int brcmf_sdio_buscoreprep(void * +- return 0; +- } +- +--static void brcmf_sdio_buscore_exitdl(void *ctx, struct brcmf_chip *chip, +-- u32 rstvec) +-+static void brcmf_sdio_buscore_activate(void *ctx, struct brcmf_chip *chip, +-+ u32 rstvec) +- { +- struct brcmf_sdio_dev *sdiodev = ctx; +- struct brcmf_core *core; +-@@ -3815,7 +3815,7 @@ static void brcmf_sdio_buscore_write32(v +- +- static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = { +- .prepare = brcmf_sdio_buscoreprep, +-- .exit_dl = brcmf_sdio_buscore_exitdl, +-+ .activate = brcmf_sdio_buscore_activate, +- .read32 = brcmf_sdio_buscore_read32, +- .write32 = brcmf_sdio_buscore_write32, +- }; +-@@ -4239,12 +4239,11 @@ void brcmf_sdio_remove(struct brcmf_sdio +- sdio_claim_host(bus->sdiodev->func[1]); +- brcmf_sdio_clkctl(bus, CLK_AVAIL, false); +- /* Leave the device in state where it is +-- * 'quiet'. This is done by putting it in +-- * download_state which essentially resets +-- * all necessary cores. +-+ * 'passive'. This is done by resetting all +-+ * necessary cores. +- */ +- msleep(20); +-- brcmf_chip_enter_download(bus->ci); +-+ brcmf_chip_set_passive(bus->ci); +- brcmf_sdio_clkctl(bus, CLK_NONE, false); +- sdio_release_host(bus->sdiodev->func[1]); +- } +diff --git a/package/kernel/mac80211/patches/342-brcmfmac-assure-device-is-ready-for-download-after-b.patch b/package/kernel/mac80211/patches/342-brcmfmac-assure-device-is-ready-for-download-after-b.patch +deleted file mode 100644 +index 6b1dd81..0000000 +--- a/package/kernel/mac80211/patches/342-brcmfmac-assure-device-is-ready-for-download-after-b.patch ++++ /dev/null +@@ -1,61 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 11 Mar 2015 16:11:30 +0100 +-Subject: [PATCH] brcmfmac: assure device is ready for download after +- brcmf_chip_attach() +- +-Make the brcmf_chip_attach() function responsible for putting the +-device in a state where it is accessible for firmware download. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-@@ -786,12 +786,6 @@ static int brcmf_chip_setup(struct brcmf +- if (chip->ops->setup) +- ret = chip->ops->setup(chip->ctx, pub); +- +-- /* +-- * Make sure any on-chip ARM is off (in case strapping is wrong), +-- * or downloaded code was already running. +-- */ +-- brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3); +-- brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CR4); +- return ret; +- } +- +-@@ -833,6 +827,8 @@ struct brcmf_chip *brcmf_chip_attach(voi +- if (err < 0) +- goto fail; +- +-+ /* assure chip is passive for download */ +-+ brcmf_chip_set_passive(&chip->pub); +- return &chip->pub; +- +- fail: +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -509,8 +509,6 @@ static void brcmf_pcie_attach(struct brc +- +- static int brcmf_pcie_enter_download_state(struct brcmf_pciedev_info *devinfo) +- { +-- brcmf_chip_set_passive(devinfo->ci); +-- +- if (devinfo->ci->chip == BRCM_CC_43602_CHIP_ID) { +- brcmf_pcie_select_core(devinfo, BCMA_CORE_ARM_CR4); +- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_ARMCR4REG_BANKIDX, +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -3356,9 +3356,6 @@ static int brcmf_sdio_download_firmware( +- sdio_claim_host(bus->sdiodev->func[1]); +- brcmf_sdio_clkctl(bus, CLK_AVAIL, false); +- +-- /* Keep arm in reset */ +-- brcmf_chip_set_passive(bus->ci); +-- +- rstvec = get_unaligned_le32(fw->data); +- brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec); +- +diff --git a/package/kernel/mac80211/patches/343-brcmfmac-extract-ram-size-info-from-internal-memory-.patch b/package/kernel/mac80211/patches/343-brcmfmac-extract-ram-size-info-from-internal-memory-.patch +deleted file mode 100644 +index bcc2ed4..0000000 +--- a/package/kernel/mac80211/patches/343-brcmfmac-extract-ram-size-info-from-internal-memory-.patch ++++ /dev/null +@@ -1,367 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 11 Mar 2015 16:11:31 +0100 +-Subject: [PATCH] brcmfmac: extract ram size info from internal memory +- registers +- +-Instead of hard-coded memory sizes it is possible to obtain that +-information from the internal memory registers. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-@@ -100,9 +100,6 @@ +- #define BCM4329_CORE_SOCRAM_BASE 0x18003000 +- /* ARM Cortex M3 core, ID 0x82a */ +- #define BCM4329_CORE_ARM_BASE 0x18002000 +--#define BCM4329_RAMSIZE 0x48000 +--/* bcm43143 */ +--#define BCM43143_RAMSIZE 0x70000 +- +- #define CORE_SB(base, field) \ +- (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) +-@@ -150,6 +147,78 @@ struct sbconfig { +- u32 sbidhigh; /* identification */ +- }; +- +-+/* bankidx and bankinfo reg defines corerev >= 8 */ +-+#define SOCRAM_BANKINFO_RETNTRAM_MASK 0x00010000 +-+#define SOCRAM_BANKINFO_SZMASK 0x0000007f +-+#define SOCRAM_BANKIDX_ROM_MASK 0x00000100 +-+ +-+#define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 +-+/* socram bankinfo memtype */ +-+#define SOCRAM_MEMTYPE_RAM 0 +-+#define SOCRAM_MEMTYPE_R0M 1 +-+#define SOCRAM_MEMTYPE_DEVRAM 2 +-+ +-+#define SOCRAM_BANKINFO_SZBASE 8192 +-+#define SRCI_LSS_MASK 0x00f00000 +-+#define SRCI_LSS_SHIFT 20 +-+#define SRCI_SRNB_MASK 0xf0 +-+#define SRCI_SRNB_SHIFT 4 +-+#define SRCI_SRBSZ_MASK 0xf +-+#define SRCI_SRBSZ_SHIFT 0 +-+#define SR_BSZ_BASE 14 +-+ +-+struct sbsocramregs { +-+ u32 coreinfo; +-+ u32 bwalloc; +-+ u32 extracoreinfo; +-+ u32 biststat; +-+ u32 bankidx; +-+ u32 standbyctrl; +-+ +-+ u32 errlogstatus; /* rev 6 */ +-+ u32 errlogaddr; /* rev 6 */ +-+ /* used for patching rev 3 & 5 */ +-+ u32 cambankidx; +-+ u32 cambankstandbyctrl; +-+ u32 cambankpatchctrl; +-+ u32 cambankpatchtblbaseaddr; +-+ u32 cambankcmdreg; +-+ u32 cambankdatareg; +-+ u32 cambankmaskreg; +-+ u32 PAD[1]; +-+ u32 bankinfo; /* corev 8 */ +-+ u32 bankpda; +-+ u32 PAD[14]; +-+ u32 extmemconfig; +-+ u32 extmemparitycsr; +-+ u32 extmemparityerrdata; +-+ u32 extmemparityerrcnt; +-+ u32 extmemwrctrlandsize; +-+ u32 PAD[84]; +-+ u32 workaround; +-+ u32 pwrctl; /* corerev >= 2 */ +-+ u32 PAD[133]; +-+ u32 sr_control; /* corerev >= 15 */ +-+ u32 sr_status; /* corerev >= 15 */ +-+ u32 sr_address; /* corerev >= 15 */ +-+ u32 sr_data; /* corerev >= 15 */ +-+}; +-+ +-+#define SOCRAMREGOFFS(_f) offsetof(struct sbsocramregs, _f) +-+ +-+#define ARMCR4_CAP (0x04) +-+#define ARMCR4_BANKIDX (0x40) +-+#define ARMCR4_BANKINFO (0x44) +-+#define ARMCR4_BANKPDA (0x4C) +-+ +-+#define ARMCR4_TCBBNB_MASK 0xf0 +-+#define ARMCR4_TCBBNB_SHIFT 4 +-+#define ARMCR4_TCBANB_MASK 0xf +-+#define ARMCR4_TCBANB_SHIFT 0 +-+ +-+#define ARMCR4_BSZ_MASK 0x3f +-+#define ARMCR4_BSZ_MULT 8192 +-+ +- struct brcmf_core_priv { +- struct brcmf_core pub; +- u32 wrapbase; +-@@ -443,10 +512,6 @@ static int brcmf_chip_cores_check(struct +- break; +- case BCMA_CORE_ARM_CR4: +- cpu_found = true; +-- if (ci->pub.rambase == 0) { +-- brcmf_err("RAM base not provided with ARM CR4 core\n"); +-- return -ENOMEM; +-- } +- break; +- default: +- break; +-@@ -462,60 +527,160 @@ static int brcmf_chip_cores_check(struct +- brcmf_err("RAM core not provided with ARM CM3 core\n"); +- return -ENODEV; +- } +-- if (!ci->pub.ramsize) { +-- brcmf_err("RAM size is undetermined\n"); +-- return -ENOMEM; +-- } +- return 0; +- } +- +--static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) +-+static u32 brcmf_chip_core_read32(struct brcmf_core_priv *core, u16 reg) +- { +-- switch (ci->pub.chip) { +-- case BRCM_CC_4329_CHIP_ID: +-- ci->pub.ramsize = BCM4329_RAMSIZE; +-- break; +-- case BRCM_CC_43143_CHIP_ID: +-- ci->pub.ramsize = BCM43143_RAMSIZE; +-- break; +-- case BRCM_CC_43241_CHIP_ID: +-- ci->pub.ramsize = 0x90000; +-- break; +-- case BRCM_CC_4330_CHIP_ID: +-- ci->pub.ramsize = 0x48000; +-- break; +-+ return core->chip->ops->read32(core->chip->ctx, core->pub.base + reg); +-+} +-+ +-+static void brcmf_chip_core_write32(struct brcmf_core_priv *core, +-+ u16 reg, u32 val) +-+{ +-+ core->chip->ops->write32(core->chip->ctx, core->pub.base + reg, val); +-+} +-+ +-+static bool brcmf_chip_socram_banksize(struct brcmf_core_priv *core, u8 idx, +-+ u32 *banksize) +-+{ +-+ u32 bankinfo; +-+ u32 bankidx = (SOCRAM_MEMTYPE_RAM << SOCRAM_BANKIDX_MEMTYPE_SHIFT); +-+ +-+ bankidx |= idx; +-+ brcmf_chip_core_write32(core, SOCRAMREGOFFS(bankidx), bankidx); +-+ bankinfo = brcmf_chip_core_read32(core, SOCRAMREGOFFS(bankinfo)); +-+ *banksize = (bankinfo & SOCRAM_BANKINFO_SZMASK) + 1; +-+ *banksize *= SOCRAM_BANKINFO_SZBASE; +-+ return !!(bankinfo & SOCRAM_BANKINFO_RETNTRAM_MASK); +-+} +-+ +-+static void brcmf_chip_socram_ramsize(struct brcmf_core_priv *sr, u32 *ramsize, +-+ u32 *srsize) +-+{ +-+ u32 coreinfo; +-+ uint nb, banksize, lss; +-+ bool retent; +-+ int i; +-+ +-+ *ramsize = 0; +-+ *srsize = 0; +-+ +-+ if (WARN_ON(sr->pub.rev < 4)) +-+ return; +-+ +-+ if (!brcmf_chip_iscoreup(&sr->pub)) +-+ brcmf_chip_resetcore(&sr->pub, 0, 0, 0); +-+ +-+ /* Get info for determining size */ +-+ coreinfo = brcmf_chip_core_read32(sr, SOCRAMREGOFFS(coreinfo)); +-+ nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; +-+ +-+ if ((sr->pub.rev <= 7) || (sr->pub.rev == 12)) { +-+ banksize = (coreinfo & SRCI_SRBSZ_MASK); +-+ lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; +-+ if (lss != 0) +-+ nb--; +-+ *ramsize = nb * (1 << (banksize + SR_BSZ_BASE)); +-+ if (lss != 0) +-+ *ramsize += (1 << ((lss - 1) + SR_BSZ_BASE)); +-+ } else { +-+ nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; +-+ for (i = 0; i < nb; i++) { +-+ retent = brcmf_chip_socram_banksize(sr, i, &banksize); +-+ *ramsize += banksize; +-+ if (retent) +-+ *srsize += banksize; +-+ } +-+ } +-+ +-+ /* hardcoded save&restore memory sizes */ +-+ switch (sr->chip->pub.chip) { +- case BRCM_CC_4334_CHIP_ID: +-- case BRCM_CC_43340_CHIP_ID: +-- ci->pub.ramsize = 0x80000; +-+ if (sr->chip->pub.chiprev < 2) +-+ *srsize = (32 * 1024); +- break; +-- case BRCM_CC_4335_CHIP_ID: +-- ci->pub.ramsize = 0xc0000; +-- ci->pub.rambase = 0x180000; +-- break; +-- case BRCM_CC_43362_CHIP_ID: +-- ci->pub.ramsize = 0x3c000; +-+ default: +- break; +-+ } +-+} +-+ +-+/** Return the TCM-RAM size of the ARMCR4 core. */ +-+static u32 brcmf_chip_tcm_ramsize(struct brcmf_core_priv *cr4) +-+{ +-+ u32 corecap; +-+ u32 memsize = 0; +-+ u32 nab; +-+ u32 nbb; +-+ u32 totb; +-+ u32 bxinfo; +-+ u32 idx; +-+ +-+ corecap = brcmf_chip_core_read32(cr4, ARMCR4_CAP); +-+ +-+ nab = (corecap & ARMCR4_TCBANB_MASK) >> ARMCR4_TCBANB_SHIFT; +-+ nbb = (corecap & ARMCR4_TCBBNB_MASK) >> ARMCR4_TCBBNB_SHIFT; +-+ totb = nab + nbb; +-+ +-+ for (idx = 0; idx < totb; idx++) { +-+ brcmf_chip_core_write32(cr4, ARMCR4_BANKIDX, idx); +-+ bxinfo = brcmf_chip_core_read32(cr4, ARMCR4_BANKINFO); +-+ memsize += ((bxinfo & ARMCR4_BSZ_MASK) + 1) * ARMCR4_BSZ_MULT; +-+ } +-+ +-+ return memsize; +-+} +-+ +-+static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci) +-+{ +-+ switch (ci->pub.chip) { +- case BRCM_CC_4345_CHIP_ID: +-- ci->pub.ramsize = 0xc8000; +-- ci->pub.rambase = 0x198000; +-- break; +-+ return 0x198000; +-+ case BRCM_CC_4335_CHIP_ID: +- case BRCM_CC_4339_CHIP_ID: +- case BRCM_CC_4354_CHIP_ID: +- case BRCM_CC_4356_CHIP_ID: +- case BRCM_CC_43567_CHIP_ID: +- case BRCM_CC_43569_CHIP_ID: +- case BRCM_CC_43570_CHIP_ID: +-- ci->pub.ramsize = 0xc0000; +-- ci->pub.rambase = 0x180000; +-- break; +- case BRCM_CC_43602_CHIP_ID: +-- ci->pub.ramsize = 0xf0000; +-- ci->pub.rambase = 0x180000; +-- break; +-+ return 0x180000; +- default: +- brcmf_err("unknown chip: %s\n", ci->pub.name); +- break; +- } +-+ return 0; +-+} +-+ +-+static int brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci) +-+{ +-+ struct brcmf_core_priv *mem_core; +-+ struct brcmf_core *mem; +-+ +-+ mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_ARM_CR4); +-+ if (mem) { +-+ mem_core = container_of(mem, struct brcmf_core_priv, pub); +-+ ci->pub.ramsize = brcmf_chip_tcm_ramsize(mem_core); +-+ ci->pub.rambase = brcmf_chip_tcm_rambase(ci); +-+ if (!ci->pub.rambase) { +-+ brcmf_err("RAM base not provided with ARM CR4 core\n"); +-+ return -EINVAL; +-+ } +-+ } else { +-+ mem = brcmf_chip_get_core(&ci->pub, BCMA_CORE_INTERNAL_MEM); +-+ mem_core = container_of(mem, struct brcmf_core_priv, pub); +-+ brcmf_chip_socram_ramsize(mem_core, &ci->pub.ramsize, +-+ &ci->pub.srsize); +-+ } +-+ brcmf_dbg(INFO, "RAM: base=0x%x size=%d (0x%x) sr=%d (0x%x)\n", +-+ ci->pub.rambase, ci->pub.ramsize, ci->pub.ramsize, +-+ ci->pub.srsize, ci->pub.srsize); +-+ +-+ if (!ci->pub.ramsize) { +-+ brcmf_err("RAM size is undetermined\n"); +-+ return -ENOMEM; +-+ } +-+ return 0; +- } +- +- static u32 brcmf_chip_dmp_get_desc(struct brcmf_chip_priv *ci, u32 *eromaddr, +-@@ -668,6 +833,7 @@ static int brcmf_chip_recognition(struct +- struct brcmf_core *core; +- u32 regdata; +- u32 socitype; +-+ int ret; +- +- /* Get CC core rev +- * Chipid is assume to be at offset 0 from SI_ENUM_BASE +-@@ -720,9 +886,13 @@ static int brcmf_chip_recognition(struct +- return -ENODEV; +- } +- +-- brcmf_chip_get_raminfo(ci); +-- +-- return brcmf_chip_cores_check(ci); +-+ ret = brcmf_chip_cores_check(ci); +-+ if (ret) +-+ return ret; +-+ +-+ /* assure chip is passive for core access */ +-+ brcmf_chip_set_passive(&ci->pub); +-+ return brcmf_chip_get_raminfo(ci); +- } +- +- static void brcmf_chip_disable_arm(struct brcmf_chip_priv *chip, u16 id) +-@@ -827,8 +997,6 @@ struct brcmf_chip *brcmf_chip_attach(voi +- if (err < 0) +- goto fail; +- +-- /* assure chip is passive for download */ +-- brcmf_chip_set_passive(&chip->pub); +- return &chip->pub; +- +- fail: +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h +-@@ -30,7 +30,8 @@ +- * @pmucaps: PMU capabilities. +- * @pmurev: PMU revision. +- * @rambase: RAM base address (only applicable for ARM CR4 chips). +-- * @ramsize: amount of RAM on chip. +-+ * @ramsize: amount of RAM on chip including retention. +-+ * @srsize: amount of retention RAM on chip. +- * @name: string representation of the chip identifier. +- */ +- struct brcmf_chip { +-@@ -41,6 +42,7 @@ struct brcmf_chip { +- u32 pmurev; +- u32 rambase; +- u32 ramsize; +-+ u32 srsize; +- char name[8]; +- }; +- +diff --git a/package/kernel/mac80211/patches/344-brcmfmac-take-save-restore-memory-into-account-for-S.patch b/package/kernel/mac80211/patches/344-brcmfmac-take-save-restore-memory-into-account-for-S.patch +deleted file mode 100644 +index 69618a7..0000000 +--- a/package/kernel/mac80211/patches/344-brcmfmac-take-save-restore-memory-into-account-for-S.patch ++++ /dev/null +@@ -1,96 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 11 Mar 2015 16:11:32 +0100 +-Subject: [PATCH] brcmfmac: take save&restore memory into account for SDIO +- shared info +- +-The firmware provides pointer to SDIO shared information at end of +-RAM during firmware initialization. End of RAM is obviously determined +-by the actual ram size, but part of that may be used for save&restore +-memory. In that case another location in RAM will hold the pointer. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -1067,44 +1067,47 @@ static inline bool brcmf_sdio_valid_shar +- static int brcmf_sdio_readshared(struct brcmf_sdio *bus, +- struct sdpcm_shared *sh) +- { +-- u32 addr; +-+ u32 addr = 0; +- int rv; +- u32 shaddr = 0; +- struct sdpcm_shared_le sh_le; +- __le32 addr_le; +- +-- shaddr = bus->ci->rambase + bus->ci->ramsize - 4; +-+ sdio_claim_host(bus->sdiodev->func[1]); +-+ brcmf_sdio_bus_sleep(bus, false, false); +- +- /* +- * Read last word in socram to determine +- * address of sdpcm_shared structure +- */ +-- sdio_claim_host(bus->sdiodev->func[1]); +-- brcmf_sdio_bus_sleep(bus, false, false); +-- rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, (u8 *)&addr_le, 4); +-- sdio_release_host(bus->sdiodev->func[1]); +-+ shaddr = bus->ci->rambase + bus->ci->ramsize - 4; +-+ if (!bus->ci->rambase && brcmf_chip_sr_capable(bus->ci)) +-+ shaddr -= bus->ci->srsize; +-+ rv = brcmf_sdiod_ramrw(bus->sdiodev, false, shaddr, +-+ (u8 *)&addr_le, 4); +- if (rv < 0) +-- return rv; +-- +-- addr = le32_to_cpu(addr_le); +-- +-- brcmf_dbg(SDIO, "sdpcm_shared address 0x%08X\n", addr); +-+ goto fail; +- +- /* +- * Check if addr is valid. +- * NVRAM length at the end of memory should have been overwritten. +- */ +-+ addr = le32_to_cpu(addr_le); +- if (!brcmf_sdio_valid_shared_address(addr)) { +-- brcmf_err("invalid sdpcm_shared address 0x%08X\n", +-- addr); +-- return -EINVAL; +-+ brcmf_err("invalid sdpcm_shared address 0x%08X\n", addr); +-+ rv = -EINVAL; +-+ goto fail; +- } +- +-+ brcmf_dbg(INFO, "sdpcm_shared address 0x%08X\n", addr); +-+ +- /* Read hndrte_shared structure */ +- rv = brcmf_sdiod_ramrw(bus->sdiodev, false, addr, (u8 *)&sh_le, +- sizeof(struct sdpcm_shared_le)); +- if (rv < 0) +-- return rv; +-+ goto fail; +-+ +-+ sdio_release_host(bus->sdiodev->func[1]); +- +- /* Endianness */ +- sh->flags = le32_to_cpu(sh_le.flags); +-@@ -1121,8 +1124,13 @@ static int brcmf_sdio_readshared(struct +- sh->flags & SDPCM_SHARED_VERSION_MASK); +- return -EPROTO; +- } +-- +- return 0; +-+ +-+fail: +-+ brcmf_err("unable to obtain sdpcm_shared info: rv=%d (addr=0x%x)\n", +-+ rv, addr); +-+ sdio_release_host(bus->sdiodev->func[1]); +-+ return rv; +- } +- +- static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus) +diff --git a/package/kernel/mac80211/patches/345-brcmfmac-fix-watchdog-timer-regression.patch b/package/kernel/mac80211/patches/345-brcmfmac-fix-watchdog-timer-regression.patch +deleted file mode 100644 +index 1b10dbb..0000000 +--- a/package/kernel/mac80211/patches/345-brcmfmac-fix-watchdog-timer-regression.patch ++++ /dev/null +@@ -1,59 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 11 Mar 2015 16:11:33 +0100 +-Subject: [PATCH] brcmfmac: fix watchdog timer regression +- +-The watchdog timer is used to put the device in a low-power mode when +-it is idle for some time. This timer is stopped during that mode and +-should be restarted upon activity. This has been broken by commit +-d4150fced0365 ("brcmfmac: Simplify watchdog sleep."). This patch +-restores the behaviour as it was before that commit. +- +-Reported-by: Pontus Fuchs +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -972,7 +972,6 @@ static int brcmf_sdio_clkctl(struct brcm +- brcmf_sdio_sdclk(bus, true); +- /* Now request HT Avail on the backplane */ +- brcmf_sdio_htclk(bus, true, pendok); +-- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); +- break; +- +- case CLK_SDONLY: +-@@ -984,7 +983,6 @@ static int brcmf_sdio_clkctl(struct brcm +- else +- brcmf_err("request for %d -> %d\n", +- bus->clkstate, target); +-- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); +- break; +- +- case CLK_NONE: +-@@ -993,7 +991,6 @@ static int brcmf_sdio_clkctl(struct brcm +- brcmf_sdio_htclk(bus, false, false); +- /* Now remove the SD clock */ +- brcmf_sdio_sdclk(bus, false); +-- brcmf_sdio_wd_timer(bus, 0); +- break; +- } +- #ifdef DEBUG +-@@ -1048,6 +1045,7 @@ end: +- brcmf_sdio_clkctl(bus, CLK_NONE, pendok); +- } else { +- brcmf_sdio_clkctl(bus, CLK_AVAIL, pendok); +-+ brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS); +- } +- bus->sleeping = sleep; +- brcmf_dbg(SDIO, "new state %s\n", +-@@ -4242,6 +4240,7 @@ void brcmf_sdio_remove(struct brcmf_sdio +- if (bus->ci) { +- if (bus->sdiodev->state != BRCMF_SDIOD_NOMEDIUM) { +- sdio_claim_host(bus->sdiodev->func[1]); +-+ brcmf_sdio_wd_timer(bus, 0); +- brcmf_sdio_clkctl(bus, CLK_AVAIL, false); +- /* Leave the device in state where it is +- * 'passive'. This is done by resetting all +diff --git a/package/kernel/mac80211/patches/346-brcmfmac-avoid-runtime-pm-for-sdio-host-controller.patch b/package/kernel/mac80211/patches/346-brcmfmac-avoid-runtime-pm-for-sdio-host-controller.patch +deleted file mode 100644 +index af76f13..0000000 +--- a/package/kernel/mac80211/patches/346-brcmfmac-avoid-runtime-pm-for-sdio-host-controller.patch ++++ /dev/null +@@ -1,44 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 18 Mar 2015 13:25:21 +0100 +-Subject: [PATCH] brcmfmac: avoid runtime-pm for sdio host controller +- +-Several host controllers supporting runtime-pm are causing issues +-with our sdio wireless cards because they disable the sdio interrupt +-upon going into runtime suspend. This patch avoids that by doing +-a pm_runtime_forbid() call during the probe. Tested with Sony Vaio +-Duo 13 which uses sdhci-acpi host controller. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-@@ -29,6 +29,7 @@ +- #include +- #include +- #include +-+#include +- #include +- #include +- #include +-@@ -1006,6 +1007,7 @@ static int brcmf_sdiod_remove(struct brc +- sg_free_table(&sdiodev->sgtable); +- sdiodev->sbwad = 0; +- +-+ pm_runtime_allow(sdiodev->func[1]->card->host->parent); +- return 0; +- } +- +-@@ -1074,7 +1076,7 @@ static int brcmf_sdiod_probe(struct brcm +- ret = -ENODEV; +- goto out; +- } +-- +-+ pm_runtime_forbid(host->parent); +- out: +- if (ret) +- brcmf_sdiod_remove(sdiodev); +diff --git a/package/kernel/mac80211/patches/347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch b/package/kernel/mac80211/patches/347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch +deleted file mode 100644 +index c419cc6..0000000 +--- a/package/kernel/mac80211/patches/347-brcmfmac-Add-necessary-memory-barriers-for-SDIO.patch ++++ /dev/null +@@ -1,171 +0,0 @@ +-From: Hante Meuleman +-Date: Wed, 18 Mar 2015 13:25:22 +0100 +-Subject: [PATCH] brcmfmac: Add necessary memory barriers for SDIO. +- +-SDIO uses a thread to handle all communication with the device, +-for this data is exchanged between threads. This data needs proper +-memory barriers to make sure that data "exchange" is going correct. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Daniel (Deognyoun) Kim +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -507,8 +507,8 @@ struct brcmf_sdio { +- +- struct workqueue_struct *brcmf_wq; +- struct work_struct datawork; +-- atomic_t dpc_tskcnt; +-- atomic_t dpc_running; +-+ bool dpc_triggered; +-+ bool dpc_running; +- +- bool txoff; /* Transmit flow-controlled */ +- struct brcmf_sdio_count sdcnt; +-@@ -2713,6 +2713,7 @@ static void brcmf_sdio_dpc(struct brcmf_ +- err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, +- bus->ctrl_frame_len); +- bus->ctrl_frame_err = err; +-+ wmb(); +- bus->ctrl_frame_stat = false; +- } +- sdio_release_host(bus->sdiodev->func[1]); +-@@ -2734,6 +2735,7 @@ static void brcmf_sdio_dpc(struct brcmf_ +- sdio_claim_host(bus->sdiodev->func[1]); +- if (bus->ctrl_frame_stat) { +- bus->ctrl_frame_err = -ENODEV; +-+ wmb(); +- bus->ctrl_frame_stat = false; +- brcmf_sdio_wait_event_wakeup(bus); +- } +-@@ -2744,7 +2746,7 @@ static void brcmf_sdio_dpc(struct brcmf_ +- (!atomic_read(&bus->fcstate) && +- brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && +- data_ok(bus))) { +-- atomic_inc(&bus->dpc_tskcnt); +-+ bus->dpc_triggered = true; +- } +- } +- +-@@ -2940,6 +2942,7 @@ brcmf_sdio_bus_txctl(struct device *dev, +- /* Send from dpc */ +- bus->ctrl_frame_buf = msg; +- bus->ctrl_frame_len = msglen; +-+ wmb(); +- bus->ctrl_frame_stat = true; +- +- brcmf_sdio_trigger_dpc(bus); +-@@ -2958,6 +2961,7 @@ brcmf_sdio_bus_txctl(struct device *dev, +- if (!ret) { +- brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n", +- bus->ctrl_frame_err); +-+ rmb(); +- ret = bus->ctrl_frame_err; +- } +- +-@@ -3526,8 +3530,8 @@ done: +- +- void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus) +- { +-- if (atomic_read(&bus->dpc_tskcnt) == 0) { +-- atomic_inc(&bus->dpc_tskcnt); +-+ if (!bus->dpc_triggered) { +-+ bus->dpc_triggered = true; +- queue_work(bus->brcmf_wq, &bus->datawork); +- } +- } +-@@ -3558,7 +3562,7 @@ void brcmf_sdio_isr(struct brcmf_sdio *b +- if (!bus->intr) +- brcmf_err("isr w/o interrupt configured!\n"); +- +-- atomic_inc(&bus->dpc_tskcnt); +-+ bus->dpc_triggered = true; +- queue_work(bus->brcmf_wq, &bus->datawork); +- } +- +-@@ -3578,7 +3582,7 @@ static void brcmf_sdio_bus_watchdog(stru +- if (!bus->intr || +- (bus->sdcnt.intrcount == bus->sdcnt.lastintrs)) { +- +-- if (atomic_read(&bus->dpc_tskcnt) == 0) { +-+ if (!bus->dpc_triggered) { +- u8 devpend; +- +- sdio_claim_host(bus->sdiodev->func[1]); +-@@ -3596,7 +3600,7 @@ static void brcmf_sdio_bus_watchdog(stru +- bus->sdcnt.pollcnt++; +- atomic_set(&bus->ipend, 1); +- +-- atomic_inc(&bus->dpc_tskcnt); +-+ bus->dpc_triggered = true; +- queue_work(bus->brcmf_wq, &bus->datawork); +- } +- } +-@@ -3623,17 +3627,21 @@ static void brcmf_sdio_bus_watchdog(stru +- #endif /* DEBUG */ +- +- /* On idle timeout clear activity flag and/or turn off clock */ +-- if ((atomic_read(&bus->dpc_tskcnt) == 0) && +-- (atomic_read(&bus->dpc_running) == 0) && +-- (bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { +-- bus->idlecount++; +-- if (bus->idlecount > bus->idletime) { +-- brcmf_dbg(SDIO, "idle\n"); +-- sdio_claim_host(bus->sdiodev->func[1]); +-- brcmf_sdio_wd_timer(bus, 0); +-+ if (!bus->dpc_triggered) { +-+ rmb(); +-+ if ((!bus->dpc_running) && (bus->idletime > 0) && +-+ (bus->clkstate == CLK_AVAIL)) { +-+ bus->idlecount++; +-+ if (bus->idlecount > bus->idletime) { +-+ brcmf_dbg(SDIO, "idle\n"); +-+ sdio_claim_host(bus->sdiodev->func[1]); +-+ brcmf_sdio_wd_timer(bus, 0); +-+ bus->idlecount = 0; +-+ brcmf_sdio_bus_sleep(bus, true, false); +-+ sdio_release_host(bus->sdiodev->func[1]); +-+ } +-+ } else { +- bus->idlecount = 0; +-- brcmf_sdio_bus_sleep(bus, true, false); +-- sdio_release_host(bus->sdiodev->func[1]); +- } +- } else { +- bus->idlecount = 0; +-@@ -3645,13 +3653,14 @@ static void brcmf_sdio_dataworker(struct +- struct brcmf_sdio *bus = container_of(work, struct brcmf_sdio, +- datawork); +- +-- while (atomic_read(&bus->dpc_tskcnt)) { +-- atomic_set(&bus->dpc_running, 1); +-- atomic_set(&bus->dpc_tskcnt, 0); +-+ bus->dpc_running = true; +-+ wmb(); +-+ while (ACCESS_ONCE(bus->dpc_triggered)) { +-+ bus->dpc_triggered = false; +- brcmf_sdio_dpc(bus); +- bus->idlecount = 0; +-- atomic_set(&bus->dpc_running, 0); +- } +-+ bus->dpc_running = false; +- if (brcmf_sdiod_freezing(bus->sdiodev)) { +- brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DOWN); +- brcmf_sdiod_try_freeze(bus->sdiodev); +-@@ -4144,8 +4153,8 @@ struct brcmf_sdio *brcmf_sdio_probe(stru +- bus->watchdog_tsk = NULL; +- } +- /* Initialize DPC thread */ +-- atomic_set(&bus->dpc_tskcnt, 0); +-- atomic_set(&bus->dpc_running, 0); +-+ bus->dpc_triggered = false; +-+ bus->dpc_running = false; +- +- /* Assign bus interface call back */ +- bus->sdiodev->bus_if->dev = bus->sdiodev->dev; +diff --git a/package/kernel/mac80211/patches/348-brcmfmac-Remove-unnecessary-new-line-in-pcie-console.patch b/package/kernel/mac80211/patches/348-brcmfmac-Remove-unnecessary-new-line-in-pcie-console.patch +deleted file mode 100644 +index 1bc98a0..0000000 +--- a/package/kernel/mac80211/patches/348-brcmfmac-Remove-unnecessary-new-line-in-pcie-console.patch ++++ /dev/null +@@ -1,26 +0,0 @@ +-From: Hante Meuleman +-Date: Wed, 18 Mar 2015 13:25:24 +0100 +-Subject: [PATCH] brcmfmac: Remove unnecessary new-line in pcie console +- logging. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -651,10 +651,9 @@ static void brcmf_pcie_bus_console_read( +- console->log_str[console->log_idx] = ch; +- console->log_idx++; +- } +-- +- if (ch == '\n') { +- console->log_str[console->log_idx] = 0; +-- brcmf_dbg(PCIE, "CONSOLE: %s\n", console->log_str); +-+ brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str); +- console->log_idx = 0; +- } +- } +diff --git a/package/kernel/mac80211/patches/349-brcmfmac-add-MODULE_FIRMWARE-macros-for-bcm4356-PCIe.patch b/package/kernel/mac80211/patches/349-brcmfmac-add-MODULE_FIRMWARE-macros-for-bcm4356-PCIe.patch +deleted file mode 100644 +index fcf0bf3..0000000 +--- a/package/kernel/mac80211/patches/349-brcmfmac-add-MODULE_FIRMWARE-macros-for-bcm4356-PCIe.patch ++++ /dev/null +@@ -1,26 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 18 Mar 2015 13:25:25 +0100 +-Subject: [PATCH] brcmfmac: add MODULE_FIRMWARE() macros for bcm4356 PCIe +- device +- +-The BCM4356 PCIe wireless device was added recently but overlooked +-the fact that the MODULE_FIRMWARE() macros were missing for the +-firmwares needed by this device. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -189,6 +189,8 @@ MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME +- MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_4354_FW_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_4354_NVRAM_NAME); +-+MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME); +-+MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME); +- +diff --git a/package/kernel/mac80211/patches/350-brcmfmac-add-support-for-BCM43430-SDIO-chipset.patch b/package/kernel/mac80211/patches/350-brcmfmac-add-support-for-BCM43430-SDIO-chipset.patch +deleted file mode 100644 +index b3e9bc9..0000000 +--- a/package/kernel/mac80211/patches/350-brcmfmac-add-support-for-BCM43430-SDIO-chipset.patch ++++ /dev/null +@@ -1,138 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 18 Mar 2015 13:25:26 +0100 +-Subject: [PATCH] brcmfmac: add support for BCM43430 SDIO chipset +- +-This patch added support for the BCM43430 802.11n SDIO chipset. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Daniel (Deognyoun) Kim +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-@@ -1098,6 +1098,7 @@ static const struct sdio_device_id brcmf +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341), +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362), +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339), +-+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430), +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345), +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354), +- { /* end: all zeroes */ } +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-@@ -600,6 +600,12 @@ static void brcmf_chip_socram_ramsize(st +- if (sr->chip->pub.chiprev < 2) +- *srsize = (32 * 1024); +- break; +-+ case BRCM_CC_43430_CHIP_ID: +-+ /* assume sr for now as we can not check +-+ * firmware sr capability at this point. +-+ */ +-+ *srsize = (64 * 1024); +-+ break; +- default: +- break; +- } +-@@ -1072,6 +1078,7 @@ static void +- brcmf_chip_cm3_set_passive(struct brcmf_chip_priv *chip) +- { +- struct brcmf_core *core; +-+ struct brcmf_core_priv *sr; +- +- brcmf_chip_disable_arm(chip, BCMA_CORE_ARM_CM3); +- core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_80211); +-@@ -1081,6 +1088,13 @@ brcmf_chip_cm3_set_passive(struct brcmf_ +- D11_BCMA_IOCTL_PHYCLOCKEN); +- core = brcmf_chip_get_core(&chip->pub, BCMA_CORE_INTERNAL_MEM); +- brcmf_chip_resetcore(core, 0, 0, 0); +-+ +-+ /* disable bank #3 remap for this device */ +-+ if (chip->pub.chip == BRCM_CC_43430_CHIP_ID) { +-+ sr = container_of(core, struct brcmf_core_priv, pub); +-+ brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankidx), 3); +-+ brcmf_chip_core_write32(sr, SOCRAMREGOFFS(bankpda), 0); +-+ } +- } +- +- static bool brcmf_chip_cm3_set_active(struct brcmf_chip_priv *chip) +-@@ -1188,6 +1202,10 @@ bool brcmf_chip_sr_capable(struct brcmf_ +- addr = CORE_CC_REG(base, chipcontrol_data); +- reg = chip->ops->read32(chip->ctx, addr); +- return (reg & pmu_cc3_mask) != 0; +-+ case BRCM_CC_43430_CHIP_ID: +-+ addr = CORE_CC_REG(base, sr_control1); +-+ reg = chip->ops->read32(chip->ctx, addr); +-+ return reg != 0; +- default: +- addr = CORE_CC_REG(base, pmucapabilities_ext); +- reg = chip->ops->read32(chip->ctx, addr); +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -615,6 +615,8 @@ static const struct sdiod_drive_str sdio +- #define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt" +- #define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin" +- #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" +-+#define BCM43430_FIRMWARE_NAME "brcm/brcmfmac43430-sdio.bin" +-+#define BCM43430_NVRAM_NAME "brcm/brcmfmac43430-sdio.txt" +- #define BCM4345_FIRMWARE_NAME "brcm/brcmfmac4345-sdio.bin" +- #define BCM4345_NVRAM_NAME "brcm/brcmfmac4345-sdio.txt" +- #define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin" +-@@ -640,6 +642,8 @@ MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM43362_NVRAM_NAME); +- MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM4339_NVRAM_NAME); +-+MODULE_FIRMWARE(BCM43430_FIRMWARE_NAME); +-+MODULE_FIRMWARE(BCM43430_NVRAM_NAME); +- MODULE_FIRMWARE(BCM4345_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM4345_NVRAM_NAME); +- MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME); +-@@ -671,6 +675,7 @@ static const struct brcmf_firmware_names +- { BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) }, +- { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, +- { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, +-+ { BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43430) }, +- { BRCM_CC_4345_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4345) }, +- { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } +- }; +---- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +-+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +-@@ -37,6 +37,7 @@ +- #define BRCM_CC_43362_CHIP_ID 43362 +- #define BRCM_CC_4335_CHIP_ID 0x4335 +- #define BRCM_CC_4339_CHIP_ID 0x4339 +-+#define BRCM_CC_43430_CHIP_ID 43430 +- #define BRCM_CC_4345_CHIP_ID 0x4345 +- #define BRCM_CC_4354_CHIP_ID 0x4354 +- #define BRCM_CC_4356_CHIP_ID 0x4356 +---- a/drivers/net/wireless/brcm80211/include/chipcommon.h +-+++ b/drivers/net/wireless/brcm80211/include/chipcommon.h +-@@ -183,7 +183,14 @@ struct chipcregs { +- u8 uart1lsr; +- u8 uart1msr; +- u8 uart1scratch; +-- u32 PAD[126]; +-+ u32 PAD[62]; +-+ +-+ /* save/restore, corerev >= 48 */ +-+ u32 sr_capability; /* 0x500 */ +-+ u32 sr_control0; /* 0x504 */ +-+ u32 sr_control1; /* 0x508 */ +-+ u32 gpio_control; /* 0x50C */ +-+ u32 PAD[60]; +- +- /* PMU registers (corerev >= 20) */ +- u32 pmucontrol; /* 0x600 */ +---- a/include/linux/mmc/sdio_ids.h +-+++ b/include/linux/mmc/sdio_ids.h +-@@ -33,6 +33,7 @@ +- #define SDIO_DEVICE_ID_BROADCOM_43341 0xa94d +- #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335 +- #define SDIO_DEVICE_ID_BROADCOM_43362 0xa962 +-+#define SDIO_DEVICE_ID_BROADCOM_43430 0xa9a6 +- #define SDIO_DEVICE_ID_BROADCOM_4345 0x4345 +- #define SDIO_DEVICE_ID_BROADCOM_4354 0x4354 +- +diff --git a/package/kernel/mac80211/patches/351-brcmfmac-only-support-the-BCM43455-7-device.patch b/package/kernel/mac80211/patches/351-brcmfmac-only-support-the-BCM43455-7-device.patch +deleted file mode 100644 +index c3d7bc2..0000000 +--- a/package/kernel/mac80211/patches/351-brcmfmac-only-support-the-BCM43455-7-device.patch ++++ /dev/null +@@ -1,50 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 18 Mar 2015 13:25:27 +0100 +-Subject: [PATCH] brcmfmac: only support the BCM43455/7 device +- +-Recently support was added for the BCM4345 SDIO chipset by +-commit 9c51026509d7 ("brcmfmac: Add support for BCM4345 SDIO chipset") +-however this was verified using a BCM43455 device, which is +-a more recent revision of the chip. This patch assure that +-older revisions are not probed as they would fail. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Syed Asifful Dayyan +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -617,8 +617,8 @@ static const struct sdiod_drive_str sdio +- #define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt" +- #define BCM43430_FIRMWARE_NAME "brcm/brcmfmac43430-sdio.bin" +- #define BCM43430_NVRAM_NAME "brcm/brcmfmac43430-sdio.txt" +--#define BCM4345_FIRMWARE_NAME "brcm/brcmfmac4345-sdio.bin" +--#define BCM4345_NVRAM_NAME "brcm/brcmfmac4345-sdio.txt" +-+#define BCM43455_FIRMWARE_NAME "brcm/brcmfmac43455-sdio.bin" +-+#define BCM43455_NVRAM_NAME "brcm/brcmfmac43455-sdio.txt" +- #define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin" +- #define BCM4354_NVRAM_NAME "brcm/brcmfmac4354-sdio.txt" +- +-@@ -644,8 +644,8 @@ MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM4339_NVRAM_NAME); +- MODULE_FIRMWARE(BCM43430_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM43430_NVRAM_NAME); +--MODULE_FIRMWARE(BCM4345_FIRMWARE_NAME); +--MODULE_FIRMWARE(BCM4345_NVRAM_NAME); +-+MODULE_FIRMWARE(BCM43455_FIRMWARE_NAME); +-+MODULE_FIRMWARE(BCM43455_NVRAM_NAME); +- MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM4354_NVRAM_NAME); +- +-@@ -676,7 +676,7 @@ static const struct brcmf_firmware_names +- { BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) }, +- { BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) }, +- { BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43430) }, +-- { BRCM_CC_4345_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4345) }, +-+ { BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43455) }, +- { BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) } +- }; +- +diff --git a/package/kernel/mac80211/patches/352-brcmfmac-remove-support-for-unreleased-BCM4354-PCIe.patch b/package/kernel/mac80211/patches/352-brcmfmac-remove-support-for-unreleased-BCM4354-PCIe.patch +deleted file mode 100644 +index a62cfdf..0000000 +--- a/package/kernel/mac80211/patches/352-brcmfmac-remove-support-for-unreleased-BCM4354-PCIe.patch ++++ /dev/null +@@ -1,52 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 18 Mar 2015 13:25:28 +0100 +-Subject: [PATCH] brcmfmac: remove support for unreleased BCM4354 PCIe +- +-There are no known BCM4354 PCIe devices released so removing +-support from the driver until proven otherwise. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -47,8 +47,6 @@ enum brcmf_pcie_state { +- +- #define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin" +- #define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt" +--#define BRCMF_PCIE_4354_FW_NAME "brcm/brcmfmac4354-pcie.bin" +--#define BRCMF_PCIE_4354_NVRAM_NAME "brcm/brcmfmac4354-pcie.txt" +- #define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin" +- #define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt" +- #define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin" +-@@ -187,8 +185,6 @@ enum brcmf_pcie_state { +- +- MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME); +--MODULE_FIRMWARE(BRCMF_PCIE_4354_FW_NAME); +--MODULE_FIRMWARE(BRCMF_PCIE_4354_NVRAM_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); +-@@ -1327,10 +1323,6 @@ static int brcmf_pcie_get_fwnames(struct +- fw_name = BRCMF_PCIE_43602_FW_NAME; +- nvram_name = BRCMF_PCIE_43602_NVRAM_NAME; +- break; +-- case BRCM_CC_4354_CHIP_ID: +-- fw_name = BRCMF_PCIE_4354_FW_NAME; +-- nvram_name = BRCMF_PCIE_4354_NVRAM_NAME; +-- break; +- case BRCM_CC_4356_CHIP_ID: +- fw_name = BRCMF_PCIE_4356_FW_NAME; +- nvram_name = BRCMF_PCIE_4356_NVRAM_NAME; +-@@ -1855,7 +1847,6 @@ cleanup: +- PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_OTHER << 8, 0xffff00, 0 } +- +- static struct pci_device_id brcmf_pcie_devid_table[] = { +-- BRCMF_PCIE_DEVICE(BRCM_PCIE_4354_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID), +diff --git a/package/kernel/mac80211/patches/353-brcmfmac-disable-MBSS-feature-for-BCM43362.patch b/package/kernel/mac80211/patches/353-brcmfmac-disable-MBSS-feature-for-BCM43362.patch +deleted file mode 100644 +index 366ff85..0000000 +--- a/package/kernel/mac80211/patches/353-brcmfmac-disable-MBSS-feature-for-BCM43362.patch ++++ /dev/null +@@ -1,28 +0,0 @@ +-From: Arend van Spriel +-Date: Fri, 20 Mar 2015 22:18:17 +0100 +-Subject: [PATCH] brcmfmac: disable MBSS feature for BCM43362 +- +-The BCM43362 firmware falsely reports it is capable of providing +-MBSS. As a result AP mode no longer works for this device. Therefor +-disable MBSS in the driver for this chipset. +- +-Cc: stable@vger.kernel.org # 3.19.y +-Reported-by: Jorg Krause +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c +-@@ -126,7 +126,8 @@ void brcmf_feat_attach(struct brcmf_pub +- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan"); +- if (drvr->bus_if->wowl_supported) +- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl"); +-- brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); +-+ if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID) +-+ brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); +- +- /* set chip related quirks */ +- switch (drvr->bus_if->chip) { +diff --git a/package/kernel/mac80211/patches/354-brcmfmac-use-static-superset-of-channels-for-wiphy-b.patch b/package/kernel/mac80211/patches/354-brcmfmac-use-static-superset-of-channels-for-wiphy-b.patch +deleted file mode 100644 +index 6e461f6..0000000 +--- a/package/kernel/mac80211/patches/354-brcmfmac-use-static-superset-of-channels-for-wiphy-b.patch ++++ /dev/null +@@ -1,300 +0,0 @@ +-From: Arend van Spriel +-Date: Tue, 14 Apr 2015 20:10:24 +0200 +-Subject: [PATCH] brcmfmac: use static superset of channels for wiphy +- bands +- +-The driver was constructing a list of channels per wiphy band +-by querying the device. This list is not what the hardware is +-able to do as it is already filtered by the country setting in +-the device. As user-space may change the country this would +-require updating the channel list which is not recommended [1]. +-This patch introduces a superset of channels. The individual +-channels are disabled appropriately by querying the device. +- +-[1] http://mid.gmane.org/1426706320.3001.21.camel@sipsolutions.net +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Daniel (Deognyoun) Kim +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -129,13 +129,47 @@ static struct ieee80211_rate __wl_rates[ +- RATETAB_ENT(BRCM_RATE_54M, 0), +- }; +- +--#define wl_a_rates (__wl_rates + 4) +--#define wl_a_rates_size 8 +- #define wl_g_rates (__wl_rates + 0) +--#define wl_g_rates_size 12 +-+#define wl_g_rates_size ARRAY_SIZE(__wl_rates) +-+#define wl_a_rates (__wl_rates + 4) +-+#define wl_a_rates_size (wl_g_rates_size - 4) +-+ +-+#define CHAN2G(_channel, _freq) { \ +-+ .band = IEEE80211_BAND_2GHZ, \ +-+ .center_freq = (_freq), \ +-+ .hw_value = (_channel), \ +-+ .flags = IEEE80211_CHAN_DISABLED, \ +-+ .max_antenna_gain = 0, \ +-+ .max_power = 30, \ +-+} +-+ +-+#define CHAN5G(_channel) { \ +-+ .band = IEEE80211_BAND_5GHZ, \ +-+ .center_freq = 5000 + (5 * (_channel)), \ +-+ .hw_value = (_channel), \ +-+ .flags = IEEE80211_CHAN_DISABLED, \ +-+ .max_antenna_gain = 0, \ +-+ .max_power = 30, \ +-+} +-+ +-+static struct ieee80211_channel __wl_2ghz_channels[] = { +-+ CHAN2G(1, 2412), CHAN2G(2, 2417), CHAN2G(3, 2422), CHAN2G(4, 2427), +-+ CHAN2G(5, 2432), CHAN2G(6, 2437), CHAN2G(7, 2442), CHAN2G(8, 2447), +-+ CHAN2G(9, 2452), CHAN2G(10, 2457), CHAN2G(11, 2462), CHAN2G(12, 2467), +-+ CHAN2G(13, 2472), CHAN2G(14, 2484) +-+}; +-+ +-+static struct ieee80211_channel __wl_5ghz_channels[] = { +-+ CHAN5G(34), CHAN5G(36), CHAN5G(38), CHAN5G(40), CHAN5G(42), +-+ CHAN5G(44), CHAN5G(46), CHAN5G(48), CHAN5G(52), CHAN5G(56), +-+ CHAN5G(60), CHAN5G(64), CHAN5G(100), CHAN5G(104), CHAN5G(108), +-+ CHAN5G(112), CHAN5G(116), CHAN5G(120), CHAN5G(124), CHAN5G(128), +-+ CHAN5G(132), CHAN5G(136), CHAN5G(140), CHAN5G(144), CHAN5G(149), +-+ CHAN5G(153), CHAN5G(157), CHAN5G(161), CHAN5G(165) +-+}; +- +- /* Band templates duplicated per wiphy. The channel info +-- * is filled in after querying the device. +-+ * above is added to the band during setup. +- */ +- static const struct ieee80211_supported_band __wl_band_2ghz = { +- .band = IEEE80211_BAND_2GHZ, +-@@ -143,7 +177,7 @@ static const struct ieee80211_supported_ +- .n_bitrates = wl_g_rates_size, +- }; +- +--static const struct ieee80211_supported_band __wl_band_5ghz_a = { +-+static const struct ieee80211_supported_band __wl_band_5ghz = { +- .band = IEEE80211_BAND_5GHZ, +- .bitrates = wl_a_rates, +- .n_bitrates = wl_a_rates_size, +-@@ -5252,40 +5286,6 @@ dongle_scantime_out: +- return err; +- } +- +--/* Filter the list of channels received from firmware counting only +-- * the 20MHz channels. The wiphy band data only needs those which get +-- * flagged to indicate if they can take part in higher bandwidth. +-- */ +--static void brcmf_count_20mhz_channels(struct brcmf_cfg80211_info *cfg, +-- struct brcmf_chanspec_list *chlist, +-- u32 chcnt[]) +--{ +-- u32 total = le32_to_cpu(chlist->count); +-- struct brcmu_chan ch; +-- int i; +-- +-- for (i = 0; i < total; i++) { +-- ch.chspec = (u16)le32_to_cpu(chlist->element[i]); +-- cfg->d11inf.decchspec(&ch); +-- +-- /* Firmware gives a ordered list. We skip non-20MHz +-- * channels is 2G. For 5G we can abort upon reaching +-- * a non-20MHz channel in the list. +-- */ +-- if (ch.bw != BRCMU_CHAN_BW_20) { +-- if (ch.band == BRCMU_CHAN_BAND_5G) +-- break; +-- else +-- continue; +-- } +-- +-- if (ch.band == BRCMU_CHAN_BAND_2G) +-- chcnt[0] += 1; +-- else if (ch.band == BRCMU_CHAN_BAND_5G) +-- chcnt[1] += 1; +-- } +--} +-- +- static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel, +- struct brcmu_chan *ch) +- { +-@@ -5321,7 +5321,6 @@ static int brcmf_construct_chaninfo(stru +- u32 i, j; +- u32 total; +- u32 chaninfo; +-- u32 chcnt[2] = { 0, 0 }; +- u32 index; +- +- pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); +-@@ -5338,42 +5337,15 @@ static int brcmf_construct_chaninfo(stru +- goto fail_pbuf; +- } +- +-- brcmf_count_20mhz_channels(cfg, list, chcnt); +- wiphy = cfg_to_wiphy(cfg); +-- if (chcnt[0]) { +-- band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz), +-- GFP_KERNEL); +-- if (band == NULL) { +-- err = -ENOMEM; +-- goto fail_pbuf; +-- } +-- band->channels = kcalloc(chcnt[0], sizeof(*channel), +-- GFP_KERNEL); +-- if (band->channels == NULL) { +-- kfree(band); +-- err = -ENOMEM; +-- goto fail_pbuf; +-- } +-- band->n_channels = 0; +-- wiphy->bands[IEEE80211_BAND_2GHZ] = band; +-- } +-- if (chcnt[1]) { +-- band = kmemdup(&__wl_band_5ghz_a, sizeof(__wl_band_5ghz_a), +-- GFP_KERNEL); +-- if (band == NULL) { +-- err = -ENOMEM; +-- goto fail_band2g; +-- } +-- band->channels = kcalloc(chcnt[1], sizeof(*channel), +-- GFP_KERNEL); +-- if (band->channels == NULL) { +-- kfree(band); +-- err = -ENOMEM; +-- goto fail_band2g; +-- } +-- band->n_channels = 0; +-- wiphy->bands[IEEE80211_BAND_5GHZ] = band; +-- } +-+ band = wiphy->bands[IEEE80211_BAND_2GHZ]; +-+ if (band) +-+ for (i = 0; i < band->n_channels; i++) +-+ band->channels[i].flags = IEEE80211_CHAN_DISABLED; +-+ band = wiphy->bands[IEEE80211_BAND_5GHZ]; +-+ if (band) +-+ for (i = 0; i < band->n_channels; i++) +-+ band->channels[i].flags = IEEE80211_CHAN_DISABLED; +- +- total = le32_to_cpu(list->count); +- for (i = 0; i < total; i++) { +-@@ -5388,6 +5360,8 @@ static int brcmf_construct_chaninfo(stru +- brcmf_err("Invalid channel Spec. 0x%x.\n", ch.chspec); +- continue; +- } +-+ if (!band) +-+ continue; +- if (!(bw_cap[band->band] & WLC_BW_40MHZ_BIT) && +- ch.bw == BRCMU_CHAN_BW_40) +- continue; +-@@ -5415,9 +5389,9 @@ static int brcmf_construct_chaninfo(stru +- } else if (ch.bw == BRCMU_CHAN_BW_40) { +- brcmf_update_bw40_channel_flag(&channel[index], &ch); +- } else { +-- /* disable other bandwidths for now as mentioned +-- * order assure they are enabled for subsequent +-- * chanspecs. +-+ /* enable the channel and disable other bandwidths +-+ * for now as mentioned order assure they are enabled +-+ * for subsequent chanspecs. +- */ +- channel[index].flags = IEEE80211_CHAN_NO_HT40 | +- IEEE80211_CHAN_NO_80MHZ; +-@@ -5436,16 +5410,8 @@ static int brcmf_construct_chaninfo(stru +- IEEE80211_CHAN_NO_IR; +- } +- } +-- if (index == band->n_channels) +-- band->n_channels++; +- } +-- kfree(pbuf); +-- return 0; +- +--fail_band2g: +-- kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); +-- kfree(wiphy->bands[IEEE80211_BAND_2GHZ]); +-- wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; +- fail_pbuf: +- kfree(pbuf); +- return err; +-@@ -5778,7 +5744,12 @@ static void brcmf_wiphy_wowl_params(stru +- +- static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) +- { +-+ struct ieee80211_supported_band *band; +- struct ieee80211_iface_combination ifc_combo; +-+ __le32 bandlist[3]; +-+ u32 n_bands; +-+ int err, i; +-+ +- wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; +- wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; +- wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; +-@@ -5820,7 +5791,52 @@ static int brcmf_setup_wiphy(struct wiph +- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) +- brcmf_wiphy_wowl_params(wiphy); +- +-- return brcmf_setup_wiphybands(wiphy); +-+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BANDLIST, &bandlist, +-+ sizeof(bandlist)); +-+ if (err) { +-+ brcmf_err("could not obtain band info: err=%d\n", err); +-+ return err; +-+ } +-+ /* first entry in bandlist is number of bands */ +-+ n_bands = le32_to_cpu(bandlist[0]); +-+ for (i = 1; i <= n_bands && i < ARRAY_SIZE(bandlist); i++) { +-+ if (bandlist[i] == cpu_to_le32(WLC_BAND_2G)) { +-+ band = kmemdup(&__wl_band_2ghz, sizeof(__wl_band_2ghz), +-+ GFP_KERNEL); +-+ if (!band) +-+ return -ENOMEM; +-+ +-+ band->channels = kmemdup(&__wl_2ghz_channels, +-+ sizeof(__wl_2ghz_channels), +-+ GFP_KERNEL); +-+ if (!band->channels) { +-+ kfree(band); +-+ return -ENOMEM; +-+ } +-+ +-+ band->n_channels = ARRAY_SIZE(__wl_2ghz_channels); +-+ wiphy->bands[IEEE80211_BAND_2GHZ] = band; +-+ } +-+ if (bandlist[i] == cpu_to_le32(WLC_BAND_5G)) { +-+ band = kmemdup(&__wl_band_5ghz, sizeof(__wl_band_5ghz), +-+ GFP_KERNEL); +-+ if (!band) +-+ return -ENOMEM; +-+ +-+ band->channels = kmemdup(&__wl_5ghz_channels, +-+ sizeof(__wl_5ghz_channels), +-+ GFP_KERNEL); +-+ if (!band->channels) { +-+ kfree(band); +-+ return -ENOMEM; +-+ } +-+ +-+ band->n_channels = ARRAY_SIZE(__wl_5ghz_channels); +-+ wiphy->bands[IEEE80211_BAND_5GHZ] = band; +-+ } +-+ } +-+ err = brcmf_setup_wiphybands(wiphy); +-+ return err; +- } +- +- static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) +-@@ -6011,6 +6027,9 @@ static void brcmf_cfg80211_reg_notifier( +- +- static void brcmf_free_wiphy(struct wiphy *wiphy) +- { +-+ if (!wiphy) +-+ return; +-+ +- kfree(wiphy->iface_combinations); +- if (wiphy->bands[IEEE80211_BAND_2GHZ]) { +- kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); +diff --git a/package/kernel/mac80211/patches/355-brcmfmac-update-wiphy-band-information-upon-updating.patch b/package/kernel/mac80211/patches/355-brcmfmac-update-wiphy-band-information-upon-updating.patch +deleted file mode 100644 +index a0c22eb..0000000 +--- a/package/kernel/mac80211/patches/355-brcmfmac-update-wiphy-band-information-upon-updating.patch ++++ /dev/null +@@ -1,29 +0,0 @@ +-From: Arend van Spriel +-Date: Tue, 14 Apr 2015 20:10:25 +0200 +-Subject: [PATCH] brcmfmac: update wiphy band information upon updating +- regulatory domain +- +-When change the country code the available channels may change. So +-the wiphy bands should be updated accordingly. +- +-Reviewed-by: Daniel (Deognyoun) Kim +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -6022,7 +6022,11 @@ static void brcmf_cfg80211_reg_notifier( +- memset(&ccreq, 0, sizeof(ccreq)); +- ccreq.rev = cpu_to_le32(-1); +- memcpy(ccreq.ccode, req->alpha2, sizeof(req->alpha2)); +-- brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq)); +-+ if (brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq))) { +-+ brcmf_err("firmware rejected country setting\n"); +-+ return; +-+ } +-+ brcmf_setup_wiphybands(wiphy); +- } +- +- static void brcmf_free_wiphy(struct wiphy *wiphy) +diff --git a/package/kernel/mac80211/patches/356-brcmfmac-add-description-for-feature-flags.patch b/package/kernel/mac80211/patches/356-brcmfmac-add-description-for-feature-flags.patch +deleted file mode 100644 +index 193f507..0000000 +--- a/package/kernel/mac80211/patches/356-brcmfmac-add-description-for-feature-flags.patch ++++ /dev/null +@@ -1,24 +0,0 @@ +-From: Arend van Spriel +-Date: Tue, 14 Apr 2015 20:10:26 +0200 +-Subject: [PATCH] brcmfmac: add description for feature flags +- +-Some feature flags were not described in the header file. Adding +-the description. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h +-@@ -19,7 +19,9 @@ +- /* +- * Features: +- * +-+ * MBSS: multiple BSSID support (eg. guest network in AP mode). +- * MCHAN: multi-channel for concurrent P2P. +-+ * WOWL: Wake-On-WLAN. +- */ +- #define BRCMF_FEAT_LIST \ +- BRCMF_FEAT_DEF(MBSS) \ +diff --git a/package/kernel/mac80211/patches/357-brcmfmac-make-scheduled-scan-support-conditional.patch b/package/kernel/mac80211/patches/357-brcmfmac-make-scheduled-scan-support-conditional.patch +deleted file mode 100644 +index 42330b4..0000000 +--- a/package/kernel/mac80211/patches/357-brcmfmac-make-scheduled-scan-support-conditional.patch ++++ /dev/null +@@ -1,51 +0,0 @@ +-From: Arend van Spriel +-Date: Tue, 14 Apr 2015 20:10:27 +0200 +-Subject: [PATCH] brcmfmac: make scheduled scan support conditional +- +-The scheduled scan support depends on firmware supporting the PNO +-feature. This feature is optional so add a feature flag for this +-in the driver and announce scheduled scan support accordingly. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -5782,7 +5782,8 @@ static int brcmf_setup_wiphy(struct wiph +- wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; +- wiphy->mgmt_stypes = brcmf_txrx_stypes; +- wiphy->max_remain_on_channel_duration = 5000; +-- brcmf_wiphy_pno_params(wiphy); +-+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) +-+ brcmf_wiphy_pno_params(wiphy); +- +- /* vendor commands/events support */ +- wiphy->vendor_commands = brcmf_vendor_cmds; +---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c +-@@ -124,6 +124,7 @@ void brcmf_feat_attach(struct brcmf_pub +- struct brcmf_if *ifp = drvr->iflist[0]; +- +- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan"); +-+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn"); +- if (drvr->bus_if->wowl_supported) +- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl"); +- if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID) +---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h +-@@ -21,11 +21,13 @@ +- * +- * MBSS: multiple BSSID support (eg. guest network in AP mode). +- * MCHAN: multi-channel for concurrent P2P. +-+ * PNO: preferred network offload. +- * WOWL: Wake-On-WLAN. +- */ +- #define BRCMF_FEAT_LIST \ +- BRCMF_FEAT_DEF(MBSS) \ +- BRCMF_FEAT_DEF(MCHAN) \ +-+ BRCMF_FEAT_DEF(PNO) \ +- BRCMF_FEAT_DEF(WOWL) +- /* +- * Quirks: +diff --git a/package/kernel/mac80211/patches/358-brcmfmac-add-support-for-BCM4324-rev-B5-chipset.patch b/package/kernel/mac80211/patches/358-brcmfmac-add-support-for-BCM4324-rev-B5-chipset.patch +deleted file mode 100644 +index b859d46..0000000 +--- a/package/kernel/mac80211/patches/358-brcmfmac-add-support-for-BCM4324-rev-B5-chipset.patch ++++ /dev/null +@@ -1,43 +0,0 @@ +-From: Arend van Spriel +-Date: Tue, 14 Apr 2015 20:10:28 +0200 +-Subject: [PATCH] brcmfmac: add support for BCM4324 rev B5 chipset +- +-This patch adds support for the BCM4324 B5 revision. This device +-is similar to BCM43241 from driver and firmware perspective. It +-is known to be used in Lenovo Thinkpad Tablet devices. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -601,6 +601,8 @@ static const struct sdiod_drive_str sdio +- #define BCM43241B0_NVRAM_NAME "brcm/brcmfmac43241b0-sdio.txt" +- #define BCM43241B4_FIRMWARE_NAME "brcm/brcmfmac43241b4-sdio.bin" +- #define BCM43241B4_NVRAM_NAME "brcm/brcmfmac43241b4-sdio.txt" +-+#define BCM43241B5_FIRMWARE_NAME "brcm/brcmfmac43241b5-sdio.bin" +-+#define BCM43241B5_NVRAM_NAME "brcm/brcmfmac43241b5-sdio.txt" +- #define BCM4329_FIRMWARE_NAME "brcm/brcmfmac4329-sdio.bin" +- #define BCM4329_NVRAM_NAME "brcm/brcmfmac4329-sdio.txt" +- #define BCM4330_FIRMWARE_NAME "brcm/brcmfmac4330-sdio.bin" +-@@ -628,6 +630,8 @@ MODULE_FIRMWARE(BCM43241B0_FIRMWARE_NAME +- MODULE_FIRMWARE(BCM43241B0_NVRAM_NAME); +- MODULE_FIRMWARE(BCM43241B4_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM43241B4_NVRAM_NAME); +-+MODULE_FIRMWARE(BCM43241B5_FIRMWARE_NAME); +-+MODULE_FIRMWARE(BCM43241B5_NVRAM_NAME); +- MODULE_FIRMWARE(BCM4329_FIRMWARE_NAME); +- MODULE_FIRMWARE(BCM4329_NVRAM_NAME); +- MODULE_FIRMWARE(BCM4330_FIRMWARE_NAME); +-@@ -667,7 +671,8 @@ enum brcmf_firmware_type { +- static const struct brcmf_firmware_names brcmf_fwname_data[] = { +- { BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) }, +- { BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) }, +-- { BRCM_CC_43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) }, +-+ { BRCM_CC_43241_CHIP_ID, 0x00000020, BRCMF_FIRMWARE_NVRAM(BCM43241B4) }, +-+ { BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43241B5) }, +- { BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) }, +- { BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) }, +- { BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) }, +diff --git a/package/kernel/mac80211/patches/359-brcmfmac-process-interrupt-regardless-sdiod-state.patch b/package/kernel/mac80211/patches/359-brcmfmac-process-interrupt-regardless-sdiod-state.patch +deleted file mode 100644 +index d420308..0000000 +--- a/package/kernel/mac80211/patches/359-brcmfmac-process-interrupt-regardless-sdiod-state.patch ++++ /dev/null +@@ -1,27 +0,0 @@ +-From: Arend van Spriel +-Date: Tue, 14 Apr 2015 20:10:29 +0200 +-Subject: [PATCH] brcmfmac: process interrupt regardless sdiod state +- +-When the sdio bus state is not ready to process we abort the +-interrupt service routine. This is not wanted as it keeps the +-interrupt source active. Better clear the interrupt source. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Franky (Zhenhui) Lin +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -3555,10 +3555,6 @@ void brcmf_sdio_isr(struct brcmf_sdio *b +- return; +- } +- +-- if (bus->sdiodev->state != BRCMF_SDIOD_DATA) { +-- brcmf_err("bus is down. we have nothing to do\n"); +-- return; +-- } +- /* Count the interrupt call */ +- bus->sdcnt.intrcount++; +- if (in_interrupt()) +diff --git a/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch b/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch +deleted file mode 100644 +index ac5584e..0000000 +--- a/package/kernel/mac80211/patches/360-brcmfmac-fix-sdio-suspend-and-resume.patch ++++ /dev/null +@@ -1,68 +0,0 @@ +-From: Arend van Spriel +-Date: Tue, 14 Apr 2015 20:10:30 +0200 +-Subject: [PATCH] brcmfmac: fix sdio suspend and resume +- +-commit 330b4e4be937 ("brcmfmac: Add wowl support for SDIO devices.") +-changed the behaviour by removing the MMC_PM_KEEP_POWER flag for +-non-wowl scenario, which needs to be restored. Another necessary +-change is to mark the card as being non-removable. With this in place +-the suspend resume test passes successfully doing: +- +- # echo devices > /sys/power/pm_test +- # echo mem > /sys/power/state +- +-Note that power may still be switched off when system is going +-in S3 state. +- +-Reported-by: Fu, Zhonghui < +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Franky (Zhenhui) Lin +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-@@ -1011,6 +1011,14 @@ static int brcmf_sdiod_remove(struct brc +- return 0; +- } +- +-+static void brcmf_sdiod_host_fixup(struct mmc_host *host) +-+{ +-+ /* runtime-pm powers off the device */ +-+ pm_runtime_forbid(host->parent); +-+ /* avoid removal detection upon resume */ +-+ host->caps |= MMC_CAP_NONREMOVABLE; +-+} +-+ +- static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) +- { +- struct sdio_func *func; +-@@ -1076,7 +1084,7 @@ static int brcmf_sdiod_probe(struct brcm +- ret = -ENODEV; +- goto out; +- } +-- pm_runtime_forbid(host->parent); +-+ brcmf_sdiod_host_fixup(host); +- out: +- if (ret) +- brcmf_sdiod_remove(sdiodev); +-@@ -1246,15 +1254,15 @@ static int brcmf_ops_sdio_suspend(struct +- brcmf_sdiod_freezer_on(sdiodev); +- brcmf_sdio_wd_timer(sdiodev->bus, 0); +- +-+ sdio_flags = MMC_PM_KEEP_POWER; +- if (sdiodev->wowl_enabled) { +-- sdio_flags = MMC_PM_KEEP_POWER; +- if (sdiodev->pdata->oob_irq_supported) +- enable_irq_wake(sdiodev->pdata->oob_irq_nr); +- else +-- sdio_flags = MMC_PM_WAKE_SDIO_IRQ; +-- if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) +-- brcmf_err("Failed to set pm_flags %x\n", sdio_flags); +-+ sdio_flags |= MMC_PM_WAKE_SDIO_IRQ; +- } +-+ if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) +-+ brcmf_err("Failed to set pm_flags %x\n", sdio_flags); +- return 0; +- } +- +diff --git a/package/kernel/mac80211/patches/361-brcmfmac-add-support-for-BCM4358-PCIe-device.patch b/package/kernel/mac80211/patches/361-brcmfmac-add-support-for-BCM4358-PCIe-device.patch +deleted file mode 100644 +index a521b65..0000000 +--- a/package/kernel/mac80211/patches/361-brcmfmac-add-support-for-BCM4358-PCIe-device.patch ++++ /dev/null +@@ -1,77 +0,0 @@ +-From: Arend van Spriel +-Date: Tue, 14 Apr 2015 20:10:31 +0200 +-Subject: [PATCH] brcmfmac: add support for BCM4358 PCIe device +- +-This patch adds support for the BCM4358 2x2 11ac device. +- +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-@@ -649,6 +649,7 @@ static u32 brcmf_chip_tcm_rambase(struct +- case BRCM_CC_43567_CHIP_ID: +- case BRCM_CC_43569_CHIP_ID: +- case BRCM_CC_43570_CHIP_ID: +-+ case BRCM_CC_4358_CHIP_ID: +- case BRCM_CC_43602_CHIP_ID: +- return 0x180000; +- default: +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -51,6 +51,8 @@ enum brcmf_pcie_state { +- #define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt" +- #define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin" +- #define BRCMF_PCIE_43570_NVRAM_NAME "brcm/brcmfmac43570-pcie.txt" +-+#define BRCMF_PCIE_4358_FW_NAME "brcm/brcmfmac4358-pcie.bin" +-+#define BRCMF_PCIE_4358_NVRAM_NAME "brcm/brcmfmac4358-pcie.txt" +- +- #define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ +- +-@@ -189,6 +191,8 @@ MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME) +- MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME); +- MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME); +-+MODULE_FIRMWARE(BRCMF_PCIE_4358_FW_NAME); +-+MODULE_FIRMWARE(BRCMF_PCIE_4358_NVRAM_NAME); +- +- +- struct brcmf_pcie_console { +-@@ -1333,6 +1337,10 @@ static int brcmf_pcie_get_fwnames(struct +- fw_name = BRCMF_PCIE_43570_FW_NAME; +- nvram_name = BRCMF_PCIE_43570_NVRAM_NAME; +- break; +-+ case BRCM_CC_4358_CHIP_ID: +-+ fw_name = BRCMF_PCIE_4358_FW_NAME; +-+ nvram_name = BRCMF_PCIE_4358_NVRAM_NAME; +-+ break; +- default: +- brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip); +- return -ENODEV; +-@@ -1850,6 +1858,7 @@ static struct pci_device_id brcmf_pcie_d +- BRCMF_PCIE_DEVICE(BRCM_PCIE_4356_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID), +-+ BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID), +---- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +-+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +-@@ -45,6 +45,7 @@ +- #define BRCM_CC_43567_CHIP_ID 43567 +- #define BRCM_CC_43569_CHIP_ID 43569 +- #define BRCM_CC_43570_CHIP_ID 43570 +-+#define BRCM_CC_4358_CHIP_ID 0x4358 +- #define BRCM_CC_43602_CHIP_ID 43602 +- +- /* USB Device IDs */ +-@@ -59,6 +60,7 @@ +- #define BRCM_PCIE_4356_DEVICE_ID 0x43ec +- #define BRCM_PCIE_43567_DEVICE_ID 0x43d3 +- #define BRCM_PCIE_43570_DEVICE_ID 0x43d9 +-+#define BRCM_PCIE_4358_DEVICE_ID 0x43e9 +- #define BRCM_PCIE_43602_DEVICE_ID 0x43ba +- #define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb +- #define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc +diff --git a/package/kernel/mac80211/patches/362-brcmfmac-add-additional-43602-pcie-device-id.patch b/package/kernel/mac80211/patches/362-brcmfmac-add-additional-43602-pcie-device-id.patch +deleted file mode 100644 +index bcbb984..0000000 +--- a/package/kernel/mac80211/patches/362-brcmfmac-add-additional-43602-pcie-device-id.patch ++++ /dev/null +@@ -1,30 +0,0 @@ +-From: Hante Meuleman +-Date: Tue, 14 Apr 2015 20:10:32 +0200 +-Subject: [PATCH] brcmfmac: add additional 43602 pcie device id. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -1862,6 +1862,7 @@ static struct pci_device_id brcmf_pcie_d +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID), +- BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID), +-+ BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_RAW_DEVICE_ID), +- { /* end: all zeroes */ } +- }; +- +---- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +-+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h +-@@ -64,6 +64,7 @@ +- #define BRCM_PCIE_43602_DEVICE_ID 0x43ba +- #define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb +- #define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc +-+#define BRCM_PCIE_43602_RAW_DEVICE_ID 43602 +- +- /* brcmsmac IDs */ +- #define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ +diff --git a/package/kernel/mac80211/patches/363-brcmfmac-Add-support-for-multiple-PCIE-devices-in-nv.patch b/package/kernel/mac80211/patches/363-brcmfmac-Add-support-for-multiple-PCIE-devices-in-nv.patch +deleted file mode 100644 +index 5f9bbea..0000000 +--- a/package/kernel/mac80211/patches/363-brcmfmac-Add-support-for-multiple-PCIE-devices-in-nv.patch ++++ /dev/null +@@ -1,351 +0,0 @@ +-From: Hante Meuleman +-Date: Tue, 14 Apr 2015 20:10:33 +0200 +-Subject: [PATCH] brcmfmac: Add support for multiple PCIE devices in +- nvram. +- +-With PCIE it is possible to support multiple devices with the +-same device type. They all load the same nvram file. In order to +-support this the nvram can specify which part of the nvram is +-for which pcie device. This patch adds support for these new +-types of nvram files. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Daniel (Deognyoun) Kim +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-@@ -23,6 +23,10 @@ +- #include "debug.h" +- #include "firmware.h" +- +-+#define BRCMF_FW_MAX_NVRAM_SIZE 64000 +-+#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */ +-+#define BRCMF_FW_NVRAM_PCIEDEV_LEN 9 /* pcie/1/4/ */ +-+ +- char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; +- module_param_string(firmware_path, brcmf_firmware_path, +- BRCMF_FW_PATH_LEN, 0440); +-@@ -46,6 +50,8 @@ enum nvram_parser_state { +- * @column: current column in line. +- * @pos: byte offset in input buffer. +- * @entry: start position of key,value entry. +-+ * @multi_dev_v1: detect pcie multi device v1 (compressed). +-+ * @multi_dev_v2: detect pcie multi device v2. +- */ +- struct nvram_parser { +- enum nvram_parser_state state; +-@@ -56,6 +62,8 @@ struct nvram_parser { +- u32 column; +- u32 pos; +- u32 entry; +-+ bool multi_dev_v1; +-+ bool multi_dev_v2; +- }; +- +- static bool is_nvram_char(char c) +-@@ -108,6 +116,10 @@ static enum nvram_parser_state brcmf_nvr +- st = COMMENT; +- else +- st = VALUE; +-+ if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0) +-+ nvp->multi_dev_v1 = true; +-+ if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0) +-+ nvp->multi_dev_v2 = true; +- } else if (!is_nvram_char(c)) { +- brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", +- nvp->line, nvp->column); +-@@ -133,6 +145,8 @@ brcmf_nvram_handle_value(struct nvram_pa +- ekv = (u8 *)&nvp->fwnv->data[nvp->pos]; +- skv = (u8 *)&nvp->fwnv->data[nvp->entry]; +- cplen = ekv - skv; +-+ if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE) +-+ return END; +- /* copy to output buffer */ +- memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen); +- nvp->nvram_len += cplen; +-@@ -180,10 +194,18 @@ static enum nvram_parser_state +- static int brcmf_init_nvram_parser(struct nvram_parser *nvp, +- const struct firmware *nv) +- { +-+ size_t size; +-+ +- memset(nvp, 0, sizeof(*nvp)); +- nvp->fwnv = nv; +-+ /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */ +-+ if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE) +-+ size = BRCMF_FW_MAX_NVRAM_SIZE; +-+ else +-+ size = nv->size; +- /* Alloc for extra 0 byte + roundup by 4 + length field */ +-- nvp->nvram = kzalloc(nv->size + 1 + 3 + sizeof(u32), GFP_KERNEL); +-+ size += 1 + 3 + sizeof(u32); +-+ nvp->nvram = kzalloc(size, GFP_KERNEL); +- if (!nvp->nvram) +- return -ENOMEM; +- +-@@ -192,12 +214,136 @@ static int brcmf_init_nvram_parser(struc +- return 0; +- } +- +-+/* brcmf_fw_strip_multi_v1 :Some nvram files contain settings for multiple +-+ * devices. Strip it down for one device, use domain_nr/bus_nr to determine +-+ * which data is to be returned. v1 is the version where nvram is stored +-+ * compressed and "devpath" maps to index for valid entries. +-+ */ +-+static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr, +-+ u16 bus_nr) +-+{ +-+ u32 i, j; +-+ bool found; +-+ u8 *nvram; +-+ u8 id; +-+ +-+ nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL); +-+ if (!nvram) +-+ goto fail; +-+ +-+ /* min length: devpath0=pcie/1/4/ + 0:x=y */ +-+ if (nvp->nvram_len < BRCMF_FW_NVRAM_DEVPATH_LEN + 6) +-+ goto fail; +-+ +-+ /* First search for the devpathX and see if it is the configuration +-+ * for domain_nr/bus_nr. Search complete nvp +-+ */ +-+ found = false; +-+ i = 0; +-+ while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) { +-+ /* Format: devpathX=pcie/Y/Z/ +-+ * Y = domain_nr, Z = bus_nr, X = virtual ID +-+ */ +-+ if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) && +-+ (strncmp(&nvp->nvram[i + 8], "=pcie/", 6) == 0)) { +-+ if (((nvp->nvram[i + 14] - '0') == domain_nr) && +-+ ((nvp->nvram[i + 16] - '0') == bus_nr)) { +-+ id = nvp->nvram[i + 7] - '0'; +-+ found = true; +-+ break; +-+ } +-+ } +-+ while (nvp->nvram[i] != 0) +-+ i++; +-+ i++; +-+ } +-+ if (!found) +-+ goto fail; +-+ +-+ /* Now copy all valid entries, release old nvram and assign new one */ +-+ i = 0; +-+ j = 0; +-+ while (i < nvp->nvram_len) { +-+ if ((nvp->nvram[i] - '0' == id) && (nvp->nvram[i + 1] == ':')) { +-+ i += 2; +-+ while (nvp->nvram[i] != 0) { +-+ nvram[j] = nvp->nvram[i]; +-+ i++; +-+ j++; +-+ } +-+ nvram[j] = 0; +-+ j++; +-+ } +-+ while (nvp->nvram[i] != 0) +-+ i++; +-+ i++; +-+ } +-+ kfree(nvp->nvram); +-+ nvp->nvram = nvram; +-+ nvp->nvram_len = j; +-+ return; +-+ +-+fail: +-+ kfree(nvram); +-+ nvp->nvram_len = 0; +-+} +-+ +-+/* brcmf_fw_strip_multi_v2 :Some nvram files contain settings for multiple +-+ * devices. Strip it down for one device, use domain_nr/bus_nr to determine +-+ * which data is to be returned. v2 is the version where nvram is stored +-+ * uncompressed, all relevant valid entries are identified by +-+ * pcie/domain_nr/bus_nr: +-+ */ +-+static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr, +-+ u16 bus_nr) +-+{ +-+ u32 i, j; +-+ u8 *nvram; +-+ +-+ nvram = kzalloc(nvp->nvram_len + 1 + 3 + sizeof(u32), GFP_KERNEL); +-+ if (!nvram) +-+ goto fail; +-+ +-+ /* Copy all valid entries, release old nvram and assign new one. +-+ * Valid entries are of type pcie/X/Y/ where X = domain_nr and +-+ * Y = bus_nr. +-+ */ +-+ i = 0; +-+ j = 0; +-+ while (i < nvp->nvram_len - BRCMF_FW_NVRAM_PCIEDEV_LEN) { +-+ if ((strncmp(&nvp->nvram[i], "pcie/", 5) == 0) && +-+ (nvp->nvram[i + 6] == '/') && (nvp->nvram[i + 8] == '/') && +-+ ((nvp->nvram[i + 5] - '0') == domain_nr) && +-+ ((nvp->nvram[i + 7] - '0') == bus_nr)) { +-+ i += BRCMF_FW_NVRAM_PCIEDEV_LEN; +-+ while (nvp->nvram[i] != 0) { +-+ nvram[j] = nvp->nvram[i]; +-+ i++; +-+ j++; +-+ } +-+ nvram[j] = 0; +-+ j++; +-+ } +-+ while (nvp->nvram[i] != 0) +-+ i++; +-+ i++; +-+ } +-+ kfree(nvp->nvram); +-+ nvp->nvram = nvram; +-+ nvp->nvram_len = j; +-+ return; +-+fail: +-+ kfree(nvram); +-+ nvp->nvram_len = 0; +-+} +-+ +- /* brcmf_nvram_strip :Takes a buffer of "=\n" lines read from a fil +- * and ending in a NUL. Removes carriage returns, empty lines, comment lines, +- * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. +- * End of buffer is completed with token identifying length of buffer. +- */ +--static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length) +-+static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length, +-+ u16 domain_nr, u16 bus_nr) +- { +- struct nvram_parser nvp; +- u32 pad; +-@@ -212,6 +358,16 @@ static void *brcmf_fw_nvram_strip(const +- if (nvp.state == END) +- break; +- } +-+ if (nvp.multi_dev_v1) +-+ brcmf_fw_strip_multi_v1(&nvp, domain_nr, bus_nr); +-+ else if (nvp.multi_dev_v2) +-+ brcmf_fw_strip_multi_v2(&nvp, domain_nr, bus_nr); +-+ +-+ if (nvp.nvram_len == 0) { +-+ kfree(nvp.nvram); +-+ return NULL; +-+ } +-+ +- pad = nvp.nvram_len; +- *new_length = roundup(nvp.nvram_len + 1, 4); +- while (pad != *new_length) { +-@@ -239,6 +395,8 @@ struct brcmf_fw { +- u16 flags; +- const struct firmware *code; +- const char *nvram_name; +-+ u16 domain_nr; +-+ u16 bus_nr; +- void (*done)(struct device *dev, const struct firmware *fw, +- void *nvram_image, u32 nvram_len); +- }; +-@@ -254,7 +412,8 @@ static void brcmf_fw_request_nvram_done( +- goto fail; +- +- if (fw) { +-- nvram = brcmf_fw_nvram_strip(fw, &nvram_length); +-+ nvram = brcmf_fw_nvram_strip(fw, &nvram_length, +-+ fwctx->domain_nr, fwctx->bus_nr); +- release_firmware(fw); +- if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) +- goto fail; +-@@ -309,11 +468,12 @@ fail: +- kfree(fwctx); +- } +- +--int brcmf_fw_get_firmwares(struct device *dev, u16 flags, +-- const char *code, const char *nvram, +-- void (*fw_cb)(struct device *dev, +-- const struct firmware *fw, +-- void *nvram_image, u32 nvram_len)) +-+int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, +-+ const char *code, const char *nvram, +-+ void (*fw_cb)(struct device *dev, +-+ const struct firmware *fw, +-+ void *nvram_image, u32 nvram_len), +-+ u16 domain_nr, u16 bus_nr) +- { +- struct brcmf_fw *fwctx; +- +-@@ -333,8 +493,21 @@ int brcmf_fw_get_firmwares(struct device +- fwctx->done = fw_cb; +- if (flags & BRCMF_FW_REQUEST_NVRAM) +- fwctx->nvram_name = nvram; +-+ fwctx->domain_nr = domain_nr; +-+ fwctx->bus_nr = bus_nr; +- +- return request_firmware_nowait(THIS_MODULE, true, code, dev, +- GFP_KERNEL, fwctx, +- brcmf_fw_request_code_done); +- } +-+ +-+int brcmf_fw_get_firmwares(struct device *dev, u16 flags, +-+ const char *code, const char *nvram, +-+ void (*fw_cb)(struct device *dev, +-+ const struct firmware *fw, +-+ void *nvram_image, u32 nvram_len)) +-+{ +-+ return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0, +-+ 0); +-+} +-+ +---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h +-@@ -32,6 +32,12 @@ void brcmf_fw_nvram_free(void *nvram); +- * fails it will not use the callback, but call device_release_driver() +- * instead which will call the driver .remove() callback. +- */ +-+int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, +-+ const char *code, const char *nvram, +-+ void (*fw_cb)(struct device *dev, +-+ const struct firmware *fw, +-+ void *nvram_image, u32 nvram_len), +-+ u16 domain_nr, u16 bus_nr); +- int brcmf_fw_get_firmwares(struct device *dev, u16 flags, +- const char *code, const char *nvram, +- void (*fw_cb)(struct device *dev, +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -1649,8 +1649,13 @@ brcmf_pcie_probe(struct pci_dev *pdev, c +- struct brcmf_pciedev_info *devinfo; +- struct brcmf_pciedev *pcie_bus_dev; +- struct brcmf_bus *bus; +-+ u16 domain_nr; +-+ u16 bus_nr; +- +-- brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device); +-+ domain_nr = pci_domain_nr(pdev->bus) + 1; +-+ bus_nr = pdev->bus->number; +-+ brcmf_dbg(PCIE, "Enter %x:%x (%d/%d)\n", pdev->vendor, pdev->device, +-+ domain_nr, bus_nr); +- +- ret = -ENOMEM; +- devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); +-@@ -1699,10 +1704,10 @@ brcmf_pcie_probe(struct pci_dev *pdev, c +- if (ret) +- goto fail_bus; +- +-- ret = brcmf_fw_get_firmwares(bus->dev, BRCMF_FW_REQUEST_NVRAM | +-- BRCMF_FW_REQ_NV_OPTIONAL, +-- devinfo->fw_name, devinfo->nvram_name, +-- brcmf_pcie_setup); +-+ ret = brcmf_fw_get_firmwares_pcie(bus->dev, BRCMF_FW_REQUEST_NVRAM | +-+ BRCMF_FW_REQ_NV_OPTIONAL, +-+ devinfo->fw_name, devinfo->nvram_name, +-+ brcmf_pcie_setup, domain_nr, bus_nr); +- if (ret == 0) +- return 0; +- fail_bus: +diff --git a/package/kernel/mac80211/patches/364-brcmfmac-cleanup-a-sizeof.patch b/package/kernel/mac80211/patches/364-brcmfmac-cleanup-a-sizeof.patch +deleted file mode 100644 +index d26e118..0000000 +--- a/package/kernel/mac80211/patches/364-brcmfmac-cleanup-a-sizeof.patch ++++ /dev/null +@@ -1,23 +0,0 @@ +-From: Dan Carpenter +-Date: Thu, 7 May 2015 12:59:19 +0300 +-Subject: [PATCH] brcmfmac: cleanup a sizeof() +- +-"flowrings" and "*flowrings" are both pointers so this always returns +-sizeof(void *) and the current code works fine. But "*flowrings" is +-intended here and static checkers complain, so lets change it. +- +-Signed-off-by: Dan Carpenter +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -1617,7 +1617,7 @@ static void brcmf_pcie_setup(struct devi +- bus->msgbuf->commonrings[i] = +- &devinfo->shared.commonrings[i]->commonring; +- +-- flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(flowrings), +-+ flowrings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*flowrings), +- GFP_KERNEL); +- if (!flowrings) +- goto fail; +diff --git a/package/kernel/mac80211/patches/365-brcmfmac-check-result-of-USB-firmware-request.patch b/package/kernel/mac80211/patches/365-brcmfmac-check-result-of-USB-firmware-request.patch +deleted file mode 100644 +index 9b2880d..0000000 +--- a/package/kernel/mac80211/patches/365-brcmfmac-check-result-of-USB-firmware-request.patch ++++ /dev/null +@@ -1,33 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Thu, 7 May 2015 14:13:03 +0200 +-Subject: [PATCH] brcmfmac: check result of USB firmware request +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-This prevents silence failures with driver waiting (infinitely) for a +-callback. +- +-Signed-off-by: Rafał Miłecki +-Acked-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c +-@@ -1270,8 +1270,13 @@ static int brcmf_usb_probe_cb(struct brc +- bus->chiprev = bus_pub->chiprev; +- +- /* request firmware here */ +-- brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), NULL, +-- brcmf_usb_probe_phase2); +-+ ret = brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), +-+ NULL, brcmf_usb_probe_phase2); +-+ if (ret) { +-+ brcmf_err("firmware request failed: %d\n", ret); +-+ goto fail; +-+ } +-+ +- return 0; +- +- fail: +diff --git a/package/kernel/mac80211/patches/366-brcmfmac-prohibit-ACPI-power-management-for-brcmfmac.patch b/package/kernel/mac80211/patches/366-brcmfmac-prohibit-ACPI-power-management-for-brcmfmac.patch +deleted file mode 100644 +index d46b300..0000000 +--- a/package/kernel/mac80211/patches/366-brcmfmac-prohibit-ACPI-power-management-for-brcmfmac.patch ++++ /dev/null +@@ -1,47 +0,0 @@ +-From: "Fu, Zhonghui" +-Date: Mon, 11 May 2015 10:41:32 +0800 +-Subject: [PATCH] brcmfmac: prohibit ACPI power management for brcmfmac driver +- +-ACPI will manage WiFi chip's power state during suspend/resume +-process on some tablet platforms(such as ASUS T100TA). This is +-not supported by brcmfmac driver now, and the context of WiFi +-chip will be damaged after resume. This patch informs ACPI not +-to manage WiFi chip's power state. +- +-Signed-off-by: Zhonghui Fu +-Acked-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-@@ -33,6 +33,7 @@ +- #include +- #include +- #include +-+#include +- #include +- +- #include +-@@ -1122,6 +1123,8 @@ static int brcmf_ops_sdio_probe(struct s +- int err; +- struct brcmf_sdio_dev *sdiodev; +- struct brcmf_bus *bus_if; +-+ struct device *dev; +-+ struct acpi_device *adev; +- +- brcmf_dbg(SDIO, "Enter\n"); +- brcmf_dbg(SDIO, "Class=%x\n", func->class); +-@@ -1129,6 +1132,12 @@ static int brcmf_ops_sdio_probe(struct s +- brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); +- brcmf_dbg(SDIO, "Function#: %d\n", func->num); +- +-+ /* prohibit ACPI power management for this device */ +-+ dev = &func->dev; +-+ adev = ACPI_COMPANION(dev); +-+ if (adev) +-+ adev->flags.power_manageable = 0; +-+ +- /* Consume func num 1 but dont do anything with it. */ +- if (func->num == 1) +- return 0; +diff --git a/package/kernel/mac80211/patches/367-brcmfmac-avoid-gcc-5.1-warning.patch b/package/kernel/mac80211/patches/367-brcmfmac-avoid-gcc-5.1-warning.patch +deleted file mode 100644 +index 9b4609f..0000000 +--- a/package/kernel/mac80211/patches/367-brcmfmac-avoid-gcc-5.1-warning.patch ++++ /dev/null +@@ -1,30 +0,0 @@ +-From: Arnd Bergmann +-Date: Tue, 12 May 2015 23:54:25 +0200 +-Subject: [PATCH] brcmfmac: avoid gcc-5.1 warning +- +-gcc-5.0 gained a new warning in the fwsignal portion of the brcmfmac +-driver: +- +-drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c: In function 'brcmf_fws_txs_process': +-drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c:1478:8: warning: 'skb' may be used uninitialized in this function [-Wmaybe-uninitialized] +- +-This is a false positive, and marking the brcmf_fws_hanger_poppkt function +-as 'static inline' makes the warning go away. I have checked the object +-file output and while a little code gets moved around, the size of +-the binary remains identical. +- +-Signed-off-by: Arnd Bergmann +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-@@ -635,7 +635,7 @@ static int brcmf_fws_hanger_pushpkt(stru +- return 0; +- } +- +--static int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h, +-+static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h, +- u32 slot_id, struct sk_buff **pktout, +- bool remove_item) +- { +diff --git a/package/kernel/mac80211/patches/368-brcmfmac-allow-device-tree-node-without-interrupts-p.patch b/package/kernel/mac80211/patches/368-brcmfmac-allow-device-tree-node-without-interrupts-p.patch +deleted file mode 100644 +index b16782d..0000000 +--- a/package/kernel/mac80211/patches/368-brcmfmac-allow-device-tree-node-without-interrupts-p.patch ++++ /dev/null +@@ -1,45 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 20 May 2015 14:09:47 +0200 +-Subject: [PATCH] brcmfmac: allow device tree node without 'interrupts' +- property +- +-As described in the device tree bindings for 'brcm,bcm4329-fmac' +-nodes, the interrupts property is optional. So adding a check +-for the presence of this property before attempting to parse +-and map the interrupt. If not present or parsing fails return +-and fallback to in-band sdio interrupt. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/of.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/of.c +-@@ -39,10 +39,16 @@ void brcmf_of_probe(struct brcmf_sdio_de +- if (!sdiodev->pdata) +- return; +- +-+ if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) +-+ sdiodev->pdata->drive_strength = val; +-+ +-+ /* make sure there are interrupts defined in the node */ +-+ if (!of_find_property(np, "interrupts", NULL)) +-+ return; +-+ +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) { +- brcmf_err("interrupt could not be mapped\n"); +-- devm_kfree(dev, sdiodev->pdata); +- return; +- } +- irqf = irqd_get_trigger_type(irq_get_irq_data(irq)); +-@@ -50,7 +56,4 @@ void brcmf_of_probe(struct brcmf_sdio_de +- sdiodev->pdata->oob_irq_supported = true; +- sdiodev->pdata->oob_irq_nr = irq; +- sdiodev->pdata->oob_irq_flags = irqf; +-- +-- if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) +-- sdiodev->pdata->drive_strength = val; +- } +diff --git a/package/kernel/mac80211/patches/369-brcmfmac-Improve-throughput-by-scheduling-msbug-flow.patch b/package/kernel/mac80211/patches/369-brcmfmac-Improve-throughput-by-scheduling-msbug-flow.patch +deleted file mode 100644 +index f81250e..0000000 +--- a/package/kernel/mac80211/patches/369-brcmfmac-Improve-throughput-by-scheduling-msbug-flow.patch ++++ /dev/null +@@ -1,87 +0,0 @@ +-From: Hante Meuleman +-Date: Wed, 20 May 2015 14:09:48 +0200 +-Subject: [PATCH] brcmfmac: Improve throughput by scheduling msbug flow worker. +- +-The tx flow worker in msgbuf gets scheduled at tx till a certain +-threshold has been reached. Then the tx completes will take over +-the scheduling. When amsdu and ampdu is used the frames are +-transferred wireless in a very bulky fashion, in combination +-with this scheduling algorithm and buffer limiters in the stack +-this can result in limited throughput. This change causes the +-flow worker to be scheduled more frequently from tx. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Daniel (Deognyoun) Kim +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +-@@ -249,8 +249,8 @@ void brcmf_flowring_delete(struct brcmf_ +- } +- +- +--void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, +-- struct sk_buff *skb) +-+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, +-+ struct sk_buff *skb) +- { +- struct brcmf_flowring_ring *ring; +- +-@@ -271,6 +271,7 @@ void brcmf_flowring_enqueue(struct brcmf +- if (skb_queue_len(&ring->skblist) < BRCMF_FLOWRING_LOW) +- brcmf_flowring_block(flow, flowid, false); +- } +-+ return skb_queue_len(&ring->skblist); +- } +- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.h +-@@ -64,8 +64,8 @@ u32 brcmf_flowring_create(struct brcmf_f +- void brcmf_flowring_delete(struct brcmf_flowring *flow, u8 flowid); +- void brcmf_flowring_open(struct brcmf_flowring *flow, u8 flowid); +- u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u8 flowid); +--void brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, +-- struct sk_buff *skb); +-+u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u8 flowid, +-+ struct sk_buff *skb); +- struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u8 flowid); +- void brcmf_flowring_reinsert(struct brcmf_flowring *flow, u8 flowid, +- struct sk_buff *skb); +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-@@ -73,7 +73,7 @@ +- #define BRCMF_MSGBUF_TX_FLUSH_CNT1 32 +- #define BRCMF_MSGBUF_TX_FLUSH_CNT2 96 +- +--#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 64 +-+#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96 +- #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32 +- +- struct msgbuf_common_hdr { +-@@ -797,6 +797,8 @@ static int brcmf_msgbuf_txdata(struct br +- struct brcmf_flowring *flow = msgbuf->flow; +- struct ethhdr *eh = (struct ethhdr *)(skb->data); +- u32 flowid; +-+ u32 queue_count; +-+ bool force; +- +- flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx); +- if (flowid == BRCMF_FLOWRING_INVALID_ID) { +-@@ -804,8 +806,9 @@ static int brcmf_msgbuf_txdata(struct br +- if (flowid == BRCMF_FLOWRING_INVALID_ID) +- return -ENOMEM; +- } +-- brcmf_flowring_enqueue(flow, flowid, skb); +-- brcmf_msgbuf_schedule_txdata(msgbuf, flowid, false); +-+ queue_count = brcmf_flowring_enqueue(flow, flowid, skb); +-+ force = ((queue_count % BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) == 0); +-+ brcmf_msgbuf_schedule_txdata(msgbuf, flowid, force); +- +- return 0; +- } +diff --git a/package/kernel/mac80211/patches/370-brcmfmac-remove-pci-shared-structure-rev4-support.patch b/package/kernel/mac80211/patches/370-brcmfmac-remove-pci-shared-structure-rev4-support.patch +deleted file mode 100644 +index 61153c4..0000000 +--- a/package/kernel/mac80211/patches/370-brcmfmac-remove-pci-shared-structure-rev4-support.patch ++++ /dev/null +@@ -1,41 +0,0 @@ +-From: Franky Lin +-Date: Wed, 20 May 2015 14:09:49 +0200 +-Subject: [PATCH] brcmfmac: remove pci shared structure rev4 support +- +-All pcie full dongle chips supported by fmac are using rev 5+ shared +-structure. This patch removes the rev4 related code. +- +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Hante Meuleman +-Reviewed-by: Arend Van Spriel +-Signed-off-by: Franky Lin +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -112,10 +112,9 @@ enum brcmf_pcie_state { +- BRCMF_PCIE_MB_INT_D2H3_DB0 | \ +- BRCMF_PCIE_MB_INT_D2H3_DB1) +- +--#define BRCMF_PCIE_MIN_SHARED_VERSION 4 +-+#define BRCMF_PCIE_MIN_SHARED_VERSION 5 +- #define BRCMF_PCIE_MAX_SHARED_VERSION 5 +- #define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF +--#define BRCMF_PCIE_SHARED_TXPUSH_SUPPORT 0x4000 +- +- #define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000 +- #define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000 +-@@ -1280,11 +1279,6 @@ brcmf_pcie_init_share_ram_info(struct br +- brcmf_err("Unsupported PCIE version %d\n", version); +- return -EINVAL; +- } +-- if (shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT) { +-- brcmf_err("Unsupported legacy TX mode 0x%x\n", +-- shared->flags & BRCMF_PCIE_SHARED_TXPUSH_SUPPORT); +-- return -EINVAL; +-- } +- +- addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET; +- shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr); +diff --git a/package/kernel/mac80211/patches/371-brcmfmac-remove-dummy-cache-flush-invalidate-functio.patch b/package/kernel/mac80211/patches/371-brcmfmac-remove-dummy-cache-flush-invalidate-functio.patch +deleted file mode 100644 +index 8c8eebe..0000000 +--- a/package/kernel/mac80211/patches/371-brcmfmac-remove-dummy-cache-flush-invalidate-functio.patch ++++ /dev/null +@@ -1,120 +0,0 @@ +-From: Franky Lin +-Date: Wed, 20 May 2015 14:09:50 +0200 +-Subject: [PATCH] brcmfmac: remove dummy cache flush/invalidate function +- +-brcmf_dma_flush and brcmf_dma_invalidate_cache are not necessary and +-have never been implemented. +- +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Hante Meuleman +-Reviewed-by: Arend Van Spriel +-Signed-off-by: Franky Lin +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c +-@@ -22,17 +22,6 @@ +- #include "core.h" +- #include "commonring.h" +- +-- +--/* dma flushing needs implementation for mips and arm platforms. Should +-- * be put in util. Note, this is not real flushing. It is virtual non +-- * cached memory. Only write buffers should have to be drained. Though +-- * this may be different depending on platform...... +-- * SEE ALSO msgbuf.c +-- */ +--#define brcmf_dma_flush(addr, len) +--#define brcmf_dma_invalidate_cache(addr, len) +-- +-- +- void brcmf_commonring_register_cb(struct brcmf_commonring *commonring, +- int (*cr_ring_bell)(void *ctx), +- int (*cr_update_rptr)(void *ctx), +-@@ -206,14 +195,9 @@ int brcmf_commonring_write_complete(stru +- address = commonring->buf_addr; +- address += (commonring->f_ptr * commonring->item_len); +- if (commonring->f_ptr > commonring->w_ptr) { +-- brcmf_dma_flush(address, +-- (commonring->depth - commonring->f_ptr) * +-- commonring->item_len); +- address = commonring->buf_addr; +- commonring->f_ptr = 0; +- } +-- brcmf_dma_flush(address, (commonring->w_ptr - commonring->f_ptr) * +-- commonring->item_len); +- +- commonring->f_ptr = commonring->w_ptr; +- +-@@ -258,8 +242,6 @@ void *brcmf_commonring_get_read_ptr(stru +- if (commonring->r_ptr == commonring->depth) +- commonring->r_ptr = 0; +- +-- brcmf_dma_invalidate_cache(ret_addr, *n_ items * commonring->item_len); +-- +- return ret_addr; +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-@@ -278,16 +278,6 @@ struct brcmf_msgbuf_pktids { +- struct brcmf_msgbuf_pktid *array; +- }; +- +-- +--/* dma flushing needs implementation for mips and arm platforms. Should +-- * be put in util. Note, this is not real flushing. It is virtual non +-- * cached memory. Only write buffers should have to be drained. Though +-- * this may be different depending on platform...... +-- */ +--#define brcmf_dma_flush(addr, len) +--#define brcmf_dma_invalidate_cache(addr, len) +-- +-- +- static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf); +- +- +-@@ -462,7 +452,6 @@ static int brcmf_msgbuf_tx_ioctl(struct +- memcpy(msgbuf->ioctbuf, buf, buf_len); +- else +- memset(msgbuf->ioctbuf, 0, buf_len); +-- brcmf_dma_flush(ioctl_buf, buf_len); +- +- err = brcmf_commonring_write_complete(commonring); +- brcmf_commonring_unlock(commonring); +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -276,15 +276,6 @@ static const u32 brcmf_ring_itemsize[BRC +- }; +- +- +--/* dma flushing needs implementation for mips and arm platforms. Should +-- * be put in util. Note, this is not real flushing. It is virtual non +-- * cached memory. Only write buffers should have to be drained. Though +-- * this may be different depending on platform...... +-- */ +--#define brcmf_dma_flush(addr, len) +--#define brcmf_dma_invalidate_cache(addr, len) +-- +-- +- static u32 +- brcmf_pcie_read_reg32(struct brcmf_pciedev_info *devinfo, u32 reg_offset) +- { +-@@ -1174,7 +1165,6 @@ static int brcmf_pcie_init_scratchbuffer +- goto fail; +- +- memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN); +-- brcmf_dma_flush(devinfo->shared.scratch, BRCMF_DMA_D2H_SCRATCH_BUF_LEN); +- +- addr = devinfo->shared.tcm_base_address + +- BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET; +-@@ -1192,7 +1182,6 @@ static int brcmf_pcie_init_scratchbuffer +- goto fail; +- +- memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN); +-- brcmf_dma_flush(devinfo->shared.ringupd, BRCMF_DMA_D2H_RINGUPD_BUF_LEN); +- +- addr = devinfo->shared.tcm_base_address + +- BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET; +diff --git a/package/kernel/mac80211/patches/372-brcmfmac-add-support-for-dma-indices-feature.patch b/package/kernel/mac80211/patches/372-brcmfmac-add-support-for-dma-indices-feature.patch +deleted file mode 100644 +index 2f50abd..0000000 +--- a/package/kernel/mac80211/patches/372-brcmfmac-add-support-for-dma-indices-feature.patch ++++ /dev/null +@@ -1,270 +0,0 @@ +-From: Franky Lin +-Date: Wed, 20 May 2015 14:09:51 +0200 +-Subject: [PATCH] brcmfmac: add support for dma indices feature +- +-PCIe full dongle firmware can support a dma indices feature with which +-firmware can update/fetch the read/write indices of message buffer +-rings on both host to dongle and dongle to host directions. The support is +-announced by firmware through shared flags. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Franky Lin +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -115,6 +115,8 @@ enum brcmf_pcie_state { +- #define BRCMF_PCIE_MIN_SHARED_VERSION 5 +- #define BRCMF_PCIE_MAX_SHARED_VERSION 5 +- #define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF +-+#define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000 +-+#define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000 +- +- #define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000 +- #define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000 +-@@ -146,6 +148,10 @@ enum brcmf_pcie_state { +- #define BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET 8 +- #define BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET 12 +- #define BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET 16 +-+#define BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET 20 +-+#define BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET 28 +-+#define BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET 36 +-+#define BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET 44 +- #define BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET 0 +- #define BRCMF_SHARED_RING_MAX_SUB_QUEUES 52 +- +-@@ -247,6 +253,13 @@ struct brcmf_pciedev_info { +- bool mbdata_completed; +- bool irq_allocated; +- bool wowl_enabled; +-+ u8 dma_idx_sz; +-+ void *idxbuf; +-+ u32 idxbuf_sz; +-+ dma_addr_t idxbuf_dmahandle; +-+ u16 (*read_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset); +-+ void (*write_ptr)(struct brcmf_pciedev_info *devinfo, u32 mem_offset, +-+ u16 value); +- }; +- +- struct brcmf_pcie_ringbuf { +-@@ -323,6 +336,25 @@ brcmf_pcie_write_tcm16(struct brcmf_pcie +- } +- +- +-+static u16 +-+brcmf_pcie_read_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset) +-+{ +-+ u16 *address = devinfo->idxbuf + mem_offset; +-+ +-+ return (*(address)); +-+} +-+ +-+ +-+static void +-+brcmf_pcie_write_idx(struct brcmf_pciedev_info *devinfo, u32 mem_offset, +-+ u16 value) +-+{ +-+ u16 *address = devinfo->idxbuf + mem_offset; +-+ +-+ *(address) = value; +-+} +-+ +-+ +- static u32 +- brcmf_pcie_read_tcm32(struct brcmf_pciedev_info *devinfo, u32 mem_offset) +- { +-@@ -868,7 +900,7 @@ static int brcmf_pcie_ring_mb_write_rptr +- brcmf_dbg(PCIE, "W r_ptr %d (%d), ring %d\n", commonring->r_ptr, +- commonring->w_ptr, ring->id); +- +-- brcmf_pcie_write_tcm16(devinfo, ring->r_idx_addr, commonring->r_ptr); +-+ devinfo->write_ptr(devinfo, ring->r_idx_addr, commonring->r_ptr); +- +- return 0; +- } +-@@ -886,7 +918,7 @@ static int brcmf_pcie_ring_mb_write_wptr +- brcmf_dbg(PCIE, "W w_ptr %d (%d), ring %d\n", commonring->w_ptr, +- commonring->r_ptr, ring->id); +- +-- brcmf_pcie_write_tcm16(devinfo, ring->w_idx_addr, commonring->w_ptr); +-+ devinfo->write_ptr(devinfo, ring->w_idx_addr, commonring->w_ptr); +- +- return 0; +- } +-@@ -915,7 +947,7 @@ static int brcmf_pcie_ring_mb_update_rpt +- if (devinfo->state != BRCMFMAC_PCIE_STATE_UP) +- return -EIO; +- +-- commonring->r_ptr = brcmf_pcie_read_tcm16(devinfo, ring->r_idx_addr); +-+ commonring->r_ptr = devinfo->read_ptr(devinfo, ring->r_idx_addr); +- +- brcmf_dbg(PCIE, "R r_ptr %d (%d), ring %d\n", commonring->r_ptr, +- commonring->w_ptr, ring->id); +-@@ -933,7 +965,7 @@ static int brcmf_pcie_ring_mb_update_wpt +- if (devinfo->state != BRCMFMAC_PCIE_STATE_UP) +- return -EIO; +- +-- commonring->w_ptr = brcmf_pcie_read_tcm16(devinfo, ring->w_idx_addr); +-+ commonring->w_ptr = devinfo->read_ptr(devinfo, ring->w_idx_addr); +- +- brcmf_dbg(PCIE, "R w_ptr %d (%d), ring %d\n", commonring->w_ptr, +- commonring->r_ptr, ring->id); +-@@ -1038,6 +1070,13 @@ static void brcmf_pcie_release_ringbuffe +- } +- kfree(devinfo->shared.flowrings); +- devinfo->shared.flowrings = NULL; +-+ if (devinfo->idxbuf) { +-+ dma_free_coherent(&devinfo->pdev->dev, +-+ devinfo->idxbuf_sz, +-+ devinfo->idxbuf, +-+ devinfo->idxbuf_dmahandle); +-+ devinfo->idxbuf = NULL; +-+ } +- } +- +- +-@@ -1053,19 +1092,72 @@ static int brcmf_pcie_init_ringbuffers(s +- u32 addr; +- u32 ring_mem_ptr; +- u32 i; +-+ u64 address; +-+ u32 bufsz; +- u16 max_sub_queues; +-+ u8 idx_offset; +- +- ring_addr = devinfo->shared.ring_info_addr; +- brcmf_dbg(PCIE, "Base ring addr = 0x%08x\n", ring_addr); +-+ addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES; +-+ max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr); +- +-- addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET; +-- d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +-- addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET; +-- d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +-- addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET; +-- h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +-- addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET; +-- h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +-+ if (devinfo->dma_idx_sz != 0) { +-+ bufsz = (BRCMF_NROF_D2H_COMMON_MSGRINGS + max_sub_queues) * +-+ devinfo->dma_idx_sz * 2; +-+ devinfo->idxbuf = dma_alloc_coherent(&devinfo->pdev->dev, bufsz, +-+ &devinfo->idxbuf_dmahandle, +-+ GFP_KERNEL); +-+ if (!devinfo->idxbuf) +-+ devinfo->dma_idx_sz = 0; +-+ } +-+ +-+ if (devinfo->dma_idx_sz == 0) { +-+ addr = ring_addr + BRCMF_SHARED_RING_D2H_W_IDX_PTR_OFFSET; +-+ d2h_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +-+ addr = ring_addr + BRCMF_SHARED_RING_D2H_R_IDX_PTR_OFFSET; +-+ d2h_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +-+ addr = ring_addr + BRCMF_SHARED_RING_H2D_W_IDX_PTR_OFFSET; +-+ h2d_w_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +-+ addr = ring_addr + BRCMF_SHARED_RING_H2D_R_IDX_PTR_OFFSET; +-+ h2d_r_idx_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +-+ idx_offset = sizeof(u32); +-+ devinfo->write_ptr = brcmf_pcie_write_tcm16; +-+ devinfo->read_ptr = brcmf_pcie_read_tcm16; +-+ brcmf_dbg(PCIE, "Using TCM indices\n"); +-+ } else { +-+ memset(devinfo->idxbuf, 0, bufsz); +-+ devinfo->idxbuf_sz = bufsz; +-+ idx_offset = devinfo->dma_idx_sz; +-+ devinfo->write_ptr = brcmf_pcie_write_idx; +-+ devinfo->read_ptr = brcmf_pcie_read_idx; +-+ +-+ h2d_w_idx_ptr = 0; +-+ addr = ring_addr + BRCMF_SHARED_RING_H2D_WP_HADDR_OFFSET; +-+ address = (u64)devinfo->idxbuf_dmahandle; +-+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); +-+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); +-+ +-+ h2d_r_idx_ptr = h2d_w_idx_ptr + max_sub_queues * idx_offset; +-+ addr = ring_addr + BRCMF_SHARED_RING_H2D_RP_HADDR_OFFSET; +-+ address += max_sub_queues * idx_offset; +-+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); +-+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); +-+ +-+ d2h_w_idx_ptr = h2d_r_idx_ptr + max_sub_queues * idx_offset; +-+ addr = ring_addr + BRCMF_SHARED_RING_D2H_WP_HADDR_OFFSET; +-+ address += max_sub_queues * idx_offset; +-+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); +-+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); +-+ +-+ d2h_r_idx_ptr = d2h_w_idx_ptr + +-+ BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset; +-+ addr = ring_addr + BRCMF_SHARED_RING_D2H_RP_HADDR_OFFSET; +-+ address += BRCMF_NROF_D2H_COMMON_MSGRINGS * idx_offset; +-+ brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff); +-+ brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32); +-+ brcmf_dbg(PCIE, "Using host memory indices\n"); +-+ } +- +- addr = ring_addr + BRCMF_SHARED_RING_TCM_MEMLOC_OFFSET; +- ring_mem_ptr = brcmf_pcie_read_tcm32(devinfo, addr); +-@@ -1079,8 +1171,8 @@ static int brcmf_pcie_init_ringbuffers(s +- ring->id = i; +- devinfo->shared.commonrings[i] = ring; +- +-- h2d_w_idx_ptr += sizeof(u32); +-- h2d_r_idx_ptr += sizeof(u32); +-+ h2d_w_idx_ptr += idx_offset; +-+ h2d_r_idx_ptr += idx_offset; +- ring_mem_ptr += BRCMF_RING_MEM_SZ; +- } +- +-@@ -1094,13 +1186,11 @@ static int brcmf_pcie_init_ringbuffers(s +- ring->id = i; +- devinfo->shared.commonrings[i] = ring; +- +-- d2h_w_idx_ptr += sizeof(u32); +-- d2h_r_idx_ptr += sizeof(u32); +-+ d2h_w_idx_ptr += idx_offset; +-+ d2h_r_idx_ptr += idx_offset; +- ring_mem_ptr += BRCMF_RING_MEM_SZ; +- } +- +-- addr = ring_addr + BRCMF_SHARED_RING_MAX_SUB_QUEUES; +-- max_sub_queues = brcmf_pcie_read_tcm16(devinfo, addr); +- devinfo->shared.nrof_flowrings = +- max_sub_queues - BRCMF_NROF_H2D_COMMON_MSGRINGS; +- rings = kcalloc(devinfo->shared.nrof_flowrings, sizeof(*ring), +-@@ -1124,15 +1214,15 @@ static int brcmf_pcie_init_ringbuffers(s +- ring); +- ring->w_idx_addr = h2d_w_idx_ptr; +- ring->r_idx_addr = h2d_r_idx_ptr; +-- h2d_w_idx_ptr += sizeof(u32); +-- h2d_r_idx_ptr += sizeof(u32); +-+ h2d_w_idx_ptr += idx_offset; +-+ h2d_r_idx_ptr += idx_offset; +- } +- devinfo->shared.flowrings = rings; +- +- return 0; +- +- fail: +-- brcmf_err("Allocating commonring buffers failed\n"); +-+ brcmf_err("Allocating ring buffers failed\n"); +- brcmf_pcie_release_ringbuffers(devinfo); +- return -ENOMEM; +- } +-@@ -1269,6 +1359,14 @@ brcmf_pcie_init_share_ram_info(struct br +- return -EINVAL; +- } +- +-+ /* check firmware support dma indicies */ +-+ if (shared->flags & BRCMF_PCIE_SHARED_DMA_INDEX) { +-+ if (shared->flags & BRCMF_PCIE_SHARED_DMA_2B_IDX) +-+ devinfo->dma_idx_sz = sizeof(u16); +-+ else +-+ devinfo->dma_idx_sz = sizeof(u32); +-+ } +-+ +- addr = sharedram_addr + BRCMF_SHARED_MAX_RXBUFPOST_OFFSET; +- shared->max_rxbufpost = brcmf_pcie_read_tcm16(devinfo, addr); +- if (shared->max_rxbufpost == 0) +diff --git a/package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch b/package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch +deleted file mode 100644 +index 28408d2..0000000 +--- a/package/kernel/mac80211/patches/373-brcmfmac-avoid-null-pointer-access-when-brcmf_msgbuf.patch ++++ /dev/null +@@ -1,102 +0,0 @@ +-From: Arend van Spriel +-Date: Tue, 26 May 2015 13:19:46 +0200 +-Subject: [PATCH] brcmfmac: avoid null pointer access when +- brcmf_msgbuf_get_pktid() fails +- +-The function brcmf_msgbuf_get_pktid() may return a NULL pointer so +-the callers should check the return pointer before accessing it to +-avoid the crash below (see [1]): +- +-brcmfmac: brcmf_msgbuf_get_pktid: Invalid packet id 273 (not in use) +-BUG: unable to handle kernel NULL pointer dereference at 0000000000000080 +-IP: [] skb_pull+0x5/0x50 +-PGD 0 +-Oops: 0000 [#1] PREEMPT SMP +-Modules linked in: pci_stub vboxpci(O) vboxnetflt(O) vboxnetadp(O) vboxdrv(O) +- snd_hda_codec_hdmi bnep mousedev hid_generic ushwmon msr ext4 crc16 mbcache +- jbd2 sd_mod uas usb_storage ahci libahci libata scsi_mod xhci_pci xhci_hcd +- usbcore usb_common +-CPU: 0 PID: 1661 Comm: irq/61-brcmf_pc Tainted: G O 4.0.1-MacbookPro-ARCH #1 +-Hardware name: Apple Inc. MacBookPro12,1/Mac-E43C1C25D4880AD6, +- BIOS MBP121.88Z.0167.B02.1503241251 03/24/2015 +-task: ffff880264203cc0 ti: ffff88025ffe4000 task.ti: ffff88025ffe4000 +-RIP: 0010:[] [] skb_pull+0x5/0x50 +-RSP: 0018:ffff88025ffe7d40 EFLAGS: 00010202 +-RAX: 0000000000000000 RBX: ffff88008a33c000 RCX: 0000000000000044 +-RDX: 0000000000000000 RSI: 000000000000004a RDI: 0000000000000000 +-RBP: ffff88025ffe7da8 R08: 0000000000000096 R09: 000000000000004a +-R10: 0000000000000000 R11: 000000000000048e R12: ffff88025ff14f00 +-R13: 0000000000000000 R14: ffff880263b48200 R15: ffff88008a33c000 +-FS: 0000000000000000(0000) GS:ffff88026ec00000(0000) knlGS:0000000000000000 +-CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +-CR2: 0000000000000080 CR3: 000000000180b000 CR4: 00000000003407f0 +-Stack: +- ffffffffa06aed74 ffff88025ffe7dc8 ffff880263b48270 ffff880263b48278 +- 05ea88020000004a 0002ffff81014635 000000001720b2f6 ffff88026ec116c0 +- ffff880263b48200 0000000000010000 ffff880263b4ae00 ffff880264203cc0 +-Call Trace: +- [] ? brcmf_msgbuf_process_rx+0x404/0x480 [brcmfmac] +- [] ? irq_finalize_oneshot.part.30+0xf0/0xf0 +- [] brcmf_proto_msgbuf_rx_trigger+0x35/0xf0 [brcmfmac] +- [] brcmf_pcie_isr_thread_v2+0x8a/0x130 [brcmfmac] +- [] irq_thread_fn+0x20/0x50 +- [] irq_thread+0x13f/0x170 +- [] ? wake_threads_waitq+0x30/0x30 +- [] ? irq_thread_dtor+0xb0/0xb0 +- [] kthread+0xd8/0xf0 +- [] ? kthread_create_on_node+0x1c0/0x1c0 +- [] ret_from_fork+0x58/0x90 +- [] ? kthread_create_on_node+0x1c0/0x1c0 +-Code: 01 83 e2 f7 88 50 01 48 83 c4 08 5b 5d f3 c3 0f 1f 80 00 00 00 00 83 e2 +- f7 88 50 01 c3 66 0f 1f 84 00 00 00 00 00 0f 1f +-RIP [] skb_pull+0x5/0x50 +- RSP +-CR2: 0000000000000080 +----[ end trace b074c0f90e7c997d ]--- +- +-[1] http://mid.gmane.org/20150430193259.GA5630@googlemail.com +- +-Cc: # v3.18, v3.19, v4.0, v4.1 +-Reported-by: Michael Hornung +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-@@ -500,11 +500,9 @@ static int brcmf_msgbuf_query_dcmd(struc +- msgbuf->rx_pktids, +- msgbuf->ioctl_resp_pktid); +- if (msgbuf->ioctl_resp_ret_len != 0) { +-- if (!skb) { +-- brcmf_err("Invalid packet id idx recv'd %d\n", +-- msgbuf->ioctl_resp_pktid); +-+ if (!skb) +- return -EBADF; +-- } +-+ +- memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ? +- len : msgbuf->ioctl_resp_ret_len); +- } +-@@ -866,10 +864,8 @@ brcmf_msgbuf_process_txstatus(struct brc +- flowid -= BRCMF_NROF_H2D_COMMON_MSGRINGS; +- skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev, +- msgbuf->tx_pktids, idx); +-- if (!skb) { +-- brcmf_err("Invalid packet id idx recv'd %d\n", idx); +-+ if (!skb) +- return; +-- } +- +- set_bit(flowid, msgbuf->txstatus_done_map); +- commonring = msgbuf->flowrings[flowid]; +-@@ -1148,6 +1144,8 @@ brcmf_msgbuf_process_rx_complete(struct +- +- skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev, +- msgbuf->rx_pktids, idx); +-+ if (!skb) +-+ return; +- +- if (data_offset) +- skb_pull(skb, data_offset); +diff --git a/package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch b/package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch +deleted file mode 100644 +index f023034..0000000 +--- a/package/kernel/mac80211/patches/374-brcmfmac-fix-invalid-access-to-struct-acpi_device-fi.patch ++++ /dev/null +@@ -1,63 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 27 May 2015 19:31:41 +0200 +-Subject: [PATCH] brcmfmac: fix invalid access to struct acpi_device fields +- +-The fields of struct acpi_device are only known when CONFIG_ACPI is +-defined. Fix this by using a helper function. This will resolve the +-issue found in linux-next: +- +- ../brcmfmac/bcmsdh.c: In function 'brcmf_ops_sdio_probe': +- ../brcmfmac/bcmsdh.c:1139:7: error: dereferencing pointer to incomplete type +- adev->flags.power_manageable = 0; +- ^ +- +-Fixes: f0992ace680c ("brcmfmac: prohibit ACPI power management ...") +-Cc: Fu, Zhonghui +-Reported-by: Stephen Rothwell +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-@@ -1117,6 +1117,18 @@ MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_id +- static struct brcmfmac_sdio_platform_data *brcmfmac_sdio_pdata; +- +- +-+static void brcmf_sdiod_acpi_set_power_manageable(struct device *dev, +-+ int val) +-+{ +-+#if IS_ENABLED(CONFIG_ACPI) +-+ struct acpi_device *adev; +-+ +-+ adev = ACPI_COMPANION(dev); +-+ if (adev) +-+ adev->flags.power_manageable = 0; +-+#endif +-+} +-+ +- static int brcmf_ops_sdio_probe(struct sdio_func *func, +- const struct sdio_device_id *id) +- { +-@@ -1124,7 +1136,6 @@ static int brcmf_ops_sdio_probe(struct s +- struct brcmf_sdio_dev *sdiodev; +- struct brcmf_bus *bus_if; +- struct device *dev; +-- struct acpi_device *adev; +- +- brcmf_dbg(SDIO, "Enter\n"); +- brcmf_dbg(SDIO, "Class=%x\n", func->class); +-@@ -1132,11 +1143,9 @@ static int brcmf_ops_sdio_probe(struct s +- brcmf_dbg(SDIO, "sdio device ID: 0x%04x\n", func->device); +- brcmf_dbg(SDIO, "Function#: %d\n", func->num); +- +-- /* prohibit ACPI power management for this device */ +- dev = &func->dev; +-- adev = ACPI_COMPANION(dev); +-- if (adev) +-- adev->flags.power_manageable = 0; +-+ /* prohibit ACPI power management for this device */ +-+ brcmf_sdiod_acpi_set_power_manageable(dev, 0); +- +- /* Consume func num 1 but dont do anything with it. */ +- if (func->num == 1) +diff --git a/package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch b/package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch +deleted file mode 100644 +index 2bfd44f..0000000 +--- a/package/kernel/mac80211/patches/375-brcmfmac-simplify-check-stripping-v2-NVRAM.patch ++++ /dev/null +@@ -1,56 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Wed, 20 May 2015 09:34:21 +0200 +-Subject: [PATCH] brcmfmac: simplify check stripping v2 NVRAM +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-Comparing NVRAM entry with a full filtering string is simpler than +-comparing it with a short prefix and then checking random chars at magic +-offsets. The cost of snprintf relatively low, we execute it just once. +-Tested on BCM43602 with NVRAM hacked to use V2 format. +- +-Signed-off-by: Rafał Miłecki +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-@@ -25,7 +25,7 @@ +- +- #define BRCMF_FW_MAX_NVRAM_SIZE 64000 +- #define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */ +--#define BRCMF_FW_NVRAM_PCIEDEV_LEN 9 /* pcie/1/4/ */ +-+#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */ +- +- char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; +- module_param_string(firmware_path, brcmf_firmware_path, +-@@ -297,6 +297,8 @@ fail: +- static void brcmf_fw_strip_multi_v2(struct nvram_parser *nvp, u16 domain_nr, +- u16 bus_nr) +- { +-+ char prefix[BRCMF_FW_NVRAM_PCIEDEV_LEN]; +-+ size_t len; +- u32 i, j; +- u8 *nvram; +- +-@@ -308,14 +310,13 @@ static void brcmf_fw_strip_multi_v2(stru +- * Valid entries are of type pcie/X/Y/ where X = domain_nr and +- * Y = bus_nr. +- */ +-+ snprintf(prefix, sizeof(prefix), "pcie/%d/%d/", domain_nr, bus_nr); +-+ len = strlen(prefix); +- i = 0; +- j = 0; +-- while (i < nvp->nvram_len - BRCMF_FW_NVRAM_PCIEDEV_LEN) { +-- if ((strncmp(&nvp->nvram[i], "pcie/", 5) == 0) && +-- (nvp->nvram[i + 6] == '/') && (nvp->nvram[i + 8] == '/') && +-- ((nvp->nvram[i + 5] - '0') == domain_nr) && +-- ((nvp->nvram[i + 7] - '0') == bus_nr)) { +-- i += BRCMF_FW_NVRAM_PCIEDEV_LEN; +-+ while (i < nvp->nvram_len - len) { +-+ if (strncmp(&nvp->nvram[i], prefix, len) == 0) { +-+ i += len; +- while (nvp->nvram[i] != 0) { +- nvram[j] = nvp->nvram[i]; +- i++; +diff --git a/package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch b/package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch +deleted file mode 100644 +index 0e65114..0000000 +--- a/package/kernel/mac80211/patches/376-brcmfmac-simplify-check-finding-NVRAM-v1-device-path.patch ++++ /dev/null +@@ -1,57 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Wed, 20 May 2015 11:01:08 +0200 +-Subject: [PATCH] brcmfmac: simplify check finding NVRAM v1 device path +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-With a simple use of snprintf and small buffer we can compare NVRAM +-entry value with a full string. This way we avoid checking random chars +-at magic offsets. +-Tested on BCM43602 with NVRAM hacked to use v1 format. +- +-Signed-off-by: Rafał Miłecki +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-@@ -222,6 +222,10 @@ static int brcmf_init_nvram_parser(struc +- static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr, +- u16 bus_nr) +- { +-+ /* Device path with a leading '=' key-value separator */ +-+ char pcie_path[] = "=pcie/?/?"; +-+ size_t pcie_len; +-+ +- u32 i, j; +- bool found; +- u8 *nvram; +-@@ -238,6 +242,9 @@ static void brcmf_fw_strip_multi_v1(stru +- /* First search for the devpathX and see if it is the configuration +- * for domain_nr/bus_nr. Search complete nvp +- */ +-+ snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr, +-+ bus_nr); +-+ pcie_len = strlen(pcie_path); +- found = false; +- i = 0; +- while (i < nvp->nvram_len - BRCMF_FW_NVRAM_DEVPATH_LEN) { +-@@ -245,13 +252,10 @@ static void brcmf_fw_strip_multi_v1(stru +- * Y = domain_nr, Z = bus_nr, X = virtual ID +- */ +- if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) && +-- (strncmp(&nvp->nvram[i + 8], "=pcie/", 6) == 0)) { +-- if (((nvp->nvram[i + 14] - '0') == domain_nr) && +-- ((nvp->nvram[i + 16] - '0') == bus_nr)) { +-- id = nvp->nvram[i + 7] - '0'; +-- found = true; +-- break; +-- } +-+ (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) { +-+ id = nvp->nvram[i + 7] - '0'; +-+ found = true; +-+ break; +- } +- while (nvp->nvram[i] != 0) +- i++; +diff --git a/package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch b/package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch +deleted file mode 100644 +index dc174e5..0000000 +--- a/package/kernel/mac80211/patches/377-brcmfmac-treat-0-as-end-of-comment-when-parsing-NVRA.patch ++++ /dev/null +@@ -1,45 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Wed, 20 May 2015 13:59:54 +0200 +-Subject: [PATCH] brcmfmac: treat \0 as end of comment when parsing NVRAM +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-This fixes brcmfmac dealing with NVRAM coming from platform e.g. from a +-flash MTD partition. In such cases entries are separated by \0 instead +-of \n which caused ignoring whole content after the first "comment". +-While platform NVRAM doesn't usually contain comments, we switch to +-COMMENT state after e.g. finding an unexpected char in key name. +- +-Signed-off-by: Rafał Miłecki +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-@@ -162,17 +162,20 @@ brcmf_nvram_handle_value(struct nvram_pa +- static enum nvram_parser_state +- brcmf_nvram_handle_comment(struct nvram_parser *nvp) +- { +-- char *eol, *sol; +-+ char *eoc, *sol; +- +- sol = (char *)&nvp->fwnv->data[nvp->pos]; +-- eol = strchr(sol, '\n'); +-- if (eol == NULL) +-- return END; +-+ eoc = strchr(sol, '\n'); +-+ if (!eoc) { +-+ eoc = strchr(sol, '\0'); +-+ if (!eoc) +-+ return END; +-+ } +- +- /* eat all moving to next line */ +- nvp->line++; +- nvp->column = 1; +-- nvp->pos += (eol - sol) + 1; +-+ nvp->pos += (eoc - sol) + 1; +- return IDLE; +- } +- +diff --git a/package/kernel/mac80211/patches/378-brcmfmac-allow-NVRAM-values-to-contain-spaces.patch b/package/kernel/mac80211/patches/378-brcmfmac-allow-NVRAM-values-to-contain-spaces.patch +deleted file mode 100644 +index 5700142..0000000 +--- a/package/kernel/mac80211/patches/378-brcmfmac-allow-NVRAM-values-to-contain-spaces.patch ++++ /dev/null +@@ -1,50 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Sat, 23 May 2015 09:15:33 +0200 +-Subject: [PATCH] brcmfmac: allow NVRAM values to contain spaces +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-Platform NVRAMs often contain values with spaces. Even if right now most +-firmware-supported entries are simple values, we shouldn't reject these +-with spaces. It was semi-confirmed by Broadcom in the early patch adding +-support for platform NVRAMs. +- +-Signed-off-by: Rafał Miłecki +-Acked-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-@@ -66,6 +66,12 @@ struct nvram_parser { +- bool multi_dev_v2; +- }; +- +-+/** +-+ * is_nvram_char() - check if char is a valid one for NVRAM entry +-+ * +-+ * It accepts all printable ASCII chars except for '#' which opens a comment. +-+ * Please note that ' ' (space) while accepted is not a valid key name char. +-+ */ +- static bool is_nvram_char(char c) +- { +- /* comment marker excluded */ +-@@ -73,7 +79,7 @@ static bool is_nvram_char(char c) +- return false; +- +- /* key and value may have any other readable character */ +-- return (c > 0x20 && c < 0x7f); +-+ return (c >= 0x20 && c < 0x7f); +- } +- +- static bool is_whitespace(char c) +-@@ -120,7 +126,7 @@ static enum nvram_parser_state brcmf_nvr +- nvp->multi_dev_v1 = true; +- if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0) +- nvp->multi_dev_v2 = true; +-- } else if (!is_nvram_char(c)) { +-+ } else if (!is_nvram_char(c) || c == ' ') { +- brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", +- nvp->line, nvp->column); +- return COMMENT; +diff --git a/package/kernel/mac80211/patches/379-ath9k-fix-DMA-stop-sequence-for-AR9003.patch b/package/kernel/mac80211/patches/379-ath9k-fix-DMA-stop-sequence-for-AR9003.patch +deleted file mode 100644 +index 814b0d7..0000000 +--- a/package/kernel/mac80211/patches/379-ath9k-fix-DMA-stop-sequence-for-AR9003.patch ++++ /dev/null +@@ -1,33 +0,0 @@ +-From: Felix Fietkau +-Date: Tue, 2 Jun 2015 10:35:46 +0200 +-Subject: [PATCH] ath9k: fix DMA stop sequence for AR9003+ +- +-AR93xx and newer needs to stop rx before tx to avoid getting the DMA +-engine or MAC into a stuck state. +-This should reduce/fix the occurence of "Failed to stop Tx DMA" logspam. +- +-Cc: stable@vger.kernel.org +-Signed-off-by: Felix Fietkau +---- +- +---- a/drivers/net/wireless/ath/ath9k/main.c +-+++ b/drivers/net/wireless/ath/ath9k/main.c +-@@ -216,11 +216,13 @@ static bool ath_prepare_reset(struct ath +- ath_stop_ani(sc); +- ath9k_hw_disable_interrupts(ah); +- +-- if (!ath_drain_all_txq(sc)) +-- ret = false; +-- +-- if (!ath_stoprecv(sc)) +-- ret = false; +-+ if (AR_SREV_9300_20_OR_LATER(ah)) { +-+ ret &= ath_stoprecv(sc); +-+ ret &= ath_drain_all_txq(sc); +-+ } else { +-+ ret &= ath_drain_all_txq(sc); +-+ ret &= ath_stoprecv(sc); +-+ } +- +- return ret; +- } +diff --git a/package/kernel/mac80211/patches/380-brcmfmac-support-NVRAMs-containing-pci-devpaths-inst.patch b/package/kernel/mac80211/patches/380-brcmfmac-support-NVRAMs-containing-pci-devpaths-inst.patch +deleted file mode 100644 +index 7bbd57e..0000000 +--- a/package/kernel/mac80211/patches/380-brcmfmac-support-NVRAMs-containing-pci-devpaths-inst.patch ++++ /dev/null +@@ -1,56 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Thu, 28 May 2015 14:19:21 +0200 +-Subject: [PATCH] brcmfmac: support NVRAMs containing pci devpaths (instead of +- pcie) +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-Recently Broadcom added support for NVRAMs with entries for multiple +-PCIe devices. One of the supported formats is based on prefixes defined +-like: devpath0=pcie/1/4/ and entries like 0:foo=bar 0:baz=qux etc. +- +-Unfortunately there are also a bit older devices using different way of +-defining prefixes, e.g. SmartRG SR400ac (2 x BCM43602) with entries: +-devpath0=pci/1/1/ +-devpath1=pci/2/1 +-Broadcom stated this old format will never be used/supported by brcmfmac +-but given the simplicity of this patch I'll insist on supporting it. +- +-Signed-off-by: Rafał Miłecki +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-@@ -232,6 +232,8 @@ static void brcmf_fw_strip_multi_v1(stru +- u16 bus_nr) +- { +- /* Device path with a leading '=' key-value separator */ +-+ char pci_path[] = "=pci/?/?"; +-+ size_t pci_len; +- char pcie_path[] = "=pcie/?/?"; +- size_t pcie_len; +- +-@@ -251,6 +253,9 @@ static void brcmf_fw_strip_multi_v1(stru +- /* First search for the devpathX and see if it is the configuration +- * for domain_nr/bus_nr. Search complete nvp +- */ +-+ snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr, +-+ bus_nr); +-+ pci_len = strlen(pci_path); +- snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr, +- bus_nr); +- pcie_len = strlen(pcie_path); +-@@ -260,8 +265,9 @@ static void brcmf_fw_strip_multi_v1(stru +- /* Format: devpathX=pcie/Y/Z/ +- * Y = domain_nr, Z = bus_nr, X = virtual ID +- */ +-- if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) && +-- (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) { +-+ if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 && +-+ (!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) || +-+ !strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) { +- id = nvp->nvram[i + 7] - '0'; +- found = true; +- break; +diff --git a/package/kernel/mac80211/patches/381-brcmfmac-set-wiphy-perm_addr-to-hardware-MAC-address.patch b/package/kernel/mac80211/patches/381-brcmfmac-set-wiphy-perm_addr-to-hardware-MAC-address.patch +deleted file mode 100644 +index 1eff6ed..0000000 +--- a/package/kernel/mac80211/patches/381-brcmfmac-set-wiphy-perm_addr-to-hardware-MAC-address.patch ++++ /dev/null +@@ -1,23 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Sun, 31 May 2015 02:52:26 +0200 +-Subject: [PATCH] brcmfmac: set wiphy perm_addr to hardware MAC address +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-This allows e.g. user space to use /sys/class/ieee80211/*/macaddress +- +-Signed-off-by: Rafał Miłecki +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -6070,6 +6070,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802 +- brcmf_err("Could not allocate wiphy device\n"); +- return NULL; +- } +-+ memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN); +- set_wiphy_dev(wiphy, busdev); +- +- cfg = wiphy_priv(wiphy); +diff --git a/package/kernel/mac80211/patches/382-brcmfmac-use-direct-data-pointer-in-NVRAM-parser-str.patch b/package/kernel/mac80211/patches/382-brcmfmac-use-direct-data-pointer-in-NVRAM-parser-str.patch +deleted file mode 100644 +index c6e83dd..0000000 +--- a/package/kernel/mac80211/patches/382-brcmfmac-use-direct-data-pointer-in-NVRAM-parser-str.patch ++++ /dev/null +@@ -1,144 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Thu, 4 Jun 2015 22:11:07 +0200 +-Subject: [PATCH] brcmfmac: use direct data pointer in NVRAM parser struct +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-As we plan to add support for platform NVRAM we should store direct +-data pointer without the extra struct firmware layer. This will allow +-us to support other sources with the only requirement being u8 buffer. +- +-Signed-off-by: Rafał Miłecki +-Acked-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +-@@ -43,7 +43,7 @@ enum nvram_parser_state { +- * struct nvram_parser - internal info for parser. +- * +- * @state: current parser state. +-- * @fwnv: input buffer being parsed. +-+ * @data: input buffer being parsed. +- * @nvram: output buffer with parse result. +- * @nvram_len: lenght of parse result. +- * @line: current line. +-@@ -55,7 +55,7 @@ enum nvram_parser_state { +- */ +- struct nvram_parser { +- enum nvram_parser_state state; +-- const struct firmware *fwnv; +-+ const u8 *data; +- u8 *nvram; +- u32 nvram_len; +- u32 line; +-@@ -91,7 +91,7 @@ static enum nvram_parser_state brcmf_nvr +- { +- char c; +- +-- c = nvp->fwnv->data[nvp->pos]; +-+ c = nvp->data[nvp->pos]; +- if (c == '\n') +- return COMMENT; +- if (is_whitespace(c)) +-@@ -115,16 +115,16 @@ static enum nvram_parser_state brcmf_nvr +- enum nvram_parser_state st = nvp->state; +- char c; +- +-- c = nvp->fwnv->data[nvp->pos]; +-+ c = nvp->data[nvp->pos]; +- if (c == '=') { +- /* ignore RAW1 by treating as comment */ +-- if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0) +-+ if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0) +- st = COMMENT; +- else +- st = VALUE; +-- if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0) +-+ if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0) +- nvp->multi_dev_v1 = true; +-- if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0) +-+ if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0) +- nvp->multi_dev_v2 = true; +- } else if (!is_nvram_char(c) || c == ' ') { +- brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", +-@@ -145,11 +145,11 @@ brcmf_nvram_handle_value(struct nvram_pa +- char *ekv; +- u32 cplen; +- +-- c = nvp->fwnv->data[nvp->pos]; +-+ c = nvp->data[nvp->pos]; +- if (!is_nvram_char(c)) { +- /* key,value pair complete */ +-- ekv = (u8 *)&nvp->fwnv->data[nvp->pos]; +-- skv = (u8 *)&nvp->fwnv->data[nvp->entry]; +-+ ekv = (u8 *)&nvp->data[nvp->pos]; +-+ skv = (u8 *)&nvp->data[nvp->entry]; +- cplen = ekv - skv; +- if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE) +- return END; +-@@ -170,7 +170,7 @@ brcmf_nvram_handle_comment(struct nvram_ +- { +- char *eoc, *sol; +- +-- sol = (char *)&nvp->fwnv->data[nvp->pos]; +-+ sol = (char *)&nvp->data[nvp->pos]; +- eoc = strchr(sol, '\n'); +- if (!eoc) { +- eoc = strchr(sol, '\0'); +-@@ -201,17 +201,17 @@ static enum nvram_parser_state +- }; +- +- static int brcmf_init_nvram_parser(struct nvram_parser *nvp, +-- const struct firmware *nv) +-+ const u8 *data, size_t data_len) +- { +- size_t size; +- +- memset(nvp, 0, sizeof(*nvp)); +-- nvp->fwnv = nv; +-+ nvp->data = data; +- /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */ +-- if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE) +-+ if (data_len > BRCMF_FW_MAX_NVRAM_SIZE) +- size = BRCMF_FW_MAX_NVRAM_SIZE; +- else +-- size = nv->size; +-+ size = data_len; +- /* Alloc for extra 0 byte + roundup by 4 + length field */ +- size += 1 + 3 + sizeof(u32); +- nvp->nvram = kzalloc(size, GFP_KERNEL); +-@@ -362,18 +362,18 @@ fail: +- * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. +- * End of buffer is completed with token identifying length of buffer. +- */ +--static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length, +-- u16 domain_nr, u16 bus_nr) +-+static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len, +-+ u32 *new_length, u16 domain_nr, u16 bus_nr) +- { +- struct nvram_parser nvp; +- u32 pad; +- u32 token; +- __le32 token_le; +- +-- if (brcmf_init_nvram_parser(&nvp, nv) < 0) +-+ if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0) +- return NULL; +- +-- while (nvp.pos < nv->size) { +-+ while (nvp.pos < data_len) { +- nvp.state = nv_parser_states[nvp.state](&nvp); +- if (nvp.state == END) +- break; +-@@ -432,7 +432,7 @@ static void brcmf_fw_request_nvram_done( +- goto fail; +- +- if (fw) { +-- nvram = brcmf_fw_nvram_strip(fw, &nvram_length, +-+ nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length, +- fwctx->domain_nr, fwctx->bus_nr); +- release_firmware(fw); +- if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) +diff --git a/package/kernel/mac80211/patches/383-b43-fix-support-for-14e4-4321-PCI-dev-with-BCM4321-c.patch b/package/kernel/mac80211/patches/383-b43-fix-support-for-14e4-4321-PCI-dev-with-BCM4321-c.patch +deleted file mode 100644 +index 4ecef3b..0000000 +--- a/package/kernel/mac80211/patches/383-b43-fix-support-for-14e4-4321-PCI-dev-with-BCM4321-c.patch ++++ /dev/null +@@ -1,32 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Sat, 6 Jun 2015 22:45:59 +0200 +-Subject: [PATCH] b43: fix support for 14e4:4321 PCI dev with BCM4321 chipset +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-It seems Broadcom released two devices with conflicting device id. There +-are for sure 14e4:4321 PCI devices with BCM4321 (N-PHY) chipset, they +-can be found in routers, e.g. Netgear WNR834Bv2. However, according to +-Broadcom public sources 0x4321 is also used for 5 GHz BCM4306 (G-PHY). +-It's unsure if they meant PCI device id, or "virtual" id (from SPROM). +-To distinguish these devices lets check PHY type (G vs. N). +- +-Signed-off-by: Rafał Miłecki +-Cc: # 3.16+ +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/b43/main.c +-+++ b/drivers/net/wireless/b43/main.c +-@@ -5365,6 +5365,10 @@ static void b43_supported_bands(struct b +- *have_5ghz_phy = true; +- return; +- case 0x4321: /* BCM4306 */ +-+ /* There are 14e4:4321 PCI devs with 2.4 GHz BCM4321 (N-PHY) */ +-+ if (dev->phy.type != B43_PHYTYPE_G) +-+ break; +-+ /* fall through */ +- case 0x4313: /* BCM4311 */ +- case 0x431a: /* BCM4318 */ +- case 0x432a: /* BCM4321 */ +diff --git a/package/kernel/mac80211/patches/384-ath9k-force-rx_clear-when-disabling-rx.patch b/package/kernel/mac80211/patches/384-ath9k-force-rx_clear-when-disabling-rx.patch +deleted file mode 100644 +index bddb15a..0000000 +--- a/package/kernel/mac80211/patches/384-ath9k-force-rx_clear-when-disabling-rx.patch ++++ /dev/null +@@ -1,31 +0,0 @@ +-From: Felix Fietkau +-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 +-Rx related DMA stop warnings +- +-Cc: stable@vger.kernel.org +-Signed-off-by: Felix Fietkau +---- +- +---- a/drivers/net/wireless/ath/ath9k/mac.c +-+++ b/drivers/net/wireless/ath/ath9k/mac.c +-@@ -677,13 +677,15 @@ void ath9k_hw_startpcureceive(struct ath +- +- ath9k_ani_reset(ah, is_scanning); +- +-- REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); +-+ REG_CLR_BIT(ah, AR_DIAG_SW, +-+ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); +- } +- EXPORT_SYMBOL(ath9k_hw_startpcureceive); +- +- void ath9k_hw_abortpcurecv(struct ath_hw *ah) +- { +-- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); +-+ REG_SET_BIT(ah, AR_DIAG_SW, +-+ AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT | AR_DIAG_FORCE_RX_CLEAR); +- +- ath9k_hw_disable_mib_counters(ah); +- } +diff --git a/package/kernel/mac80211/patches/385-ath9k_hw-fix-device-ID-check-for-AR956x.patch b/package/kernel/mac80211/patches/385-ath9k_hw-fix-device-ID-check-for-AR956x.patch +deleted file mode 100644 +index 2674efb..0000000 +--- a/package/kernel/mac80211/patches/385-ath9k_hw-fix-device-ID-check-for-AR956x.patch ++++ /dev/null +@@ -1,20 +0,0 @@ +-From: Felix Fietkau +-Date: Sun, 21 Jun 2015 19:45:59 +0200 +-Subject: [PATCH] ath9k_hw: fix device ID check for AR956x +- +-Because of the missing return, the macVersion value was being +-overwritten with an invalid register read +- +-Signed-off-by: Felix Fietkau +---- +- +---- a/drivers/net/wireless/ath/ath9k/hw.c +-+++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -278,6 +278,7 @@ static void ath9k_hw_read_revisions(stru +- return; +- case AR9300_DEVID_QCA956X: +- ah->hw_version.macVersion = AR_SREV_VERSION_9561; +-+ return; +- } +- +- val = REG_READ(ah, AR_SREV) & AR_SREV_ID; +diff --git a/package/kernel/mac80211/patches/385-brcmfmac-Update-msgbuf-read-pointer-quicker.patch b/package/kernel/mac80211/patches/385-brcmfmac-Update-msgbuf-read-pointer-quicker.patch +deleted file mode 100644 +index 74df9f9..0000000 +--- a/package/kernel/mac80211/patches/385-brcmfmac-Update-msgbuf-read-pointer-quicker.patch ++++ /dev/null +@@ -1,109 +0,0 @@ +-From: Hante Meuleman +-Date: Mon, 8 Jun 2015 14:38:32 +0200 +-Subject: [PATCH] brcmfmac: Update msgbuf read pointer quicker. +- +-On device to host data using msgbuf the read pointer gets updated +-once all data is processed. Updating this pointer more frequently +-allows the firmware to add more data quicker. This will result in +-slightly higher and more stable throughput on CPU bounded host +-processors. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c +-@@ -223,8 +223,6 @@ void brcmf_commonring_write_cancel(struc +- void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, +- u16 *n_items) +- { +-- void *ret_addr; +-- +- if (commonring->cr_update_wptr) +- commonring->cr_update_wptr(commonring->cr_ctx); +- +-@@ -235,19 +233,18 @@ void *brcmf_commonring_get_read_ptr(stru +- if (*n_items == 0) +- return NULL; +- +-- ret_addr = commonring->buf_addr + +-- (commonring->r_ptr * commonring->item_len); +-- +-- commonring->r_ptr += *n_items; +-- if (commonring->r_ptr == commonring->depth) +-- commonring->r_ptr = 0; +-- +-- return ret_addr; +-+ return commonring->buf_addr + +-+ (commonring->r_ptr * commonring->item_len); +- } +- +- +--int brcmf_commonring_read_complete(struct brcmf_commonring *commonring) +-+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring, +-+ u16 n_items) +- { +-+ commonring->r_ptr += n_items; +-+ if (commonring->r_ptr == commonring->depth) +-+ commonring->r_ptr = 0; +-+ +- if (commonring->cr_write_rptr) +- return commonring->cr_write_rptr(commonring->cr_ctx); +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h +-@@ -62,7 +62,8 @@ void brcmf_commonring_write_cancel(struc +- u16 n_items); +- void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, +- u16 *n_items); +--int brcmf_commonring_read_complete(struct brcmf_commonring *commonring); +-+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring, +-+ u16 n_items); +- +- #define brcmf_commonring_n_items(commonring) (commonring->depth) +- #define brcmf_commonring_len_item(commonring) (commonring->item_len) +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-@@ -75,6 +75,8 @@ +- +- #define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96 +- #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32 +-+#define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS 48 +-+ +- +- struct msgbuf_common_hdr { +- u8 msgtype; +-@@ -1257,19 +1259,27 @@ static void brcmf_msgbuf_process_rx(stru +- { +- void *buf; +- u16 count; +-+ u16 processed; +- +- again: +- buf = brcmf_commonring_get_read_ptr(commonring, &count); +- if (buf == NULL) +- return; +- +-+ processed = 0; +- while (count) { +- brcmf_msgbuf_process_msgtype(msgbuf, +- buf + msgbuf->rx_dataoffset); +- buf += brcmf_commonring_len_item(commonring); +-+ processed++; +-+ if (processed == BRCMF_MSGBUF_UPDATE_RX_PTR_THRS) { +-+ brcmf_commonring_read_complete(commonring, processed); +-+ processed = 0; +-+ } +- count--; +- } +-- brcmf_commonring_read_complete(commonring); +-+ if (processed) +-+ brcmf_commonring_read_complete(commonring, processed); +- +- if (commonring->r_ptr == 0) +- goto again; +diff --git a/package/kernel/mac80211/patches/386-brcmfmac-remove-chipinfo-debugfs-entry.patch b/package/kernel/mac80211/patches/386-brcmfmac-remove-chipinfo-debugfs-entry.patch +deleted file mode 100644 +index 9e5b486..0000000 +--- a/package/kernel/mac80211/patches/386-brcmfmac-remove-chipinfo-debugfs-entry.patch ++++ /dev/null +@@ -1,39 +0,0 @@ +-From: Arend van Spriel +-Date: Mon, 8 Jun 2015 14:38:33 +0200 +-Subject: [PATCH] brcmfmac: remove chipinfo debugfs entry +- +-The information provided by chipinfo is also provided by the +-revinfo debugfs entry. Removing it from debugfs. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c +-@@ -41,15 +41,6 @@ void brcmf_debugfs_exit(void) +- root_folder = NULL; +- } +- +--static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data) +--{ +-- struct brcmf_bus *bus = dev_get_drvdata(seq->private); +-- +-- seq_printf(seq, "chip: %x(%u) rev %u\n", +-- bus->chip, bus->chip, bus->chiprev); +-- return 0; +--} +-- +- int brcmf_debugfs_attach(struct brcmf_pub *drvr) +- { +- struct device *dev = drvr->bus_if->dev; +-@@ -58,7 +49,6 @@ int brcmf_debugfs_attach(struct brcmf_pu +- return -ENODEV; +- +- drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); +-- brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read); +- +- return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); +- } +diff --git a/package/kernel/mac80211/patches/387-brcmfmac-remove-watchdog-reset-from-brcmf_pcie_busco.patch b/package/kernel/mac80211/patches/387-brcmfmac-remove-watchdog-reset-from-brcmf_pcie_busco.patch +deleted file mode 100644 +index c38b2cd..0000000 +--- a/package/kernel/mac80211/patches/387-brcmfmac-remove-watchdog-reset-from-brcmf_pcie_busco.patch ++++ /dev/null +@@ -1,53 +0,0 @@ +-From: Arend van Spriel +-Date: Mon, 8 Jun 2015 14:38:34 +0200 +-Subject: [PATCH] brcmfmac: remove watchdog reset from +- brcmf_pcie_buscoreprep() +- +-The watchdog reset as done in brcmf_pcie_buscoreprep() is not +-sufficient. It needs to modify PCIe core registers as well +-which is properly done by brcmf_pcie_reset_device() after the +-chip recognition is done. So the faulty watchdog reset can be +-removed as it was causing driver reload to fail and hang the +-system requiring a power-cycle. Instead the call to to the +-brcmf_pcie_reset_device() function is done twice in the unload. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Daniel (Deognyoun) Kim +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -1629,20 +1629,7 @@ static void brcmf_pcie_buscore_write32(v +- +- static int brcmf_pcie_buscoreprep(void *ctx) +- { +-- struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; +-- int err; +-- +-- err = brcmf_pcie_get_resource(devinfo); +-- if (err == 0) { +-- /* Set CC watchdog to reset all the cores on the chip to bring +-- * back dongle to a sane state. +-- */ +-- brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE, +-- watchdog), 4); +-- msleep(100); +-- } +-- +-- return err; +-+ return brcmf_pcie_get_resource(ctx); +- } +- +- +-@@ -1824,6 +1811,7 @@ brcmf_pcie_remove(struct pci_dev *pdev) +- brcmf_pcie_intr_disable(devinfo); +- +- brcmf_detach(&pdev->dev); +-+ brcmf_pcie_reset_device(devinfo); +- +- kfree(bus->bus_priv.pcie); +- kfree(bus->msgbuf->flowrings); +diff --git a/package/kernel/mac80211/patches/388-brcmfmac-use-debugfs_create_devm_seqfile-helper-func.patch b/package/kernel/mac80211/patches/388-brcmfmac-use-debugfs_create_devm_seqfile-helper-func.patch +deleted file mode 100644 +index 756fbb2..0000000 +--- a/package/kernel/mac80211/patches/388-brcmfmac-use-debugfs_create_devm_seqfile-helper-func.patch ++++ /dev/null +@@ -1,69 +0,0 @@ +-From: Arend van Spriel +-Date: Mon, 8 Jun 2015 14:38:35 +0200 +-Subject: [PATCH] brcmfmac: use debugfs_create_devm_seqfile() helper +- function +- +-Some time ago the function debugfs_create_devm_seqfile() was +-introduced in debugfs. The caller simply needs to provide a +-device pointer and read function. The function brcmf_debugfs_add_entry() +-is now simply a wrapper only doing the work for CONFIG_BRCMDBG. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Daniel (Deognyoun) Kim +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c +-@@ -64,44 +64,12 @@ struct dentry *brcmf_debugfs_get_devdir( +- return drvr->dbgfs_dir; +- } +- +--struct brcmf_debugfs_entry { +-- int (*read)(struct seq_file *seq, void *data); +-- struct brcmf_pub *drvr; +--}; +-- +--static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f) +--{ +-- struct brcmf_debugfs_entry *entry = inode->i_private; +-- +-- return single_open(f, entry->read, entry->drvr->bus_if->dev); +--} +-- +--static const struct file_operations brcmf_debugfs_def_ops = { +-- .owner = THIS_MODULE, +-- .open = brcmf_debugfs_entry_open, +-- .release = single_release, +-- .read = seq_read, +-- .llseek = seq_lseek +--}; +-- +- int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, +- int (*read_fn)(struct seq_file *seq, void *data)) +- { +-- struct dentry *dentry = drvr->dbgfs_dir; +-- struct brcmf_debugfs_entry *entry; +-- +-- if (IS_ERR_OR_NULL(dentry)) +-- return -ENOENT; +-- +-- entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL); +-- if (!entry) +-- return -ENOMEM; +-- +-- entry->read = read_fn; +-- entry->drvr = drvr; +-- +-- dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry, +-- &brcmf_debugfs_def_ops); +-+ struct dentry *e; +- +-- return PTR_ERR_OR_ZERO(dentry); +-+ e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn, +-+ drvr->dbgfs_dir, read_fn); +-+ return PTR_ERR_OR_ZERO(e); +- } +diff --git a/package/kernel/mac80211/patches/389-0001-brcmfmac-Check-if-firmware-supports-p2p.patch b/package/kernel/mac80211/patches/389-0001-brcmfmac-Check-if-firmware-supports-p2p.patch +deleted file mode 100644 +index ff24a4a..0000000 +--- a/package/kernel/mac80211/patches/389-0001-brcmfmac-Check-if-firmware-supports-p2p.patch ++++ /dev/null +@@ -1,42 +0,0 @@ +-From: Pontus Fuchs +-Date: Thu, 11 Jun 2015 00:12:17 +0200 +-Subject: [PATCH] brcmfmac: Check if firmware supports p2p +- +-Add a feature flag to reflect the firmware's p2p capability. +- +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Hante Meuleman +-Reviewed-by: Arend Van Spriel +-Signed-off-by: Pontus Fuchs +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c +-@@ -129,6 +129,7 @@ void brcmf_feat_attach(struct brcmf_pub +- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl"); +- if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID) +- brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); +-+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p"); +- +- /* set chip related quirks */ +- switch (drvr->bus_if->chip) { +---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h +-@@ -23,12 +23,14 @@ +- * MCHAN: multi-channel for concurrent P2P. +- * PNO: preferred network offload. +- * WOWL: Wake-On-WLAN. +-+ * P2P: peer-to-peer +- */ +- #define BRCMF_FEAT_LIST \ +- BRCMF_FEAT_DEF(MBSS) \ +- BRCMF_FEAT_DEF(MCHAN) \ +- BRCMF_FEAT_DEF(PNO) \ +-- BRCMF_FEAT_DEF(WOWL) +-+ BRCMF_FEAT_DEF(WOWL) \ +-+ BRCMF_FEAT_DEF(P2P) +- /* +- * Quirks: +- * +diff --git a/package/kernel/mac80211/patches/389-0002-brcmfmac-Build-wiphy-mode-and-interface-combinations.patch b/package/kernel/mac80211/patches/389-0002-brcmfmac-Build-wiphy-mode-and-interface-combinations.patch +deleted file mode 100644 +index 3876ba0..0000000 +--- a/package/kernel/mac80211/patches/389-0002-brcmfmac-Build-wiphy-mode-and-interface-combinations.patch ++++ /dev/null +@@ -1,198 +0,0 @@ +-From: Pontus Fuchs +-Date: Thu, 11 Jun 2015 00:12:18 +0200 +-Subject: [PATCH] brcmfmac: Build wiphy mode and interface combinations +- dynamically +- +-Switch from using semi hard coded interface combinations. This makes +-it easier to announce what the firmware actually supports. This fixes +-the case where brcmfmac announces p2p but the firmware doesn't +-support it. +- +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Hante Meuleman +-Reviewed-by: Arend Van Spriel +-Signed-off-by: Pontus Fuchs +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -52,8 +52,6 @@ +- #define BRCMF_PNO_SCAN_COMPLETE 1 +- #define BRCMF_PNO_SCAN_INCOMPLETE 0 +- +--#define BRCMF_IFACE_MAX_CNT 3 +-- +- #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ +- #define WPA_OUI_TYPE 1 +- #define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */ +-@@ -5639,53 +5637,6 @@ static int brcmf_setup_wiphybands(struct +- return 0; +- } +- +--static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = { +-- { +-- .max = 1, +-- .types = BIT(NL80211_IFTYPE_STATION) | +-- BIT(NL80211_IFTYPE_ADHOC) +-- }, +-- { +-- .max = 4, +-- .types = BIT(NL80211_IFTYPE_AP) +-- }, +-- { +-- .max = 1, +-- .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | +-- BIT(NL80211_IFTYPE_P2P_GO) +-- }, +-- { +-- .max = 1, +-- .types = BIT(NL80211_IFTYPE_P2P_DEVICE) +-- } +--}; +-- +--static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = { +-- { +-- .max = 2, +-- .types = BIT(NL80211_IFTYPE_STATION) | +-- BIT(NL80211_IFTYPE_ADHOC) | +-- BIT(NL80211_IFTYPE_AP) +-- }, +-- { +-- .max = 1, +-- .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | +-- BIT(NL80211_IFTYPE_P2P_GO) +-- }, +-- { +-- .max = 1, +-- .types = BIT(NL80211_IFTYPE_P2P_DEVICE) +-- } +--}; +--static struct ieee80211_iface_combination brcmf_iface_combos[] = { +-- { +-- .max_interfaces = BRCMF_IFACE_MAX_CNT, +-- .num_different_channels = 1, +-- .n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss), +-- .limits = brcmf_iface_limits_sbss, +-- } +--}; +-- +- static const struct ieee80211_txrx_stypes +- brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { +- [NL80211_IFTYPE_STATION] = { +-@@ -5715,6 +5666,67 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = +- } +- }; +- +-+static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) +-+{ +-+ struct ieee80211_iface_combination *combo = NULL; +-+ struct ieee80211_iface_limit *limits = NULL; +-+ int i = 0, max_iface_cnt; +-+ +-+ combo = kzalloc(sizeof(*combo), GFP_KERNEL); +-+ if (!combo) +-+ goto err; +-+ +-+ limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL); +-+ if (!limits) +-+ goto err; +-+ +-+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | +-+ BIT(NL80211_IFTYPE_ADHOC) | +-+ BIT(NL80211_IFTYPE_AP); +-+ +-+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) +-+ combo->num_different_channels = 2; +-+ else +-+ combo->num_different_channels = 1; +-+ +-+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) { +-+ limits[i].max = 1; +-+ limits[i++].types = BIT(NL80211_IFTYPE_STATION); +-+ limits[i].max = 4; +-+ limits[i++].types = BIT(NL80211_IFTYPE_AP); +-+ max_iface_cnt = 5; +-+ } else { +-+ limits[i].max = 2; +-+ limits[i++].types = BIT(NL80211_IFTYPE_STATION) | +-+ BIT(NL80211_IFTYPE_AP); +-+ max_iface_cnt = 2; +-+ } +-+ +-+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) { +-+ wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | +-+ BIT(NL80211_IFTYPE_P2P_GO) | +-+ BIT(NL80211_IFTYPE_P2P_DEVICE); +-+ limits[i].max = 1; +-+ limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | +-+ BIT(NL80211_IFTYPE_P2P_GO); +-+ limits[i].max = 1; +-+ limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); +-+ max_iface_cnt += 2; +-+ } +-+ combo->max_interfaces = max_iface_cnt; +-+ combo->limits = limits; +-+ combo->n_limits = i; +-+ +-+ wiphy->iface_combinations = combo; +-+ wiphy->n_iface_combinations = 1; +-+ return 0; +-+ +-+err: +-+ kfree(limits); +-+ kfree(combo); +-+ return -ENOMEM; +-+} +-+ +- static void brcmf_wiphy_pno_params(struct wiphy *wiphy) +- { +- /* scheduled scan settings */ +-@@ -5745,7 +5757,6 @@ static void brcmf_wiphy_wowl_params(stru +- static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) +- { +- struct ieee80211_supported_band *band; +-- struct ieee80211_iface_combination ifc_combo; +- __le32 bandlist[3]; +- u32 n_bands; +- int err, i; +-@@ -5753,24 +5764,11 @@ static int brcmf_setup_wiphy(struct wiph +- wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; +- wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; +- wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; +-- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | +-- BIT(NL80211_IFTYPE_ADHOC) | +-- BIT(NL80211_IFTYPE_AP) | +-- BIT(NL80211_IFTYPE_P2P_CLIENT) | +-- BIT(NL80211_IFTYPE_P2P_GO) | +-- BIT(NL80211_IFTYPE_P2P_DEVICE); +-- /* need VSDB firmware feature for concurrent channels */ +-- ifc_combo = brcmf_iface_combos[0]; +-- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) +-- ifc_combo.num_different_channels = 2; +-- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) { +-- ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss), +-- ifc_combo.limits = brcmf_iface_limits_mbss; +-- } +-- wiphy->iface_combinations = kmemdup(&ifc_combo, +-- sizeof(ifc_combo), +-- GFP_KERNEL); +-- wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); +-+ +-+ err = brcmf_setup_ifmodes(wiphy, ifp); +-+ if (err) +-+ return err; +-+ +- wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; +- wiphy->cipher_suites = __wl_cipher_suites; +- wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); +-@@ -6035,6 +6033,8 @@ static void brcmf_free_wiphy(struct wiph +- if (!wiphy) +- return; +- +-+ if (wiphy->iface_combinations) +-+ kfree(wiphy->iface_combinations->limits); +- kfree(wiphy->iface_combinations); +- if (wiphy->bands[IEEE80211_BAND_2GHZ]) { +- kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); +diff --git a/package/kernel/mac80211/patches/389-0003-brcmfmac-rework-.get_station-callback.patch b/package/kernel/mac80211/patches/389-0003-brcmfmac-rework-.get_station-callback.patch +deleted file mode 100644 +index 7bd0686..0000000 +--- a/package/kernel/mac80211/patches/389-0003-brcmfmac-rework-.get_station-callback.patch ++++ /dev/null +@@ -1,326 +0,0 @@ +-From: Arend van Spriel +-Date: Thu, 11 Jun 2015 00:12:19 +0200 +-Subject: [PATCH] brcmfmac: rework .get_station() callback +- +-The .get_station() cfg80211 callback is used in several scenarios. In +-managed mode it can obtain information about the access-point and its +-BSS parameters. In managed mode it can also obtain information about +-TDLS peers. In AP mode it can obtain information about connected +-clients. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Daniel (Deognyoun) Kim +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -2395,27 +2395,80 @@ brcmf_cfg80211_reconfigure_wep(struct br +- brcmf_err("set wsec error (%d)\n", err); +- } +- +-+static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si) +-+{ +-+ struct nl80211_sta_flag_update *sfu; +-+ +-+ brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags); +-+ si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS); +-+ sfu = &si->sta_flags; +-+ sfu->mask = BIT(NL80211_STA_FLAG_WME) | +-+ BIT(NL80211_STA_FLAG_AUTHENTICATED) | +-+ BIT(NL80211_STA_FLAG_ASSOCIATED) | +-+ BIT(NL80211_STA_FLAG_AUTHORIZED); +-+ if (fw_sta_flags & BRCMF_STA_WME) +-+ sfu->set |= BIT(NL80211_STA_FLAG_WME); +-+ if (fw_sta_flags & BRCMF_STA_AUTHE) +-+ sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); +-+ if (fw_sta_flags & BRCMF_STA_ASSOC) +-+ sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED); +-+ if (fw_sta_flags & BRCMF_STA_AUTHO) +-+ sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED); +-+} +-+ +-+static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) +-+{ +-+ struct { +-+ __le32 len; +-+ struct brcmf_bss_info_le bss_le; +-+ } *buf; +-+ u16 capability; +-+ int err; +-+ +-+ buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); +-+ if (!buf) +-+ return; +-+ +-+ buf->len = cpu_to_le32(WL_BSS_INFO_MAX); +-+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf, +-+ WL_BSS_INFO_MAX); +-+ if (err) { +-+ brcmf_err("Failed to get bss info (%d)\n", err); +-+ return; +-+ } +-+ si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); +-+ si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); +-+ si->bss_param.dtim_period = buf->bss_le.dtim_period; +-+ capability = le16_to_cpu(buf->bss_le.capability); +-+ if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT) +-+ si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; +-+ if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE) +-+ si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; +-+ if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) +-+ si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; +-+} +-+ +- static s32 +- brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, +- const u8 *mac, struct station_info *sinfo) +- { +- struct brcmf_if *ifp = netdev_priv(ndev); +-- struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; +-- struct brcmf_scb_val_le scb_val; +-- int rssi; +-- s32 rate; +- s32 err = 0; +-- u8 *bssid = profile->bssid; +- struct brcmf_sta_info_le sta_info_le; +-- u32 beacon_period; +-- u32 dtim_period; +-+ u32 sta_flags; +-+ u32 is_tdls_peer; +- +- brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac); +- if (!check_vif_up(ifp->vif)) +- return -EIO; +- +-- if (brcmf_is_apmode(ifp->vif)) { +-- memcpy(&sta_info_le, mac, ETH_ALEN); +-+ memset(&sta_info_le, 0, sizeof(sta_info_le)); +-+ memcpy(&sta_info_le, mac, ETH_ALEN); +-+ err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info", +-+ &sta_info_le, +-+ sizeof(sta_info_le)); +-+ is_tdls_peer = !err; +-+ if (err) { +- err = brcmf_fil_iovar_data_get(ifp, "sta_info", +- &sta_info_le, +- sizeof(sta_info_le)); +-@@ -2423,73 +2476,48 @@ brcmf_cfg80211_get_station(struct wiphy +- brcmf_err("GET STA INFO failed, %d\n", err); +- goto done; +- } +-- sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME); +-- sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; +-- if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) { +-- sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME); +-- sinfo->connected_time = le32_to_cpu(sta_info_le.in); +-- } +-- brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n", +-- sinfo->inactive_time, sinfo->connected_time); +-- } else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) { +-- if (memcmp(mac, bssid, ETH_ALEN)) { +-- brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", +-- mac, bssid); +-- err = -ENOENT; +-- goto done; +-- } +-- /* Report the current tx rate */ +-- err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate); +-- if (err) { +-- brcmf_err("Could not get rate (%d)\n", err); +-- goto done; +-- } else { +-+ } +-+ brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver)); +-+ sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME); +-+ sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; +-+ sta_flags = le32_to_cpu(sta_info_le.flags); +-+ brcmf_convert_sta_flags(sta_flags, sinfo); +-+ sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER); +-+ if (is_tdls_peer) +-+ sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); +-+ else +-+ sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); +-+ if (sta_flags & BRCMF_STA_ASSOC) { +-+ sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME); +-+ sinfo->connected_time = le32_to_cpu(sta_info_le.in); +-+ brcmf_fill_bss_param(ifp, sinfo); +-+ } +-+ if (sta_flags & BRCMF_STA_SCBSTATS) { +-+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); +-+ sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures); +-+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); +-+ sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts); +-+ sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts); +-+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); +-+ sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts); +-+ sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts); +-+ if (sinfo->tx_packets) { +- sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); +-- sinfo->txrate.legacy = rate * 5; +-- brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2); +-+ sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate); +-+ sinfo->txrate.legacy /= 100; +- } +-- +-- if (test_bit(BRCMF_VIF_STATUS_CONNECTED, +-- &ifp->vif->sme_state)) { +-- memset(&scb_val, 0, sizeof(scb_val)); +-- err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, +-- &scb_val, sizeof(scb_val)); +-- if (err) { +-- brcmf_err("Could not get rssi (%d)\n", err); +-- goto done; +-- } else { +-- rssi = le32_to_cpu(scb_val.val); +-- sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); +-- sinfo->signal = rssi; +-- brcmf_dbg(CONN, "RSSI %d dBm\n", rssi); +-- } +-- err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD, +-- &beacon_period); +-- if (err) { +-- brcmf_err("Could not get beacon period (%d)\n", +-- err); +-- goto done; +-- } else { +-- sinfo->bss_param.beacon_interval = +-- beacon_period; +-- brcmf_dbg(CONN, "Beacon peroid %d\n", +-- beacon_period); +-- } +-- err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD, +-- &dtim_period); +-- if (err) { +-- brcmf_err("Could not get DTIM period (%d)\n", +-- err); +-- goto done; +-- } else { +-- sinfo->bss_param.dtim_period = dtim_period; +-- brcmf_dbg(CONN, "DTIM peroid %d\n", +-- dtim_period); +-- } +-- sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); +-+ if (sinfo->rx_packets) { +-+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); +-+ sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate); +-+ sinfo->rxrate.legacy /= 100; +-+ } +-+ if (le16_to_cpu(sta_info_le.ver) >= 4) { +-+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES); +-+ sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes); +-+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES); +-+ sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes); +- } +-- } else +-- err = -EPERM; +-+ } +- done: +- brcmf_dbg(TRACE, "Exit\n"); +- return err; +---- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +-@@ -32,7 +32,11 @@ +- #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ +- #define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002 +- +--#define BRCMF_STA_ASSOC 0x10 /* Associated */ +-+#define BRCMF_STA_WME 0x00000002 /* WMM association */ +-+#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */ +-+#define BRCMF_STA_ASSOC 0x00000010 /* Associated */ +-+#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */ +-+#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */ +- +- /* size of brcmf_scan_params not including variable length array */ +- #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 +-@@ -113,6 +117,7 @@ +- #define BRCMF_WOWL_MAXPATTERNSIZE 128 +- +- #define BRCMF_COUNTRY_BUF_SZ 4 +-+#define BRCMF_ANT_MAX 4 +- +- /* join preference types for join_pref iovar */ +- enum brcmf_join_pref_types { +-@@ -456,25 +461,61 @@ struct brcmf_channel_info_le { +- }; +- +- struct brcmf_sta_info_le { +-- __le16 ver; /* version of this struct */ +-- __le16 len; /* length in bytes of this structure */ +-- __le16 cap; /* sta's advertised capabilities */ +-- __le32 flags; /* flags defined below */ +-- __le32 idle; /* time since data pkt rx'd from sta */ +-- u8 ea[ETH_ALEN]; /* Station address */ +-- __le32 count; /* # rates in this set */ +-- u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ +-+ __le16 ver; /* version of this struct */ +-+ __le16 len; /* length in bytes of this structure */ +-+ __le16 cap; /* sta's advertised capabilities */ +-+ __le32 flags; /* flags defined below */ +-+ __le32 idle; /* time since data pkt rx'd from sta */ +-+ u8 ea[ETH_ALEN]; /* Station address */ +-+ __le32 count; /* # rates in this set */ +-+ u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ +- /* w/hi bit set if basic */ +-- __le32 in; /* seconds elapsed since associated */ +-- __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ +-- __le32 tx_pkts; /* # of packets transmitted */ +-- __le32 tx_failures; /* # of packets failed */ +-- __le32 rx_ucast_pkts; /* # of unicast packets received */ +-- __le32 rx_mcast_pkts; /* # of multicast packets received */ +-- __le32 tx_rate; /* Rate of last successful tx frame */ +-- __le32 rx_rate; /* Rate of last successful rx frame */ +-- __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ +-- __le32 rx_decrypt_failures; /* # of packet decrypted failed */ +-+ __le32 in; /* seconds elapsed since associated */ +-+ __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ +-+ __le32 tx_pkts; /* # of packets transmitted */ +-+ __le32 tx_failures; /* # of packets failed */ +-+ __le32 rx_ucast_pkts; /* # of unicast packets received */ +-+ __le32 rx_mcast_pkts; /* # of multicast packets received */ +-+ __le32 tx_rate; /* Rate of last successful tx frame */ +-+ __le32 rx_rate; /* Rate of last successful rx frame */ +-+ __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ +-+ __le32 rx_decrypt_failures; /* # of packet decrypted failed */ +-+ __le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */ +-+ __le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */ +-+ __le32 tx_mcast_pkts; /* # of mcast pkts txed */ +-+ __le64 tx_tot_bytes; /* data bytes txed (ucast + mcast) */ +-+ __le64 rx_tot_bytes; /* data bytes recvd (ucast + mcast) */ +-+ __le64 tx_ucast_bytes; /* data bytes txed (ucast) */ +-+ __le64 tx_mcast_bytes; /* # data bytes txed (mcast) */ +-+ __le64 rx_ucast_bytes; /* data bytes recvd (ucast) */ +-+ __le64 rx_mcast_bytes; /* data bytes recvd (mcast) */ +-+ s8 rssi[BRCMF_ANT_MAX]; /* per antenna rssi */ +-+ s8 nf[BRCMF_ANT_MAX]; /* per antenna noise floor */ +-+ __le16 aid; /* association ID */ +-+ __le16 ht_capabilities; /* advertised ht caps */ +-+ __le16 vht_flags; /* converted vht flags */ +-+ __le32 tx_pkts_retry_cnt; /* # of frames where a retry was +-+ * exhausted. +-+ */ +-+ __le32 tx_pkts_retry_exhausted; /* # of user frames where a retry +-+ * was exhausted +-+ */ +-+ s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last +-+ * received data frame. +-+ */ +-+ /* TX WLAN retry/failure statistics: +-+ * Separated for host requested frames and locally generated frames. +-+ * Include unicast frame only where the retries/failures can be counted. +-+ */ +-+ __le32 tx_pkts_total; /* # user frames sent successfully */ +-+ __le32 tx_pkts_retries; /* # user frames retries */ +-+ __le32 tx_pkts_fw_total; /* # FW generated sent successfully */ +-+ __le32 tx_pkts_fw_retries; /* # retries for FW generated frames */ +-+ __le32 tx_pkts_fw_retry_exhausted; /* # FW generated where a retry +-+ * was exhausted +-+ */ +-+ __le32 rx_pkts_retried; /* # rx with retry bit set */ +-+ __le32 tx_rate_fallback; /* lowest fallback TX rate */ +- }; +- +- struct brcmf_chanspec_list { +diff --git a/package/kernel/mac80211/patches/389-0004-brcmfmac-have-sdio-return-EIO-when-device-communicat.patch b/package/kernel/mac80211/patches/389-0004-brcmfmac-have-sdio-return-EIO-when-device-communicat.patch +deleted file mode 100644 +index 302bc3e..0000000 +--- a/package/kernel/mac80211/patches/389-0004-brcmfmac-have-sdio-return-EIO-when-device-communicat.patch ++++ /dev/null +@@ -1,56 +0,0 @@ +-From: Arend van Spriel +-Date: Thu, 11 Jun 2015 00:12:20 +0200 +-Subject: [PATCH] brcmfmac: have sdio return -EIO when device communication +- is not possible +- +-The bus interface functions txctl and rxctl may be used while the device +-can not be accessed, eg. upon driver .remove() callback. This patch will +-immediately return -EIO when this is the case which speeds up the module +-unload. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +-@@ -988,6 +988,7 @@ static void brcmf_sdiod_freezer_detach(s +- +- static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) +- { +-+ sdiodev->state = BRCMF_SDIOD_DOWN; +- if (sdiodev->bus) { +- brcmf_sdio_remove(sdiodev->bus); +- sdiodev->bus = NULL; +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -2820,6 +2820,8 @@ static int brcmf_sdio_bus_txdata(struct +- struct brcmf_sdio *bus = sdiodev->bus; +- +- brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len); +-+ if (sdiodev->state != BRCMF_SDIOD_DATA) +-+ return -EIO; +- +- /* Add space for the header */ +- skb_push(pkt, bus->tx_hdrlen); +-@@ -2948,6 +2950,8 @@ brcmf_sdio_bus_txctl(struct device *dev, +- int ret; +- +- brcmf_dbg(TRACE, "Enter\n"); +-+ if (sdiodev->state != BRCMF_SDIOD_DATA) +-+ return -EIO; +- +- /* Send from dpc */ +- bus->ctrl_frame_buf = msg; +-@@ -3238,6 +3242,8 @@ brcmf_sdio_bus_rxctl(struct device *dev, +- struct brcmf_sdio *bus = sdiodev->bus; +- +- brcmf_dbg(TRACE, "Enter\n"); +-+ if (sdiodev->state != BRCMF_SDIOD_DATA) +-+ return -EIO; +- +- /* Wait until control frame is available */ +- timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending); +diff --git a/package/kernel/mac80211/patches/389-0005-ath9k-make-DMA-stop-related-messages-debug-only.patch b/package/kernel/mac80211/patches/389-0005-ath9k-make-DMA-stop-related-messages-debug-only.patch +deleted file mode 100644 +index 34af6d2..0000000 +--- a/package/kernel/mac80211/patches/389-0005-ath9k-make-DMA-stop-related-messages-debug-only.patch ++++ /dev/null +@@ -1,74 +0,0 @@ +-From: Felix Fietkau +-Date: Thu, 2 Jul 2015 13:35:05 +0200 +-Subject: [PATCH] ath9k: make DMA stop related messages debug-only +- +-A long time ago, ath9k had issues during reset where the DMA engine +-would stay active and could potentially corrupt memory. +-To debug those issues, the driver would print warnings whenever they +-occur. +- +-Nowadays, these issues are gone and the primary cause of these messages +-is if the MAC is stuck during reset or busy processing a long +-transmission. This is fairly harmless, yet these messages continue to +-worry users. +- +-To reduce the number of bogus bug reports, turn these messages into +-debug messages and count their occurence in the "reset" debugfs file. +- +-Signed-off-by: Felix Fietkau +---- +- +---- a/drivers/net/wireless/ath/ath9k/debug.c +-+++ b/drivers/net/wireless/ath/ath9k/debug.c +-@@ -765,6 +765,8 @@ static int read_file_reset(struct seq_fi +- [RESET_TYPE_BEACON_STUCK] = "Stuck Beacon", +- [RESET_TYPE_MCI] = "MCI Reset", +- [RESET_TYPE_CALIBRATION] = "Calibration error", +-+ [RESET_TX_DMA_ERROR] = "Tx DMA stop error", +-+ [RESET_RX_DMA_ERROR] = "Rx DMA stop error", +- }; +- int i; +- +---- a/drivers/net/wireless/ath/ath9k/debug.h +-+++ b/drivers/net/wireless/ath/ath9k/debug.h +-@@ -50,6 +50,8 @@ enum ath_reset_type { +- RESET_TYPE_BEACON_STUCK, +- RESET_TYPE_MCI, +- RESET_TYPE_CALIBRATION, +-+ RESET_TX_DMA_ERROR, +-+ RESET_RX_DMA_ERROR, +- __RESET_TYPE_MAX +- }; +- +---- a/drivers/net/wireless/ath/ath9k/recv.c +-+++ b/drivers/net/wireless/ath/ath9k/recv.c +-@@ -496,10 +496,9 @@ bool ath_stoprecv(struct ath_softc *sc) +- +- if (!(ah->ah_flags & AH_UNPLUGGED) && +- unlikely(!stopped)) { +-- ath_err(ath9k_hw_common(sc->sc_ah), +-- "Could not stop RX, we could be " +-- "confusing the DMA engine when we start RX up\n"); +-- ATH_DBG_WARN_ON_ONCE(!stopped); +-+ ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, +-+ "Failed to stop Rx DMA\n"); +-+ RESET_STAT_INC(sc, RESET_RX_DMA_ERROR); +- } +- return stopped && !reset; +- } +---- a/drivers/net/wireless/ath/ath9k/xmit.c +-+++ b/drivers/net/wireless/ath/ath9k/xmit.c +-@@ -1896,8 +1896,11 @@ bool ath_drain_all_txq(struct ath_softc +- npend |= BIT(i); +- } +- +-- if (npend) +-- ath_err(common, "Failed to stop TX DMA, queues=0x%03x!\n", npend); +-+ if (npend) { +-+ RESET_STAT_INC(sc, RESET_TX_DMA_ERROR); +-+ ath_dbg(common, RESET, +-+ "Failed to stop TX DMA, queues=0x%03x!\n", npend); +-+ } +- +- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { +- if (!ATH_TXQ_SETUP(sc, i)) +diff --git a/package/kernel/mac80211/patches/389-0006-brcmfmac-free-ifp-for-non-netdev-interface-in-p2p-mo.patch b/package/kernel/mac80211/patches/389-0006-brcmfmac-free-ifp-for-non-netdev-interface-in-p2p-mo.patch +deleted file mode 100644 +index 06f2dce..0000000 +--- a/package/kernel/mac80211/patches/389-0006-brcmfmac-free-ifp-for-non-netdev-interface-in-p2p-mo.patch ++++ /dev/null +@@ -1,44 +0,0 @@ +-From: Arend van Spriel +-Date: Thu, 11 Jun 2015 00:12:21 +0200 +-Subject: [PATCH] brcmfmac: free ifp for non-netdev interface in p2p module +- +-Making it more clear by freeing the ifp in same place where the +-vif object is freed. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -867,8 +867,6 @@ static void brcmf_del_if(struct brcmf_pu +- } +- /* unregister will take care of freeing it */ +- unregister_netdev(ifp->ndev); +-- } else { +-- kfree(ifp); +- } +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-@@ -2238,6 +2238,7 @@ static void brcmf_p2p_delete_p2pdev(stru +- { +- cfg80211_unregister_wdev(&vif->wdev); +- p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; +-+ kfree(vif->ifp); +- brcmf_free_vif(vif); +- } +- +-@@ -2361,6 +2362,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiph +- break; +- +- case NL80211_IFTYPE_P2P_DEVICE: +-+ brcmf_p2p_cancel_remain_on_channel(vif->ifp); +-+ brcmf_p2p_deinit_discovery(p2p); +- brcmf_p2p_delete_p2pdev(p2p, vif); +- return 0; +- default: +diff --git a/package/kernel/mac80211/patches/389-0007-brcmfmac-move-p2p-attach-detach-functions.patch b/package/kernel/mac80211/patches/389-0007-brcmfmac-move-p2p-attach-detach-functions.patch +deleted file mode 100644 +index 0a6e093..0000000 +--- a/package/kernel/mac80211/patches/389-0007-brcmfmac-move-p2p-attach-detach-functions.patch ++++ /dev/null +@@ -1,225 +0,0 @@ +-From: Arend van Spriel +-Date: Thu, 11 Jun 2015 00:12:22 +0200 +-Subject: [PATCH] brcmfmac: move p2p attach/detach functions +- +-Moving two functions in p2p.c as is so next change will be +-easier to review. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-@@ -1908,105 +1908,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probere +- +- +- /** +-- * brcmf_p2p_attach() - attach for P2P. +-- * +-- * @cfg: driver private data for cfg80211 interface. +-- */ +--s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) +--{ +-- struct brcmf_if *pri_ifp; +-- struct brcmf_if *p2p_ifp; +-- struct brcmf_cfg80211_vif *p2p_vif; +-- struct brcmf_p2p_info *p2p; +-- struct brcmf_pub *drvr; +-- s32 bssidx; +-- s32 err = 0; +-- +-- p2p = &cfg->p2p; +-- p2p->cfg = cfg; +-- +-- drvr = cfg->pub; +-- +-- pri_ifp = drvr->iflist[0]; +-- p2p_ifp = drvr->iflist[1]; +-- +-- p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; +-- +-- if (p2p_ifp) { +-- p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE, +-- false); +-- if (IS_ERR(p2p_vif)) { +-- brcmf_err("could not create discovery vif\n"); +-- err = -ENOMEM; +-- goto exit; +-- } +-- +-- p2p_vif->ifp = p2p_ifp; +-- p2p_ifp->vif = p2p_vif; +-- p2p_vif->wdev.netdev = p2p_ifp->ndev; +-- p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev; +-- SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy)); +-- +-- p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; +-- +-- brcmf_p2p_generate_bss_mac(p2p, NULL); +-- memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); +-- brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); +-- +-- /* Initialize P2P Discovery in the firmware */ +-- err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); +-- if (err < 0) { +-- brcmf_err("set p2p_disc error\n"); +-- brcmf_free_vif(p2p_vif); +-- goto exit; +-- } +-- /* obtain bsscfg index for P2P discovery */ +-- err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); +-- if (err < 0) { +-- brcmf_err("retrieving discover bsscfg index failed\n"); +-- brcmf_free_vif(p2p_vif); +-- goto exit; +-- } +-- /* Verify that firmware uses same bssidx as driver !! */ +-- if (p2p_ifp->bssidx != bssidx) { +-- brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", +-- bssidx, p2p_ifp->bssidx); +-- brcmf_free_vif(p2p_vif); +-- goto exit; +-- } +-- +-- init_completion(&p2p->send_af_done); +-- INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); +-- init_completion(&p2p->afx_hdl.act_frm_scan); +-- init_completion(&p2p->wait_next_af); +-- } +--exit: +-- return err; +--} +-- +-- +--/** +-- * brcmf_p2p_detach() - detach P2P. +-- * +-- * @p2p: P2P specific data. +-- */ +--void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) +--{ +-- struct brcmf_cfg80211_vif *vif; +-- +-- vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; +-- if (vif != NULL) { +-- brcmf_p2p_cancel_remain_on_channel(vif->ifp); +-- brcmf_p2p_deinit_discovery(p2p); +-- /* remove discovery interface */ +-- brcmf_free_vif(vif); +-- p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; +-- } +-- /* just set it all to zero */ +-- memset(p2p, 0, sizeof(*p2p)); +--} +-- +--/** +- * brcmf_p2p_get_current_chanspec() - Get current operation channel. +- * +- * @p2p: P2P specific data. +-@@ -2425,3 +2326,102 @@ void brcmf_p2p_stop_device(struct wiphy +- clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); +- mutex_unlock(&cfg->usr_sync); +- } +-+ +-+/** +-+ * brcmf_p2p_attach() - attach for P2P. +-+ * +-+ * @cfg: driver private data for cfg80211 interface. +-+ */ +-+s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) +-+{ +-+ struct brcmf_if *pri_ifp; +-+ struct brcmf_if *p2p_ifp; +-+ struct brcmf_cfg80211_vif *p2p_vif; +-+ struct brcmf_p2p_info *p2p; +-+ struct brcmf_pub *drvr; +-+ s32 bssidx; +-+ s32 err = 0; +-+ +-+ p2p = &cfg->p2p; +-+ p2p->cfg = cfg; +-+ +-+ drvr = cfg->pub; +-+ +-+ pri_ifp = drvr->iflist[0]; +-+ p2p_ifp = drvr->iflist[1]; +-+ +-+ p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; +-+ +-+ if (p2p_ifp) { +-+ p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE, +-+ false); +-+ if (IS_ERR(p2p_vif)) { +-+ brcmf_err("could not create discovery vif\n"); +-+ err = -ENOMEM; +-+ goto exit; +-+ } +-+ +-+ p2p_vif->ifp = p2p_ifp; +-+ p2p_ifp->vif = p2p_vif; +-+ p2p_vif->wdev.netdev = p2p_ifp->ndev; +-+ p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev; +-+ SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy)); +-+ +-+ p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; +-+ +-+ brcmf_p2p_generate_bss_mac(p2p, NULL); +-+ memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); +-+ brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); +-+ +-+ /* Initialize P2P Discovery in the firmware */ +-+ err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); +-+ if (err < 0) { +-+ brcmf_err("set p2p_disc error\n"); +-+ brcmf_free_vif(p2p_vif); +-+ goto exit; +-+ } +-+ /* obtain bsscfg index for P2P discovery */ +-+ err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); +-+ if (err < 0) { +-+ brcmf_err("retrieving discover bsscfg index failed\n"); +-+ brcmf_free_vif(p2p_vif); +-+ goto exit; +-+ } +-+ /* Verify that firmware uses same bssidx as driver !! */ +-+ if (p2p_ifp->bssidx != bssidx) { +-+ brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", +-+ bssidx, p2p_ifp->bssidx); +-+ brcmf_free_vif(p2p_vif); +-+ goto exit; +-+ } +-+ +-+ init_completion(&p2p->send_af_done); +-+ INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); +-+ init_completion(&p2p->afx_hdl.act_frm_scan); +-+ init_completion(&p2p->wait_next_af); +-+ } +-+exit: +-+ return err; +-+} +-+ +-+/** +-+ * brcmf_p2p_detach() - detach P2P. +-+ * +-+ * @p2p: P2P specific data. +-+ */ +-+void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) +-+{ +-+ struct brcmf_cfg80211_vif *vif; +-+ +-+ vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; +-+ if (vif != NULL) { +-+ brcmf_p2p_cancel_remain_on_channel(vif->ifp); +-+ brcmf_p2p_deinit_discovery(p2p); +-+ /* remove discovery interface */ +-+ brcmf_free_vif(vif); +-+ p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; +-+ } +-+ /* just set it all to zero */ +-+ memset(p2p, 0, sizeof(*p2p)); +-+} +-+ +diff --git a/package/kernel/mac80211/patches/389-0008-brcmfmac-assure-p2pdev-is-unregistered-upon-driver-u.patch b/package/kernel/mac80211/patches/389-0008-brcmfmac-assure-p2pdev-is-unregistered-upon-driver-u.patch +deleted file mode 100644 +index 72e8eed..0000000 +--- a/package/kernel/mac80211/patches/389-0008-brcmfmac-assure-p2pdev-is-unregistered-upon-driver-u.patch ++++ /dev/null +@@ -1,63 +0,0 @@ +-From: Arend van Spriel +-Date: Thu, 11 Jun 2015 00:12:23 +0200 +-Subject: [PATCH] brcmfmac: assure p2pdev is unregistered upon driver +- unload +- +-When unloading the driver with a p2pdev interface it resulted in +-a warning upon calling wiphy_unregister() and subsequently a crash +-in the driver. This patch assures the p2pdev is unregistered calling +-unregister_wdev() before doing the wiphy_unregister(). +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -6206,10 +6206,8 @@ void brcmf_cfg80211_detach(struct brcmf_ +- if (!cfg) +- return; +- +-- WARN_ON(!list_empty(&cfg->vif_list)); +-- wiphy_unregister(cfg->wiphy); +- brcmf_btcoex_detach(cfg); +-- brcmf_p2p_detach(&cfg->p2p); +-+ wiphy_unregister(cfg->wiphy); +- wl_deinit_priv(cfg); +- brcmf_free_wiphy(cfg->wiphy); +- } +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -1098,6 +1098,7 @@ void brcmf_detach(struct device *dev) +- +- /* stop firmware event handling */ +- brcmf_fweh_detach(drvr); +-+ brcmf_p2p_detach(&drvr->config->p2p); +- +- brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-@@ -16,6 +16,7 @@ +- #include +- #include +- #include +-+#include +- #include +- +- #include +-@@ -2418,8 +2419,9 @@ void brcmf_p2p_detach(struct brcmf_p2p_i +- brcmf_p2p_cancel_remain_on_channel(vif->ifp); +- brcmf_p2p_deinit_discovery(p2p); +- /* remove discovery interface */ +-- brcmf_free_vif(vif); +-- p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; +-+ rtnl_lock(); +-+ brcmf_p2p_delete_p2pdev(p2p, vif); +-+ rtnl_unlock(); +- } +- /* just set it all to zero */ +- memset(p2p, 0, sizeof(*p2p)); +diff --git a/package/kernel/mac80211/patches/390-0001-brcmfmac-fix-double-free-of-p2pdev-interface.patch b/package/kernel/mac80211/patches/390-0001-brcmfmac-fix-double-free-of-p2pdev-interface.patch +deleted file mode 100644 +index 179c77e..0000000 +--- a/package/kernel/mac80211/patches/390-0001-brcmfmac-fix-double-free-of-p2pdev-interface.patch ++++ /dev/null +@@ -1,27 +0,0 @@ +-From: Arend van Spriel +-Date: Mon, 15 Jun 2015 22:48:38 +0200 +-Subject: [PATCH] brcmfmac: fix double free of p2pdev interface +- +-When freeing the driver ifp pointer it should also be removed from +-the driver interface list, which is what brcmf_remove_interface() +-does. Otherwise, the ifp pointer will be freed twice triggering +-a kernel oops. +- +-Fixes: f37d69a4babc ("brcmfmac: free ifp for non-netdev interface in p2p module") +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-@@ -2140,7 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(stru +- { +- cfg80211_unregister_wdev(&vif->wdev); +- p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; +-- kfree(vif->ifp); +-+ brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx); +- brcmf_free_vif(vif); +- } +- +diff --git a/package/kernel/mac80211/patches/390-0002-brcmfmac-make-brcmf_p2p_detach-call-conditional.patch b/package/kernel/mac80211/patches/390-0002-brcmfmac-make-brcmf_p2p_detach-call-conditional.patch +deleted file mode 100644 +index e4f88b5..0000000 +--- a/package/kernel/mac80211/patches/390-0002-brcmfmac-make-brcmf_p2p_detach-call-conditional.patch ++++ /dev/null +@@ -1,29 +0,0 @@ +-From: Arend van Spriel +-Date: Mon, 15 Jun 2015 22:48:39 +0200 +-Subject: [PATCH] brcmfmac: make brcmf_p2p_detach() call conditional +- +-During verification of error handling in brcmf_cfg80211_attach() a +-null pointer dereference occurred upon calling brcmf_p2p_detach() +-from brcmf_detach(). This should only be called when the +-brcmf_cfg80211_attach() has succeeded. +- +-Fixes: f7a40873d2fa ("brcmfmac: assure p2pdev is unregistered upon driver unload") +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -1098,7 +1098,8 @@ void brcmf_detach(struct device *dev) +- +- /* stop firmware event handling */ +- brcmf_fweh_detach(drvr); +-- brcmf_p2p_detach(&drvr->config->p2p); +-+ if (drvr->config) +-+ brcmf_p2p_detach(&drvr->config->p2p); +- +- brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); +- +diff --git a/package/kernel/mac80211/patches/391-brcmfmac-set-wiphy-s-addresses-to-provide-valid-MACs.patch b/package/kernel/mac80211/patches/391-brcmfmac-set-wiphy-s-addresses-to-provide-valid-MACs.patch +deleted file mode 100644 +index 0a81237..0000000 +--- a/package/kernel/mac80211/patches/391-brcmfmac-set-wiphy-s-addresses-to-provide-valid-MACs.patch ++++ /dev/null +@@ -1,67 +0,0 @@ +-From: Rafa? Mi?ecki +-Date: Thu, 9 Jul 2015 17:07:08 +0200 +-Subject: [PATCH] brcmfmac: set wiphy's addresses to provide valid MACs +- +-Broadcom's firmware requires every BSS to use MAC address with unique +-last few bits. The amount of bits may depend on a particular firmware, +-it was verified to be 2 for BCM43602 one. +-If this condition won't be fulfilled firmware will reject such MAC: +-brcmfmac: _brcmf_set_mac_address: Setting cur_etheraddr failed, -52 +- +-We don't want to simply set addr_mask as it would also disallow using +-locally administrated bit. Instead let's build a list of addresses +-manually enabling 0x2 bit for extra interfaces. +- +-Signed-off-by: Rafa? Mi?ecki +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -5784,6 +5784,7 @@ static void brcmf_wiphy_wowl_params(stru +- +- static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) +- { +-+ struct brcmf_pub *drvr = ifp->drvr; +- struct ieee80211_supported_band *band; +- __le32 bandlist[3]; +- u32 n_bands; +-@@ -5797,6 +5798,19 @@ static int brcmf_setup_wiphy(struct wiph +- if (err) +- return err; +- +-+ for (i = 0; i < wiphy->iface_combinations->max_interfaces && +-+ i < ARRAY_SIZE(drvr->addresses); i++) { +-+ u8 *addr = drvr->addresses[i].addr; +-+ +-+ memcpy(addr, drvr->mac, ETH_ALEN); +-+ if (i) { +-+ addr[0] |= BIT(1); +-+ addr[ETH_ALEN - 1] ^= i; +-+ } +-+ } +-+ wiphy->addresses = drvr->addresses; +-+ wiphy->n_addresses = i; +-+ +- wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; +- wiphy->cipher_suites = __wl_cipher_suites; +- wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h +-@@ -21,6 +21,7 @@ +- #ifndef BRCMFMAC_CORE_H +- #define BRCMFMAC_CORE_H +- +-+#include +- #include "fweh.h" +- +- #define TOE_TX_CSUM_OL 0x00000001 +-@@ -118,6 +119,8 @@ struct brcmf_pub { +- /* Multicast data packets sent to dongle */ +- unsigned long tx_multicast; +- +-+ struct mac_address addresses[BRCMF_MAX_IFS]; +-+ +- struct brcmf_if *iflist[BRCMF_MAX_IFS]; +- +- struct mutex proto_block; +diff --git a/package/kernel/mac80211/patches/392-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch b/package/kernel/mac80211/patches/392-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch +deleted file mode 100644 +index e44f121..0000000 +--- a/package/kernel/mac80211/patches/392-brcmfmac-dhd_sdio.c-use-existing-atomic_or-primitive.patch ++++ /dev/null +@@ -1,45 +0,0 @@ +-From: Vineet Gupta +-Date: Thu, 9 Jul 2015 13:43:18 +0530 +-Subject: [PATCH] brcmfmac: dhd_sdio.c: use existing atomic_or primitive +- +-There's already a generic implementation so use that instead. +- +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -2564,15 +2564,6 @@ static inline void brcmf_sdio_clrintr(st +- } +- } +- +--static void atomic_orr(int val, atomic_t *v) +--{ +-- int old_val; +-- +-- old_val = atomic_read(v); +-- while (atomic_cmpxchg(v, old_val, val | old_val) != old_val) +-- old_val = atomic_read(v); +--} +-- +- static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) +- { +- struct brcmf_core *buscore; +-@@ -2595,7 +2586,7 @@ static int brcmf_sdio_intr_rstatus(struc +- if (val) { +- brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret); +- bus->sdcnt.f1regdata++; +-- atomic_orr(val, &bus->intstatus); +-+ atomic_or(val, &bus->intstatus); +- } +- +- return ret; +-@@ -2712,7 +2703,7 @@ static void brcmf_sdio_dpc(struct brcmf_ +- +- /* Keep still-pending events for next scheduling */ +- if (intstatus) +-- atomic_orr(intstatus, &bus->intstatus); +-+ atomic_or(intstatus, &bus->intstatus); +- +- brcmf_sdio_clrintr(bus); +- +diff --git a/package/kernel/mac80211/patches/393-0001-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch b/package/kernel/mac80211/patches/393-0001-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch +deleted file mode 100644 +index 76ca143..0000000 +--- a/package/kernel/mac80211/patches/393-0001-brcmfmac-check-all-combinations-when-setting-wiphy-s.patch ++++ /dev/null +@@ -1,46 +0,0 @@ +-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +-Date: Thu, 20 Aug 2015 00:16:42 +0200 +-Subject: [PATCH] brcmfmac: check all combinations when setting wiphy's +- addresses +-MIME-Version: 1.0 +-Content-Type: text/plain; charset=UTF-8 +-Content-Transfer-Encoding: 8bit +- +-Broadcom is working on better reflection of interface combinations. With +-upcoming patches we may have 1st combination supporting less interfaces +-than others. +-To don't run out of addresses check all combinations to find the one +-with the greatest max_interfaces value. +- +-Signed-off-by: Rafał Miłecki +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -5785,7 +5785,9 @@ static void brcmf_wiphy_wowl_params(stru +- static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) +- { +- struct brcmf_pub *drvr = ifp->drvr; +-+ const struct ieee80211_iface_combination *combo; +- struct ieee80211_supported_band *band; +-+ u16 max_interfaces = 0; +- __le32 bandlist[3]; +- u32 n_bands; +- int err, i; +-@@ -5798,8 +5800,13 @@ static int brcmf_setup_wiphy(struct wiph +- if (err) +- return err; +- +-- for (i = 0; i < wiphy->iface_combinations->max_interfaces && +-- i < ARRAY_SIZE(drvr->addresses); i++) { +-+ for (i = 0, combo = wiphy->iface_combinations; +-+ i < wiphy->n_iface_combinations; i++, combo++) { +-+ max_interfaces = max(max_interfaces, combo->max_interfaces); +-+ } +-+ +-+ for (i = 0; i < max_interfaces && i < ARRAY_SIZE(drvr->addresses); +-+ i++) { +- u8 *addr = drvr->addresses[i].addr; +- +- memcpy(addr, drvr->mac, ETH_ALEN); +diff --git a/package/kernel/mac80211/patches/393-0002-brcmfmac-correct-interface-combination-info.patch b/package/kernel/mac80211/patches/393-0002-brcmfmac-correct-interface-combination-info.patch +deleted file mode 100644 +index c4a0720..0000000 +--- a/package/kernel/mac80211/patches/393-0002-brcmfmac-correct-interface-combination-info.patch ++++ /dev/null +@@ -1,204 +0,0 @@ +-From: Arend van Spriel +-Date: Thu, 20 Aug 2015 22:06:03 +0200 +-Subject: [PATCH] brcmfmac: correct interface combination info +- +-The interface combination provided by brcmfmac did not truly reflect +-the combinations supported by driver and/or firmware. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Pontus Fuchs +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -5694,63 +5694,132 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = +- } +- }; +- +-+/** +-+ * brcmf_setup_ifmodes() - determine interface modes and combinations. +-+ * +-+ * @wiphy: wiphy object. +-+ * @ifp: interface object needed for feat module api. +-+ * +-+ * The interface modes and combinations are determined dynamically here +-+ * based on firmware functionality. +-+ * +-+ * no p2p and no mbss: +-+ * +-+ * #STA <= 1, #AP <= 1, channels = 1, 2 total +-+ * +-+ * no p2p and mbss: +-+ * +-+ * #STA <= 1, #AP <= 1, channels = 1, 2 total +-+ * #AP <= 4, matching BI, channels = 1, 4 total +-+ * +-+ * p2p, no mchan, and mbss: +-+ * +-+ * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 1, 3 total +-+ * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total +-+ * #AP <= 4, matching BI, channels = 1, 4 total +-+ * +-+ * p2p, mchan, and mbss: +-+ * +-+ * #STA <= 1, #P2P-DEV <= 1, #{P2P-CL, P2P-GO} <= 1, channels = 2, 3 total +-+ * #STA <= 1, #P2P-DEV <= 1, #AP <= 1, #P2P-CL <= 1, channels = 1, 4 total +-+ * #AP <= 4, matching BI, channels = 1, 4 total +-+ */ +- static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) +- { +- struct ieee80211_iface_combination *combo = NULL; +-- struct ieee80211_iface_limit *limits = NULL; +-- int i = 0, max_iface_cnt; +-+ struct ieee80211_iface_limit *c0_limits = NULL; +-+ struct ieee80211_iface_limit *p2p_limits = NULL; +-+ struct ieee80211_iface_limit *mbss_limits = NULL; +-+ bool mbss, p2p; +-+ int i, c, n_combos; +- +-- combo = kzalloc(sizeof(*combo), GFP_KERNEL); +-+ mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); +-+ p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); +-+ +-+ n_combos = 1 + !!p2p + !!mbss; +-+ combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL); +- if (!combo) +- goto err; +- +-- limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL); +-- if (!limits) +-+ 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); +- +-- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) +-- combo->num_different_channels = 2; +-- else +-- combo->num_different_channels = 1; +-- +-- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) { +-- limits[i].max = 1; +-- limits[i++].types = BIT(NL80211_IFTYPE_STATION); +-- limits[i].max = 4; +-- limits[i++].types = BIT(NL80211_IFTYPE_AP); +-- max_iface_cnt = 5; +-- } else { +-- limits[i].max = 2; +-- limits[i++].types = BIT(NL80211_IFTYPE_STATION) | +-- BIT(NL80211_IFTYPE_AP); +-- max_iface_cnt = 2; +-- } +-- +-- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) { +-+ c = 0; +-+ i = 0; +-+ combo[c].num_different_channels = 1; +-+ c0_limits[i].max = 1; +-+ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); +-+ if (p2p) { +-+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) +-+ combo[c].num_different_channels = 2; +- wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | +- BIT(NL80211_IFTYPE_P2P_GO) | +- BIT(NL80211_IFTYPE_P2P_DEVICE); +-- limits[i].max = 1; +-- limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | +-- BIT(NL80211_IFTYPE_P2P_GO); +-- limits[i].max = 1; +-- limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); +-- max_iface_cnt += 2; +-- } +-- combo->max_interfaces = max_iface_cnt; +-- combo->limits = limits; +-- combo->n_limits = i; +-+ c0_limits[i].max = 1; +-+ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); +-+ c0_limits[i].max = 1; +-+ c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | +-+ BIT(NL80211_IFTYPE_P2P_GO); +-+ } else { +-+ c0_limits[i].max = 1; +-+ c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); +-+ } +-+ combo[c].max_interfaces = i; +-+ combo[c].n_limits = i; +-+ combo[c].limits = c0_limits; +-+ +-+ if (p2p) { +-+ c++; +-+ i = 0; +-+ combo[c].num_different_channels = 1; +-+ p2p_limits[i].max = 1; +-+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_STATION); +-+ p2p_limits[i].max = 1; +-+ p2p_limits[i++].types = BIT(NL80211_IFTYPE_AP); +-+ p2p_limits[i].max = 1; +-+ 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].max_interfaces = i; +-+ combo[c].n_limits = i; +-+ combo[c].limits = p2p_limits; +-+ } +- +-+ if (mbss) { +-+ c++; +-+ 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].limits = mbss_limits; +-+ } +-+ wiphy->n_iface_combinations = n_combos; +- wiphy->iface_combinations = combo; +-- wiphy->n_iface_combinations = 1; +- return 0; +- +- err: +-- kfree(limits); +-+ kfree(c0_limits); +-+ kfree(p2p_limits); +-+ kfree(mbss_limits); +- kfree(combo); +- return -ENOMEM; +- } +-@@ -6079,11 +6148,15 @@ static void brcmf_cfg80211_reg_notifier( +- +- static void brcmf_free_wiphy(struct wiphy *wiphy) +- { +-+ int i; +-+ +- if (!wiphy) +- return; +- +-- if (wiphy->iface_combinations) +-- kfree(wiphy->iface_combinations->limits); +-+ if (wiphy->iface_combinations) { +-+ for (i = 0; i < wiphy->n_iface_combinations; i++) +-+ kfree(wiphy->iface_combinations[i].limits); +-+ } +- kfree(wiphy->iface_combinations); +- if (wiphy->bands[IEEE80211_BAND_2GHZ]) { +- kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); +diff --git a/package/kernel/mac80211/patches/393-0003-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch b/package/kernel/mac80211/patches/393-0003-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch +deleted file mode 100644 +index 9768ef2..0000000 +--- a/package/kernel/mac80211/patches/393-0003-brcmfmac-add-debugfs-entry-for-msgbuf-statistics.patch ++++ /dev/null +@@ -1,87 +0,0 @@ +-From: Franky Lin +-Date: Thu, 20 Aug 2015 22:06:04 +0200 +-Subject: [PATCH] brcmfmac: add debugfs entry for msgbuf statistics +- +-Expose ring buffer read/write pointers and other useful statistics +-through debugfs. +- +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Hante Meuleman +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Franky Lin +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-@@ -1360,6 +1360,60 @@ void brcmf_msgbuf_delete_flowring(struct +- } +- } +- +-+#ifdef DEBUG +-+static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data) +-+{ +-+ struct brcmf_bus *bus_if = dev_get_drvdata(seq->private); +-+ struct brcmf_pub *drvr = bus_if->drvr; +-+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd; +-+ struct brcmf_commonring *commonring; +-+ u16 i; +-+ struct brcmf_flowring_ring *ring; +-+ struct brcmf_flowring_hash *hash; +-+ +-+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT]; +-+ seq_printf(seq, "h2d_ctl_submit: rp %4u, wp %4u, depth %4u\n", +-+ commonring->r_ptr, commonring->w_ptr, commonring->depth); +-+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_RXPOST_SUBMIT]; +-+ seq_printf(seq, "h2d_rx_submit: rp %4u, wp %4u, depth %4u\n", +-+ commonring->r_ptr, commonring->w_ptr, commonring->depth); +-+ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_CONTROL_COMPLETE]; +-+ seq_printf(seq, "d2h_ctl_cmplt: rp %4u, wp %4u, depth %4u\n", +-+ commonring->r_ptr, commonring->w_ptr, commonring->depth); +-+ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_TX_COMPLETE]; +-+ seq_printf(seq, "d2h_tx_cmplt: rp %4u, wp %4u, depth %4u\n", +-+ commonring->r_ptr, commonring->w_ptr, commonring->depth); +-+ commonring = msgbuf->commonrings[BRCMF_D2H_MSGRING_RX_COMPLETE]; +-+ seq_printf(seq, "d2h_rx_cmplt: rp %4u, wp %4u, depth %4u\n", +-+ commonring->r_ptr, commonring->w_ptr, commonring->depth); +-+ +-+ seq_printf(seq, "\nh2d_flowrings: depth %u\n", +-+ BRCMF_H2D_TXFLOWRING_MAX_ITEM); +-+ seq_puts(seq, "Active flowrings:\n"); +-+ hash = msgbuf->flow->hash; +-+ for (i = 0; i < msgbuf->flow->nrofrings; i++) { +-+ if (!msgbuf->flow->rings[i]) +-+ continue; +-+ ring = msgbuf->flow->rings[i]; +-+ if (ring->status != RING_OPEN) +-+ continue; +-+ commonring = msgbuf->flowrings[i]; +-+ hash = &msgbuf->flow->hash[ring->hash_id]; +-+ seq_printf(seq, "id %3u: rp %4u, wp %4u, qlen %4u, blocked %u\n" +-+ " ifidx %u, fifo %u, da %pM\n", +-+ i, commonring->r_ptr, commonring->w_ptr, +-+ skb_queue_len(&ring->skblist), ring->blocked, +-+ hash->ifidx, hash->fifo, hash->mac); +-+ } +-+ +-+ return 0; +-+} +-+#else +-+static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data) +-+{ +-+ return 0; +-+} +-+#endif +- +- int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) +- { +-@@ -1460,6 +1514,8 @@ int brcmf_proto_msgbuf_attach(struct brc +- spin_lock_init(&msgbuf->flowring_work_lock); +- INIT_LIST_HEAD(&msgbuf->work_queue); +- +-+ brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read); +-+ +- return 0; +- +- fail: +diff --git a/package/kernel/mac80211/patches/393-0004-brcmfmac-make-use-of-cfg80211_check_combinations.patch b/package/kernel/mac80211/patches/393-0004-brcmfmac-make-use-of-cfg80211_check_combinations.patch +deleted file mode 100644 +index 2b84cf9..0000000 +--- a/package/kernel/mac80211/patches/393-0004-brcmfmac-make-use-of-cfg80211_check_combinations.patch ++++ /dev/null +@@ -1,83 +0,0 @@ +-From: Arend van Spriel +-Date: Thu, 20 Aug 2015 22:06:05 +0200 +-Subject: [PATCH] brcmfmac: make use of cfg80211_check_combinations() +- +-Use cfg80211_check_combinations() so we can bail out early when an +-interface add or change results in an invalid combination. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -469,6 +469,36 @@ brcmf_find_wpsie(const u8 *parse, u32 le +- return NULL; +- } +- +-+static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg, +-+ struct brcmf_cfg80211_vif *vif, +-+ enum nl80211_iftype new_type) +-+{ +-+ int iftype_num[NUM_NL80211_IFTYPES]; +-+ struct brcmf_cfg80211_vif *pos; +-+ +-+ memset(&iftype_num[0], 0, sizeof(iftype_num)); +-+ list_for_each_entry(pos, &cfg->vif_list, list) +-+ if (pos == vif) +-+ iftype_num[new_type]++; +-+ else +-+ iftype_num[pos->wdev.iftype]++; +-+ +-+ return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); +-+} +-+ +-+static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg, +-+ enum nl80211_iftype new_type) +-+{ +-+ int iftype_num[NUM_NL80211_IFTYPES]; +-+ struct brcmf_cfg80211_vif *pos; +-+ +-+ memset(&iftype_num[0], 0, sizeof(iftype_num)); +-+ list_for_each_entry(pos, &cfg->vif_list, list) +-+ iftype_num[pos->wdev.iftype]++; +-+ +-+ iftype_num[new_type]++; +-+ return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); +-+} +- +- static void convert_key_from_CPU(struct brcmf_wsec_key *key, +- struct brcmf_wsec_key_le *key_le) +-@@ -662,8 +692,14 @@ static struct wireless_dev *brcmf_cfg802 +- struct vif_params *params) +- { +- struct wireless_dev *wdev; +-+ int err; +- +- brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); +-+ err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type); +-+ if (err) { +-+ brcmf_err("iface validation failed: err=%d\n", err); +-+ return ERR_PTR(err); +-+ } +- switch (type) { +- case NL80211_IFTYPE_ADHOC: +- case NL80211_IFTYPE_STATION: +-@@ -822,8 +858,12 @@ brcmf_cfg80211_change_iface(struct wiphy +- s32 ap = 0; +- s32 err = 0; +- +-- brcmf_dbg(TRACE, "Enter, ndev=%p, type=%d\n", ndev, type); +-- +-+ brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type); +-+ err = brcmf_vif_change_validate(wiphy_to_cfg(wiphy), vif, type); +-+ if (err) { +-+ brcmf_err("iface validation failed: err=%d\n", err); +-+ return err; +-+ } +- switch (type) { +- case NL80211_IFTYPE_MONITOR: +- case NL80211_IFTYPE_WDS: +diff --git a/package/kernel/mac80211/patches/393-0005-brcmfmac-block-the-correct-flowring-when-backup-queu.patch b/package/kernel/mac80211/patches/393-0005-brcmfmac-block-the-correct-flowring-when-backup-queu.patch +deleted file mode 100644 +index 2d5f7b9..0000000 +--- a/package/kernel/mac80211/patches/393-0005-brcmfmac-block-the-correct-flowring-when-backup-queu.patch ++++ /dev/null +@@ -1,48 +0,0 @@ +-From: Franky Lin +-Date: Thu, 20 Aug 2015 22:06:06 +0200 +-Subject: [PATCH] brcmfmac: block the correct flowring when backup queue +- overflow +- +-brcmf_flowring_block blocks the last active flowring under the same +-interface instead of the one provided by caller. This could lead to a +-dead lock of netif stop if there are more than one flowring under the +-interface and the traffic is high enough so brcmf_flowring_enqueue can +-not unblock the ring right away. +- +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Hante Meuleman +-Signed-off-by: Franky Lin +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +-@@ -194,11 +194,15 @@ static void brcmf_flowring_block(struct +- spin_lock_irqsave(&flow->block_lock, flags); +- +- ring = flow->rings[flowid]; +-+ if (ring->blocked == blocked) { +-+ spin_unlock_irqrestore(&flow->block_lock, flags); +-+ return; +-+ } +- ifidx = brcmf_flowring_ifidx_get(flow, flowid); +- +- currently_blocked = false; +- for (i = 0; i < flow->nrofrings; i++) { +-- if (flow->rings[i]) { +-+ if ((flow->rings[i]) && (i != flowid)) { +- ring = flow->rings[i]; +- if ((ring->status == RING_OPEN) && +- (brcmf_flowring_ifidx_get(flow, i) == ifidx)) { +-@@ -209,8 +213,8 @@ static void brcmf_flowring_block(struct +- } +- } +- } +-- ring->blocked = blocked; +-- if (currently_blocked == blocked) { +-+ flow->rings[flowid]->blocked = blocked; +-+ if (currently_blocked) { +- spin_unlock_irqrestore(&flow->block_lock, flags); +- return; +- } +diff --git a/package/kernel/mac80211/patches/393-0006-brcmfmac-bump-highest-event-number-for-4339-firmware.patch b/package/kernel/mac80211/patches/393-0006-brcmfmac-bump-highest-event-number-for-4339-firmware.patch +deleted file mode 100644 +index 7378401..0000000 +--- a/package/kernel/mac80211/patches/393-0006-brcmfmac-bump-highest-event-number-for-4339-firmware.patch ++++ /dev/null +@@ -1,52 +0,0 @@ +-From: Arend van Spriel +-Date: Thu, 20 Aug 2015 22:06:07 +0200 +-Subject: [PATCH] brcmfmac: bump highest event number for 4339 firmware +- +-The event mask length is determined by the highest event number +-that is specified in the driver. When this length is shorter than +-firmware expects setting event mask will fail and device becomes +-pretty useless. This issue was reported with bcm4339 firmware that +-was recently released. +- +-Reported-by: Pontus Fuchs +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Pontus Fuchs +-Signed-off-by: Arend van Spriel +-Signed-off-by: Kalle Valo +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +-@@ -85,7 +85,6 @@ struct brcmf_event; +- BRCMF_ENUM_DEF(IF, 54) \ +- BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \ +- BRCMF_ENUM_DEF(RSSI, 56) \ +-- BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \ +- BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \ +- BRCMF_ENUM_DEF(ACTION_FRAME, 59) \ +- BRCMF_ENUM_DEF(ACTION_FRAME_COMPLETE, 60) \ +-@@ -103,8 +102,7 @@ struct brcmf_event; +- BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \ +- BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) \ +- BRCMF_ENUM_DEF(TDLS_PEER_EVENT, 92) \ +-- BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) \ +-- BRCMF_ENUM_DEF(PSTA_PRIMARY_INTF_IND, 128) +-+ BRCMF_ENUM_DEF(BCMC_CREDIT_SUPPORT, 127) +- +- #define BRCMF_ENUM_DEF(id, val) \ +- BRCMF_E_##id = (val), +-@@ -112,7 +110,11 @@ struct brcmf_event; +- /* firmware event codes sent by the dongle */ +- enum brcmf_fweh_event_code { +- BRCMF_FWEH_EVENT_ENUM_DEFLIST +-- BRCMF_E_LAST +-+ /* this determines event mask length which must match +-+ * minimum length check in device firmware so it is +-+ * hard-coded here. +-+ */ +-+ BRCMF_E_LAST = 139 +- }; +- #undef BRCMF_ENUM_DEF +- +diff --git a/package/kernel/mac80211/patches/394-0001-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch b/package/kernel/mac80211/patches/394-0001-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch +deleted file mode 100644 +index 97444b3..0000000 +--- a/package/kernel/mac80211/patches/394-0001-brcmfmac-consolidate-ifp-lookup-in-driver-core.patch ++++ /dev/null +@@ -1,138 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:14:53 +0200 +-Subject: [PATCH] brcmfmac: consolidate ifp lookup in driver core +- +-In rx path the firmware provide an interface index which is used to +-map to a struct brcmf_if instance. However, this involves some trick +-that is done in two places. This is changed by having driver core +-providing brcmf_get_ifp() function. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +-@@ -276,6 +276,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu +- struct sk_buff *pktbuf) +- { +- struct brcmf_proto_bcdc_header *h; +-+ struct brcmf_if *ifp; +- +- brcmf_dbg(BCDC, "Enter\n"); +- +-@@ -289,30 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu +- trace_brcmf_bcdchdr(pktbuf->data); +- h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); +- +-- *ifidx = BCDC_GET_IF_IDX(h); +-- if (*ifidx >= BRCMF_MAX_IFS) { +-- brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); +-+ ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); +-+ if (IS_ERR_OR_NULL(ifp)) { +-+ brcmf_dbg(INFO, "no matching ifp found\n"); +- return -EBADE; +- } +-- /* The ifidx is the idx to map to matching netdev/ifp. When receiving +-- * events this is easy because it contains the bssidx which maps +-- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. +-- * bssidx 1 is used for p2p0 and no data can be received or +-- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 +-- */ +-- if (*ifidx) +-- (*ifidx)++; +-- +- if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != +- BCDC_PROTO_VER) { +- brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", +-- brcmf_ifname(drvr, *ifidx), h->flags); +-+ brcmf_ifname(drvr, ifp->ifidx), h->flags); +- return -EBADE; +- } +- +- if (h->flags & BCDC_FLAG_SUM_GOOD) { +- brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", +-- brcmf_ifname(drvr, *ifidx), h->flags); +-+ brcmf_ifname(drvr, ifp->ifidx), h->flags); +- pktbuf->ip_summed = CHECKSUM_UNNECESSARY; +- } +- +-@@ -320,12 +312,15 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu +- +- skb_pull(pktbuf, BCDC_HEADER_LEN); +- if (do_fws) +-- brcmf_fws_hdrpull(drvr, *ifidx, h->data_offset << 2, pktbuf); +-+ brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2, +-+ pktbuf); +- else +- skb_pull(pktbuf, h->data_offset << 2); +- +- if (pktbuf->len == 0) +- return -ENODATA; +-+ +-+ *ifidx = ifp->ifidx; +- return 0; +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -83,6 +83,25 @@ char *brcmf_ifname(struct brcmf_pub *drv +- return ""; +- } +- +-+struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) +-+{ +-+ if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { +-+ brcmf_err("ifidx %d out of range\n", ifidx); +-+ return ERR_PTR(-ERANGE); +-+ } +-+ +-+ /* The ifidx is the idx to map to matching netdev/ifp. When receiving +-+ * events this is easy because it contains the bssidx which maps +-+ * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. +-+ * bssidx 1 is used for p2p0 and no data can be received or +-+ * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 +-+ */ +-+ if (ifidx) +-+ ifidx++; +-+ +-+ return drvr->iflist[ifidx]; +-+} +-+ +- static void _brcmf_set_multicast_list(struct work_struct *work) +- { +- struct brcmf_if *ifp; +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h +-@@ -202,7 +202,7 @@ int brcmf_netdev_wait_pend8021x(struct b +- +- /* Return pointer to interface name */ +- char *brcmf_ifname(struct brcmf_pub *drvr, int idx); +-- +-+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 bssidx, s32 ifidx, +- char *name, u8 *mac_addr); +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-@@ -1081,16 +1081,8 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf +- { +- struct brcmf_if *ifp; +- +-- /* The ifidx is the idx to map to matching netdev/ifp. When receiving +-- * events this is easy because it contains the bssidx which maps +-- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. +-- * bssidx 1 is used for p2p0 and no data can be received or +-- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 +-- */ +-- if (ifidx) +-- (ifidx)++; +-- ifp = msgbuf->drvr->iflist[ifidx]; +-- if (!ifp || !ifp->ndev) { +-+ ifp = brcmf_get_ifp(msgbuf->drvr, ifidx); +-+ if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) { +- brcmf_err("Received pkt for invalid ifidx %d\n", ifidx); +- brcmu_pkt_buf_free_skb(skb); +- return; +diff --git a/package/kernel/mac80211/patches/394-0002-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch b/package/kernel/mac80211/patches/394-0002-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch +deleted file mode 100644 +index 632714c..0000000 +--- a/package/kernel/mac80211/patches/394-0002-brcmfmac-make-brcmf_proto_hdrpull-return-struct-brcm.patch ++++ /dev/null +@@ -1,222 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:14:54 +0200 +-Subject: [PATCH] brcmfmac: make brcmf_proto_hdrpull() return struct +- brcmf_if instance +- +-Avoid spreading the ifidx in the driver, but have it return the +-struct brcmf_if instance. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +-@@ -272,11 +272,11 @@ brcmf_proto_bcdc_hdrpush(struct brcmf_pu +- } +- +- static int +--brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, +-- struct sk_buff *pktbuf) +-+brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws, +-+ struct sk_buff *pktbuf, struct brcmf_if **ifp) +- { +- struct brcmf_proto_bcdc_header *h; +-- struct brcmf_if *ifp; +-+ struct brcmf_if *tmp_if; +- +- brcmf_dbg(BCDC, "Enter\n"); +- +-@@ -290,21 +290,21 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu +- trace_brcmf_bcdchdr(pktbuf->data); +- h = (struct brcmf_proto_bcdc_header *)(pktbuf->data); +- +-- ifp = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); +-- if (IS_ERR_OR_NULL(ifp)) { +-+ tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h)); +-+ if (!tmp_if) { +- brcmf_dbg(INFO, "no matching ifp found\n"); +- return -EBADE; +- } +- if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != +- BCDC_PROTO_VER) { +- brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", +-- brcmf_ifname(drvr, ifp->ifidx), h->flags); +-+ brcmf_ifname(drvr, tmp_if->ifidx), h->flags); +- return -EBADE; +- } +- +- if (h->flags & BCDC_FLAG_SUM_GOOD) { +- brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", +-- brcmf_ifname(drvr, ifp->ifidx), h->flags); +-+ brcmf_ifname(drvr, tmp_if->ifidx), h->flags); +- pktbuf->ip_summed = CHECKSUM_UNNECESSARY; +- } +- +-@@ -312,7 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu +- +- skb_pull(pktbuf, BCDC_HEADER_LEN); +- if (do_fws) +-- brcmf_fws_hdrpull(drvr, ifp->ifidx, h->data_offset << 2, +-+ brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2, +- pktbuf); +- else +- skb_pull(pktbuf, h->data_offset << 2); +-@@ -320,7 +320,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu +- if (pktbuf->len == 0) +- return -ENODATA; +- +-- *ifidx = ifp->ifidx; +-+ *ifp = tmp_if; +- return 0; +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -87,7 +87,7 @@ struct brcmf_if *brcmf_get_ifp(struct br +- { +- if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { +- brcmf_err("ifidx %d out of range\n", ifidx); +-- return ERR_PTR(-ERANGE); +-+ return NULL; +- } +- +- /* The ifidx is the idx to map to matching netdev/ifp. When receiving +-@@ -539,17 +539,15 @@ void brcmf_rx_frame(struct device *dev, +- struct brcmf_bus *bus_if = dev_get_drvdata(dev); +- struct brcmf_pub *drvr = bus_if->drvr; +- struct brcmf_skb_reorder_data *rd; +-- u8 ifidx; +- int ret; +- +- brcmf_dbg(DATA, "Enter: %s: rxp=%p\n", dev_name(dev), skb); +- +- /* process and remove protocol-specific header */ +-- ret = brcmf_proto_hdrpull(drvr, true, &ifidx, skb); +-- ifp = drvr->iflist[ifidx]; +-+ ret = brcmf_proto_hdrpull(drvr, true, skb, &ifp); +- +- if (ret || !ifp || !ifp->ndev) { +-- if ((ret != -ENODATA) && ifp) +-+ if (ret != -ENODATA && ifp) +- ifp->stats.rx_errors++; +- brcmu_pkt_buf_free_skb(skb); +- return; +-@@ -592,17 +590,17 @@ void brcmf_txcomplete(struct device *dev +- { +- struct brcmf_bus *bus_if = dev_get_drvdata(dev); +- struct brcmf_pub *drvr = bus_if->drvr; +-- u8 ifidx; +-+ struct brcmf_if *ifp; +- +- /* await txstatus signal for firmware if active */ +- if (brcmf_fws_fc_active(drvr->fws)) { +- if (!success) +- brcmf_fws_bustxfail(drvr->fws, txp); +- } else { +-- if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp)) +-+ if (brcmf_proto_hdrpull(drvr, false, txp, &ifp)) +- brcmu_pkt_buf_free_skb(txp); +- else +-- brcmf_txfinalize(drvr, txp, ifidx, success); +-+ brcmf_txfinalize(drvr, txp, ifp->ifidx, success); +- } +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-@@ -1448,7 +1448,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i +- struct sk_buff *skb; +- struct brcmf_skbuff_cb *skcb; +- struct brcmf_fws_mac_descriptor *entry = NULL; +-- u8 ifidx; +-+ struct brcmf_if *ifp; +- +- brcmf_dbg(DATA, "flags %d\n", flags); +- +-@@ -1497,15 +1497,16 @@ brcmf_fws_txs_process(struct brcmf_fws_i +- } +- brcmf_fws_macdesc_return_req_credit(skb); +- +-- if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) { +-+ ret = brcmf_proto_hdrpull(fws->drvr, false, skb, &ifp); +-+ if (ret) { +- brcmu_pkt_buf_free_skb(skb); +- return -EINVAL; +- } +- if (!remove_from_hanger) +-- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx, +-+ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx, +- genbit, seq); +- if (remove_from_hanger || ret) +-- brcmf_txfinalize(fws->drvr, skb, ifidx, true); +-+ brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true); +- +- return 0; +- } +-@@ -1848,7 +1849,7 @@ static int brcmf_fws_commit_skb(struct b +- entry->transit_count--; +- if (entry->suppressed) +- entry->suppr_transit_count--; +-- brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb); +-+ (void)brcmf_proto_hdrpull(fws->drvr, false, skb, NULL); +- goto rollback; +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-@@ -522,7 +522,7 @@ static int brcmf_msgbuf_set_dcmd(struct +- +- +- static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws, +-- u8 *ifidx, struct sk_buff *skb) +-+ struct sk_buff *skb, struct brcmf_if **ifp) +- { +- return -ENODEV; +- } +-@@ -1082,7 +1082,7 @@ brcmf_msgbuf_rx_skb(struct brcmf_msgbuf +- struct brcmf_if *ifp; +- +- ifp = brcmf_get_ifp(msgbuf->drvr, ifidx); +-- if (IS_ERR_OR_NULL(ifp) || !ifp->ndev) { +-+ if (!ifp || !ifp->ndev) { +- brcmf_err("Received pkt for invalid ifidx %d\n", ifidx); +- brcmu_pkt_buf_free_skb(skb); +- return; +---- a/drivers/net/wireless/brcm80211/brcmfmac/proto.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.h +-@@ -24,8 +24,8 @@ enum proto_addr_mode { +- +- +- struct brcmf_proto { +-- int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, u8 *ifidx, +-- struct sk_buff *skb); +-+ int (*hdrpull)(struct brcmf_pub *drvr, bool do_fws, +-+ struct sk_buff *skb, struct brcmf_if **ifp); +- int (*query_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, +- void *buf, uint len); +- int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf, +-@@ -46,9 +46,19 @@ int brcmf_proto_attach(struct brcmf_pub +- void brcmf_proto_detach(struct brcmf_pub *drvr); +- +- static inline int brcmf_proto_hdrpull(struct brcmf_pub *drvr, bool do_fws, +-- u8 *ifidx, struct sk_buff *skb) +-+ struct sk_buff *skb, +-+ struct brcmf_if **ifp) +- { +-- return drvr->proto->hdrpull(drvr, do_fws, ifidx, skb); +-+ struct brcmf_if *tmp = NULL; +-+ +-+ /* assure protocol is always called with +-+ * non-null initialized pointer. +-+ */ +-+ if (ifp) +-+ *ifp = NULL; +-+ else +-+ ifp = &tmp; +-+ return drvr->proto->hdrpull(drvr, do_fws, skb, ifp); +- } +- static inline int brcmf_proto_query_dcmd(struct brcmf_pub *drvr, int ifidx, +- uint cmd, void *buf, uint len) +diff --git a/package/kernel/mac80211/patches/394-0003-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch b/package/kernel/mac80211/patches/394-0003-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch +deleted file mode 100644 +index 2d15a77..0000000 +--- a/package/kernel/mac80211/patches/394-0003-brcmfmac-change-parameters-for-brcmf_remove_interfac.patch ++++ /dev/null +@@ -1,87 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:14:55 +0200 +-Subject: [PATCH] brcmfmac: change parameters for +- brcmf_remove_interface() +- +-Just pass the interface to be removed, ie. the struct brcmf_if instance. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -4982,7 +4982,7 @@ brcmf_notify_connect_status_ap(struct br +- brcmf_dbg(CONN, "AP mode link down\n"); +- complete(&cfg->vif_disabled); +- if (ifp->vif->mbss) +-- brcmf_remove_interface(ifp->drvr, ifp->bssidx); +-+ brcmf_remove_interface(ifp); +- return 0; +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -887,12 +887,13 @@ static void brcmf_del_if(struct brcmf_pu +- } +- } +- +--void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx) +-+void brcmf_remove_interface(struct brcmf_if *ifp) +- { +-- if (drvr->iflist[bssidx]) { +-- brcmf_fws_del_interface(drvr->iflist[bssidx]); +-- brcmf_del_if(drvr, bssidx); +-- } +-+ if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp)) +-+ return; +-+ +-+ brcmf_fws_del_interface(ifp); +-+ brcmf_del_if(ifp->drvr, ifp->bssidx); +- } +- +- int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr) +-@@ -1122,7 +1123,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, i); +-+ brcmf_remove_interface(drvr->iflist[i]); +- +- brcmf_cfg80211_detach(drvr->config); +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h +-@@ -206,7 +206,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 bssidx, s32 ifidx, +- char *name, u8 *mac_addr); +--void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx); +-+void brcmf_remove_interface(struct brcmf_if *ifp); +- int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); +- void brcmf_txflowblock_if(struct brcmf_if *ifp, +- enum brcmf_netif_stop_reason reason, bool state); +---- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +-@@ -222,7 +222,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(drvr, ifevent->bssidx); +-+ brcmf_remove_interface(ifp); +- } +- +- /** +---- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +-@@ -2140,7 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(stru +- { +- cfg80211_unregister_wdev(&vif->wdev); +- p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; +-- brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx); +-+ brcmf_remove_interface(vif->ifp); +- brcmf_free_vif(vif); +- } +- +diff --git a/package/kernel/mac80211/patches/394-0004-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch b/package/kernel/mac80211/patches/394-0004-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch +deleted file mode 100644 +index 2b61f4e..0000000 +--- a/package/kernel/mac80211/patches/394-0004-brcmfmac-only-call-brcmf_cfg80211_detach-when-attach.patch ++++ /dev/null +@@ -1,92 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:14:56 +0200 +-Subject: [PATCH] brcmfmac: only call brcmf_cfg80211_detach() when attach +- was successful +- +-In brcmf_bus_start() the function brcmf_cfg80211_attach() is called which +-may fail. If this happens we should not call brcmf_cfg80211_detach() in +-the failure path as it will result in NULL pointer dereference: +- +- brcmf_fweh_activate_events: Set event_msgs error (-5) +- brcmf_bus_start: failed: -5 +- brcmf_sdio_firmware_callback: dongle is not responding +- BUG: unable to handle kernel NULL pointer dereference at 0000000000000068 +- IP: [] kernfs_find_ns+0x18/0xd0 +- PGD 0 +- Oops: 0000 [#1] SMP +- Modules linked in: brcmfmac(O) brcmutil(O) cfg80211 auth_rpcgss +- CPU: 1 PID: 45 Comm: kworker/1:1 Tainted: G O +- Hardware name: Dell Inc. Latitude E6410/07XJP9, BIOS A07 02/15/2011 +- Workqueue: events request_firmware_work_func +- task: ffff880036c09ac0 ti: ffff880036dd4000 task.ti: ffff880036dd4000 +- RIP: 0010:[] [] kernfs_find_ns+0x18/0xd0 +- RSP: 0018:ffff880036dd7a28 EFLAGS: 00010246 +- RAX: ffff880036c09ac0 RBX: 0000000000000000 RCX: 000000007fffffff +- RDX: 0000000000000000 RSI: ffffffff816578b9 RDI: 0000000000000000 +- RBP: ffff880036dd7a48 R08: 0000000000000000 R09: ffff880036c0b340 +- R10: 00000000000002ec R11: ffff880036dd7b08 R12: ffffffff816578b9 +- R13: 0000000000000000 R14: ffffffff816578b9 R15: ffff8800c6c87000 +- FS: 0000000000000000(0000) GS:ffff88012bc40000(0000) knlGS:0000000000000000 +- CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b +- CR2: 0000000000000068 CR3: 0000000001a0b000 CR4: 00000000000006e0 +- Stack: +- 0000000000000000 ffffffff816578b9 0000000000000000 ffff8800c0d003c8 +- ffff880036dd7a78 ffffffff811e8ff5 0000000ffffffff1 ffffffff81a9b060 +- ffff8800c789f880 ffff8800c0d00000 ffff880036dd7a98 ffffffff811ebe0d +- Call Trace: +- [] kernfs_find_and_get_ns+0x35/0x60 +- [] sysfs_unmerge_group+0x1d/0x60 +- [] dpm_sysfs_remove+0x22/0x60 +- [] device_del+0x49/0x240 +- [] rfkill_unregister+0x58/0xc0 +- [] wiphy_unregister+0xab/0x2f0 [cfg80211] +- [] brcmf_cfg80211_detach+0x23/0x50 [brcmfmac] +- [] brcmf_detach+0x86/0xe0 [brcmfmac] +- [] brcmf_sdio_remove+0x48/0x120 [brcmfmac] +- [] brcmf_sdiod_remove+0x29/0xd0 [brcmfmac] +- [] brcmf_ops_sdio_remove+0xb1/0x110 [brcmfmac] +- [] sdio_bus_remove+0x37/0x100 [mmc_core] +- [] __device_release_driver+0x96/0x130 +- [] device_release_driver+0x23/0x30 +- [] brcmf_sdio_firmware_callback+0x2a8/0x5d0 [brcmfmac] +- [] brcmf_fw_request_nvram_done+0x15f/0x5e0 [brcmfmac] +- [] ? devres_add+0x3f/0x50 +- [] ? usermodehelper_read_unlock+0x15/0x20 +- [] ? platform_match+0x70/0xa0 +- [] request_firmware_work_func+0x30/0x60 +- [] process_one_work+0x14c/0x3d0 +- [] worker_thread+0x11a/0x450 +- [] ? process_one_work+0x3d0/0x3d0 +- [] kthread+0xd2/0xf0 +- [] ? kthread_create_on_node+0x180/0x180 +- [] ret_from_fork+0x3f/0x70 +- [] ? kthread_create_on_node+0x180/0x180 +- Code: e9 40 fe ff ff 48 89 d8 eb 87 66 0f 1f 84 00 00 00 00 00 66 66 66 66 +- 90 55 48 89 e5 41 56 49 89 f6 41 55 49 89 d5 31 d2 41 54 53 <0f> b7 +- 47 68 48 8b 5f 48 66 c1 e8 05 83 e0 01 4d 85 ed 0f b6 c8 +- RIP [] kernfs_find_ns+0x18/0xd0 +- RSP +- CR2: 0000000000000068 +- ---[ end trace 87d6ec0d3fe46740 ]--- +- +-Reported-by: Daniel (Deognyoun) Kim +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -1049,7 +1049,10 @@ int brcmf_bus_start(struct device *dev) +- fail: +- if (ret < 0) { +- brcmf_err("failed: %d\n", ret); +-- brcmf_cfg80211_detach(drvr->config); +-+ if (drvr->config) { +-+ brcmf_cfg80211_detach(drvr->config); +-+ drvr->config = NULL; +-+ } +- if (drvr->fws) { +- brcmf_fws_del_interface(ifp); +- brcmf_fws_deinit(drvr); +diff --git a/package/kernel/mac80211/patches/394-0005-brcmfmac-correct-detection-of-p2pdev-interface-event.patch b/package/kernel/mac80211/patches/394-0005-brcmfmac-correct-detection-of-p2pdev-interface-event.patch +deleted file mode 100644 +index 868b0a8..0000000 +--- a/package/kernel/mac80211/patches/394-0005-brcmfmac-correct-detection-of-p2pdev-interface-event.patch ++++ /dev/null +@@ -1,105 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:14:57 +0200 +-Subject: [PATCH] brcmfmac: correct detection of p2pdev interface event +- +-The p2pdev interface is setup in firmware resulting in a interface +-event. This event has role and no-if flag. When role is p2p client +-and no-if flag is set it indicates that this is the p2pdev interface. +-This info is used in handling the event and adding interface in the +-driver. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -795,7 +795,7 @@ fail: +- } +- +- struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, +-- char *name, u8 *mac_addr) +-+ bool is_p2pdev, char *name, u8 *mac_addr) +- { +- struct brcmf_if *ifp; +- struct net_device *ndev; +-@@ -821,7 +821,7 @@ struct brcmf_if *brcmf_add_if(struct brc +- } +- } +- +-- if (!brcmf_p2p_enable && bssidx == 1) { +-+ if (!brcmf_p2p_enable && is_p2pdev) { +- /* this is P2P_DEVICE interface */ +- brcmf_dbg(INFO, "allocate non-netdev interface\n"); +- ifp = kzalloc(sizeof(*ifp), GFP_KERNEL); +-@@ -999,12 +999,12 @@ int brcmf_bus_start(struct device *dev) +- brcmf_dbg(TRACE, "\n"); +- +- /* add primary networking interface */ +-- ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL); +-+ ifp = brcmf_add_if(drvr, 0, 0, false, "wlan%d", NULL); +- if (IS_ERR(ifp)) +- return PTR_ERR(ifp); +- +- if (brcmf_p2p_enable) +-- p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL); +-+ p2p_ifp = brcmf_add_if(drvr, 1, 0, false, "p2p%d", NULL); +- else +- p2p_ifp = NULL; +- if (IS_ERR(p2p_ifp)) +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h +-@@ -205,7 +205,7 @@ char *brcmf_ifname(struct brcmf_pub *drv +- 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 bssidx, s32 ifidx, +-- char *name, u8 *mac_addr); +-+ bool is_p2pdev, char *name, u8 *mac_addr); +- void brcmf_remove_interface(struct brcmf_if *ifp); +- int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); +- void brcmf_txflowblock_if(struct brcmf_if *ifp, +---- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +-@@ -179,6 +179,7 @@ static void brcmf_fweh_handle_if_event(s +- { +- struct brcmf_if_event *ifevent = data; +- struct brcmf_if *ifp; +-+ bool is_p2pdev; +- int err = 0; +- +- brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n", +-@@ -186,18 +187,16 @@ static void brcmf_fweh_handle_if_event(s +- ifevent->flags, ifevent->role); +- +- /* The P2P Device interface event must not be ignored +-- * contrary to what firmware tells us. The only way to +-- * distinguish the P2P Device is by looking at the ifidx +-- * and bssidx received. +-+ * contrary to what firmware tells us. +- */ +-- if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) && +-- (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { +-+ is_p2pdev = (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) && +-+ ifevent->role == BRCMF_E_IF_ROLE_P2P_CLIENT; +-+ if (!is_p2pdev && (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { +- brcmf_dbg(EVENT, "event can be ignored\n"); +- return; +- } +- if (ifevent->ifidx >= BRCMF_MAX_IFS) { +-- brcmf_err("invalid interface index: %u\n", +-- ifevent->ifidx); +-+ brcmf_err("invalid interface index: %u\n", ifevent->ifidx); +- return; +- } +- +-@@ -207,7 +206,7 @@ static void brcmf_fweh_handle_if_event(s +- brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname, +- emsg->addr); +- ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx, +-- emsg->ifname, emsg->addr); +-+ is_p2pdev, emsg->ifname, emsg->addr); +- if (IS_ERR(ifp)) +- return; +- brcmf_fws_add_interface(ifp); +diff --git a/package/kernel/mac80211/patches/394-0006-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch b/package/kernel/mac80211/patches/394-0006-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch +deleted file mode 100644 +index aebbfa6..0000000 +--- a/package/kernel/mac80211/patches/394-0006-brcmfmac-use-brcmf_get_ifp-to-map-ifidx-to-struct-br.patch ++++ /dev/null +@@ -1,126 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:14:58 +0200 +-Subject: [PATCH] brcmfmac: use brcmf_get_ifp() to map ifidx to struct +- brcmf_if instance +- +-The knowledge on how to map the interface index to a struct brcmf_if +-instance is in brcmf_get_ifp() so use that function when only the +-interface index is known instead of accessing brcmf_pub::iflist +-directly. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c +-@@ -149,7 +149,7 @@ static s32 brcmf_btcoex_params_read(stru +- static void brcmf_btcoex_boost_wifi(struct brcmf_btcoex_info *btci, +- bool trump_sco) +- { +-- struct brcmf_if *ifp = btci->cfg->pub->iflist[0]; +-+ struct brcmf_if *ifp = brcmf_get_ifp(btci->cfg->pub, 0); +- +- if (trump_sco && !btci->saved_regs_part2) { +- /* this should reduce eSCO agressive +-@@ -468,7 +468,7 @@ int brcmf_btcoex_set_mode(struct brcmf_c +- { +- struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy); +- struct brcmf_btcoex_info *btci = cfg->btcoex; +-- struct brcmf_if *ifp = cfg->pub->iflist[0]; +-+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); +- +- switch (mode) { +- case BRCMF_BTCOEX_DISABLED: +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -6212,7 +6212,7 @@ static void brcmf_free_wiphy(struct wiph +- struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, +- struct device *busdev) +- { +-- struct net_device *ndev = drvr->iflist[0]->ndev; +-+ struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev; +- struct brcmf_cfg80211_info *cfg; +- struct wiphy *wiphy; +- struct brcmf_cfg80211_vif *vif; +---- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c +-@@ -121,7 +121,7 @@ static void brcmf_feat_iovar_int_set(str +- +- void brcmf_feat_attach(struct brcmf_pub *drvr) +- { +-- struct brcmf_if *ifp = drvr->iflist[0]; +-+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); +- +- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan"); +- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn"); +---- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +-@@ -221,7 +221,7 @@ static void brcmf_flowring_block(struct +- +- bus_if = dev_get_drvdata(flow->dev); +- drvr = bus_if->drvr; +-- ifp = drvr->iflist[ifidx]; +-+ ifp = brcmf_get_ifp(drvr, ifidx); +- brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_FLOW, blocked); +- +- spin_unlock_irqrestore(&flow->block_lock, flags); +---- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +-@@ -334,7 +334,7 @@ void brcmf_fweh_attach(struct brcmf_pub +- void brcmf_fweh_detach(struct brcmf_pub *drvr) +- { +- struct brcmf_fweh_info *fweh = &drvr->fweh; +-- struct brcmf_if *ifp = drvr->iflist[0]; +-+ struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0); +- s8 eventmask[BRCMF_EVENTING_MASK_LEN]; +- +- if (ifp) { +---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-@@ -972,7 +972,7 @@ static void +- brcmf_fws_flow_control_check(struct brcmf_fws_info *fws, struct pktq *pq, +- u8 if_id) +- { +-- struct brcmf_if *ifp = fws->drvr->iflist[!if_id ? 0 : if_id + 1]; +-+ struct brcmf_if *ifp = brcmf_get_ifp(fws->drvr, if_id); +- +- if (WARN_ON(!ifp)) +- return; +-@@ -2118,6 +2118,7 @@ static int brcmf_debugfs_fws_stats_read( +- int brcmf_fws_init(struct brcmf_pub *drvr) +- { +- struct brcmf_fws_info *fws; +-+ struct brcmf_if *ifp; +- u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; +- int rc; +- u32 mode; +-@@ -2177,21 +2178,22 @@ int brcmf_fws_init(struct brcmf_pub *drv +- * continue. Set mode back to none indicating not enabled. +- */ +- fws->fw_signals = true; +-- if (brcmf_fil_iovar_int_set(drvr->iflist[0], "tlv", tlv)) { +-+ ifp = brcmf_get_ifp(drvr, 0); +-+ if (brcmf_fil_iovar_int_set(ifp, "tlv", tlv)) { +- brcmf_err("failed to set bdcv2 tlv signaling\n"); +- fws->fcmode = BRCMF_FWS_FCMODE_NONE; +- fws->fw_signals = false; +- } +- +-- if (brcmf_fil_iovar_int_set(drvr->iflist[0], "ampdu_hostreorder", 1)) +-+ if (brcmf_fil_iovar_int_set(ifp, "ampdu_hostreorder", 1)) +- brcmf_dbg(INFO, "enabling AMPDU host-reorder failed\n"); +- +- /* Enable seq number reuse, if supported */ +-- if (brcmf_fil_iovar_int_get(drvr->iflist[0], "wlfc_mode", &mode) == 0) { +-+ if (brcmf_fil_iovar_int_get(ifp, "wlfc_mode", &mode) == 0) { +- if (BRCMF_FWS_MODE_GET_REUSESEQ(mode)) { +- mode = 0; +- BRCMF_FWS_MODE_SET_REUSESEQ(mode, 1); +-- if (brcmf_fil_iovar_int_set(drvr->iflist[0], +-+ if (brcmf_fil_iovar_int_set(ifp, +- "wlfc_mode", mode) == 0) { +- BRCMF_FWS_MODE_SET_REUSESEQ(fws->mode, 1); +- } +diff --git a/package/kernel/mac80211/patches/394-0007-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch b/package/kernel/mac80211/patches/394-0007-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch +deleted file mode 100644 +index 23a7b6f..0000000 +--- a/package/kernel/mac80211/patches/394-0007-brcmfmac-pass-struct-brcmf_if-instance-in-brcmf_txfi.patch ++++ /dev/null +@@ -1,122 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:14:59 +0200 +-Subject: [PATCH] brcmfmac: pass struct brcmf_if instance in +- brcmf_txfinalize() +- +-Most call sites of brcmf_txfinalize already have struct brcmf_if +-instance so pass that to brcmf_txfinalize() as the function +-needs it anyway. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -560,17 +560,11 @@ void brcmf_rx_frame(struct device *dev, +- brcmf_netif_rx(ifp, skb); +- } +- +--void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, +-- bool success) +-+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success) +- { +-- struct brcmf_if *ifp; +- struct ethhdr *eh; +- u16 type; +- +-- ifp = drvr->iflist[ifidx]; +-- if (!ifp) +-- goto done; +-- +- eh = (struct ethhdr *)(txp->data); +- type = ntohs(eh->h_proto); +- +-@@ -582,7 +576,7 @@ void brcmf_txfinalize(struct brcmf_pub * +- +- if (!success) +- ifp->stats.tx_errors++; +--done: +-+ +- brcmu_pkt_buf_free_skb(txp); +- } +- +-@@ -600,7 +594,7 @@ void brcmf_txcomplete(struct device *dev +- if (brcmf_proto_hdrpull(drvr, false, txp, &ifp)) +- brcmu_pkt_buf_free_skb(txp); +- else +-- brcmf_txfinalize(drvr, txp, ifp->ifidx, success); +-+ brcmf_txfinalize(ifp, txp, success); +- } +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h +-@@ -210,8 +210,7 @@ void brcmf_remove_interface(struct brcmf +- int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); +- void brcmf_txflowblock_if(struct brcmf_if *ifp, +- enum brcmf_netif_stop_reason reason, bool state); +--void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx, +-- bool success); +-+void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); +- void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); +- +- /* Sets dongle media info (drv_version, mac address). */ +---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-@@ -1506,7 +1506,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i +- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx, +- genbit, seq); +- if (remove_from_hanger || ret) +-- brcmf_txfinalize(fws->drvr, skb, ifp->ifidx, true); +-+ brcmf_txfinalize(ifp, skb, true); +- +- return 0; +- } +-@@ -1905,7 +1905,7 @@ int brcmf_fws_process_skb(struct brcmf_i +- if (fws->avoid_queueing) { +- rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb); +- if (rc < 0) +-- brcmf_txfinalize(drvr, skb, ifp->ifidx, false); +-+ brcmf_txfinalize(ifp, skb, false); +- return rc; +- } +- +-@@ -1929,7 +1929,7 @@ int brcmf_fws_process_skb(struct brcmf_i +- brcmf_fws_schedule_deq(fws); +- } else { +- brcmf_err("drop skb: no hanger slot\n"); +-- brcmf_txfinalize(drvr, skb, ifp->ifidx, false); +-+ brcmf_txfinalize(ifp, skb, false); +- rc = -ENOMEM; +- } +- brcmf_fws_unlock(fws); +-@@ -2009,8 +2009,9 @@ static void brcmf_fws_dequeue_worker(str +- ret = brcmf_proto_txdata(drvr, ifidx, 0, skb); +- brcmf_fws_lock(fws); +- if (ret < 0) +-- brcmf_txfinalize(drvr, skb, ifidx, +-- false); +-+ brcmf_txfinalize(brcmf_get_ifp(drvr, +-+ ifidx), +-+ skb, false); +- if (fws->bus_flow_blocked) +- break; +- } +---- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +-@@ -873,7 +873,11 @@ brcmf_msgbuf_process_txstatus(struct brc +- commonring = msgbuf->flowrings[flowid]; +- atomic_dec(&commonring->outstanding_tx); +- +-- brcmf_txfinalize(msgbuf->drvr, skb, tx_status->msg.ifidx, true); +-+ /* Hante: i believe this was a bug as tx_status->msg.ifidx was used +-+ * in brcmf_txfinalize as index in drvr->iflist. Can you confirm/deny? +-+ */ +-+ brcmf_txfinalize(brcmf_get_ifp(msgbuf->drvr, tx_status->msg.ifidx), +-+ skb, true); +- } +- +- +diff --git a/package/kernel/mac80211/patches/394-0008-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch b/package/kernel/mac80211/patches/394-0008-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch +deleted file mode 100644 +index 8ddc0a6..0000000 +--- a/package/kernel/mac80211/patches/394-0008-brcmfmac-add-mapping-for-interface-index-to-bsscfg-i.patch ++++ /dev/null +@@ -1,92 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:15:00 +0200 +-Subject: [PATCH] brcmfmac: add mapping for interface index to bsscfg +- index +- +-Because the P2P Device interface in firmware uses the same interface +-index as the primary interface we use the bsscfg index as index in the +-struct brcmf_pub::iflist. However, in the data path we get the interface +-index and not the bsscfg index. So we need a mapping of interface index +-to bsscfg index, which can be determined upon handle adding the interface. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -85,21 +85,20 @@ char *brcmf_ifname(struct brcmf_pub *drv +- +- struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) +- { +-+ struct brcmf_if *ifp; +-+ s32 bssidx; +-+ +- if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { +- brcmf_err("ifidx %d out of range\n", ifidx); +- return NULL; +- } +- +-- /* The ifidx is the idx to map to matching netdev/ifp. When receiving +-- * events this is easy because it contains the bssidx which maps +-- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. +-- * bssidx 1 is used for p2p0 and no data can be received or +-- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 +-- */ +-- if (ifidx) +-- ifidx++; +-+ ifp = NULL; +-+ bssidx = drvr->if2bss[ifidx]; +-+ if (bssidx >= 0) +-+ ifp = drvr->iflist[bssidx]; +- +-- return drvr->iflist[ifidx]; +-+ return ifp; +- } +- +- static void _brcmf_set_multicast_list(struct work_struct *work) +-@@ -831,6 +830,8 @@ struct brcmf_if *brcmf_add_if(struct brc +- +- ifp = netdev_priv(ndev); +- ifp->ndev = ndev; +-+ /* store mapping ifidx to bssidx */ +-+ drvr->if2bss[ifidx] = bssidx; +- } +- +- ifp->drvr = drvr; +-@@ -855,6 +856,7 @@ static void brcmf_del_if(struct brcmf_pu +- struct brcmf_if *ifp; +- +- ifp = drvr->iflist[bssidx]; +-+ drvr->if2bss[ifp->ifidx] = -1; +- drvr->iflist[bssidx] = NULL; +- if (!ifp) { +- brcmf_err("Null interface, idx=%d\n", bssidx); +-@@ -862,6 +864,7 @@ static void brcmf_del_if(struct brcmf_pu +- } +- brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx); +- if (ifp->ndev) { +-+ drvr->if2bss[ifp->ifidx] = -1; +- if (bssidx == 0) { +- if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { +- rtnl_lock(); +-@@ -926,6 +929,7 @@ int brcmf_attach(struct device *dev) +- if (!drvr) +- return -ENOMEM; +- +-+ memset(drvr->if2bss, 0xFF, sizeof(drvr->if2bss)); +- mutex_init(&drvr->proto_block); +- +- /* Link to bus module */ +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h +-@@ -122,6 +122,7 @@ struct brcmf_pub { +- struct mac_address addresses[BRCMF_MAX_IFS]; +- +- struct brcmf_if *iflist[BRCMF_MAX_IFS]; +-+ s32 if2bss[BRCMF_MAX_IFS]; +- +- struct mutex proto_block; +- unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; +diff --git a/package/kernel/mac80211/patches/394-0009-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch b/package/kernel/mac80211/patches/394-0009-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch +deleted file mode 100644 +index a0a798b..0000000 +--- a/package/kernel/mac80211/patches/394-0009-brcmfmac-add-dedicated-debug-level-for-firmware-cons.patch ++++ /dev/null +@@ -1,103 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:15:01 +0200 +-Subject: [PATCH] brcmfmac: add dedicated debug level for firmware +- console logging +- +-Both PCIe and SDIO devices have the possibility to log the firmware +-console output in kernel log. For PCIe it is logged when PCIE debug +-level is enabled. For SDIO it is logged when user specifies a non-zero +-console interval through debugfs. This patch tries to make it a +-bit more consistent. The firmware console output is only logged when +-FWCON debug level is enabled. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Reviewed-by: Pontus Fuchs +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h +-@@ -37,6 +37,7 @@ +- #define BRCMF_SDIO_VAL 0x00020000 +- #define BRCMF_MSGBUF_VAL 0x00040000 +- #define BRCMF_PCIE_VAL 0x00080000 +-+#define BRCMF_FWCON_VAL 0x00100000 +- +- /* set default print format */ +- #undef pr_fmt +-@@ -78,6 +79,7 @@ do { \ +- #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) +- #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) +- #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) +-+#define BRCMF_FWCON_ON() (brcmf_msg_level & BRCMF_FWCON_VAL) +- +- #else /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */ +- +-@@ -90,6 +92,7 @@ do { \ +- #define BRCMF_GLOM_ON() 0 +- #define BRCMF_EVENT_ON() 0 +- #define BRCMF_FIL_ON() 0 +-+#define BRCMF_FWCON_ON() 0 +- +- #endif /* defined(DEBUG) || defined(CPTCFG_BRCM_TRACING) */ +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -644,7 +644,7 @@ static void brcmf_pcie_bus_console_init( +- addr = console->base_addr + BRCMF_CONSOLE_BUFSIZE_OFFSET; +- console->bufsize = brcmf_pcie_read_tcm32(devinfo, addr); +- +-- brcmf_dbg(PCIE, "Console: base %x, buf %x, size %d\n", +-+ brcmf_dbg(FWCON, "Console: base %x, buf %x, size %d\n", +- console->base_addr, console->buf_addr, console->bufsize); +- } +- +-@@ -656,6 +656,9 @@ static void brcmf_pcie_bus_console_read( +- u8 ch; +- u32 newidx; +- +-+ if (!BRCMF_FWCON_ON()) +-+ return; +-+ +- console = &devinfo->shared.console; +- addr = console->base_addr + BRCMF_CONSOLE_WRITEIDX_OFFSET; +- newidx = brcmf_pcie_read_tcm32(devinfo, addr); +-@@ -677,7 +680,7 @@ static void brcmf_pcie_bus_console_read( +- } +- if (ch == '\n') { +- console->log_str[console->log_idx] = 0; +-- brcmf_dbg(PCIE, "CONSOLE: %s", console->log_str); +-+ pr_debug("CONSOLE: %s", console->log_str); +- console->log_idx = 0; +- } +- } +---- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c +-@@ -123,6 +123,7 @@ struct rte_console { +- +- #define BRCMF_FIRSTREAD (1 << 6) +- +-+#define BRCMF_CONSOLE 10 /* watchdog interval to poll console */ +- +- /* SBSDIO_DEVICE_CTL */ +- +-@@ -3204,6 +3205,8 @@ static void brcmf_sdio_debugfs_create(st +- if (IS_ERR_OR_NULL(dentry)) +- return; +- +-+ bus->console_interval = BRCMF_CONSOLE; +-+ +- brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read); +- brcmf_debugfs_add_entry(drvr, "counters", +- brcmf_debugfs_sdio_count_read); +-@@ -3613,7 +3616,7 @@ static void brcmf_sdio_bus_watchdog(stru +- } +- #ifdef DEBUG +- /* Poll for console output periodically */ +-- if (bus->sdiodev->state == BRCMF_SDIOD_DATA && +-+ if (bus->sdiodev->state == BRCMF_SDIOD_DATA && BRCMF_FWCON_ON() && +- bus->console_interval != 0) { +- bus->console.count += BRCMF_WD_POLL_MS; +- if (bus->console.count >= bus->console_interval) { +diff --git a/package/kernel/mac80211/patches/394-0010-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch b/package/kernel/mac80211/patches/394-0010-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch +deleted file mode 100644 +index 53e7ede..0000000 +--- a/package/kernel/mac80211/patches/394-0010-brcmfmac-remove-ifidx-parameter-from-brcmf_fws_txsta.patch ++++ /dev/null +@@ -1,34 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:15:02 +0200 +-Subject: [PATCH] brcmfmac: remove ifidx parameter from +- brcmf_fws_txstatus_suppressed() +- +-The brcmf_fws_txstatus_suppressed() function prototype specifies an +-ifidx parameter which is not used within the function implementation. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-@@ -1398,7 +1398,7 @@ done: +- } +- +- static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo, +-- struct sk_buff *skb, u8 ifidx, +-+ struct sk_buff *skb, +- u32 genbit, u16 seq) +- { +- struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac; +-@@ -1503,7 +1503,7 @@ brcmf_fws_txs_process(struct brcmf_fws_i +- return -EINVAL; +- } +- if (!remove_from_hanger) +-- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifp->ifidx, +-+ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, +- genbit, seq); +- if (remove_from_hanger || ret) +- brcmf_txfinalize(ifp, skb, true); +diff --git a/package/kernel/mac80211/patches/394-0011-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch b/package/kernel/mac80211/patches/394-0011-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch +deleted file mode 100644 +index bb05235..0000000 +--- a/package/kernel/mac80211/patches/394-0011-brcmfmac-change-prototype-for-brcmf_fws_hdrpull.patch ++++ /dev/null +@@ -1,97 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:15:03 +0200 +-Subject: [PATCH] brcmfmac: change prototype for brcmf_fws_hdrpull() +- +-Instead of passing ifidx and drvr just pass struct brcmf_if pointer +-which holds both parameters. +- +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +-@@ -312,8 +312,7 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pu +- +- skb_pull(pktbuf, BCDC_HEADER_LEN); +- if (do_fws) +-- brcmf_fws_hdrpull(drvr, tmp_if->ifidx, h->data_offset << 2, +-- pktbuf); +-+ brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf); +- else +- skb_pull(pktbuf, h->data_offset << 2); +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +-@@ -1616,11 +1616,10 @@ static int brcmf_fws_notify_bcmc_credit_ +- return 0; +- } +- +--int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, +-- struct sk_buff *skb) +-+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb) +- { +- struct brcmf_skb_reorder_data *rd; +-- struct brcmf_fws_info *fws = drvr->fws; +-+ struct brcmf_fws_info *fws = ifp->drvr->fws; +- u8 *signal_data; +- s16 data_len; +- u8 type; +-@@ -1630,20 +1629,20 @@ int brcmf_fws_hdrpull(struct brcmf_pub * +- s32 err; +- +- brcmf_dbg(HDRS, "enter: ifidx %d, skblen %u, sig %d\n", +-- ifidx, skb->len, signal_len); +-+ ifp->ifidx, skb->len, siglen); +- +-- WARN_ON(signal_len > skb->len); +-+ WARN_ON(siglen > skb->len); +- +-- if (!signal_len) +-- return 0; +-+ if (!siglen) +-+ return; +- /* if flow control disabled, skip to packet data and leave */ +- if ((!fws) || (!fws->fw_signals)) { +-- skb_pull(skb, signal_len); +-- return 0; +-+ skb_pull(skb, siglen); +-+ return; +- } +- +- fws->stats.header_pulls++; +-- data_len = signal_len; +-+ data_len = siglen; +- signal_data = skb->data; +- +- status = BRCMF_FWS_RET_OK_NOSCHEDULE; +-@@ -1731,14 +1730,12 @@ int brcmf_fws_hdrpull(struct brcmf_pub * +- /* signalling processing result does +- * not affect the actual ethernet packet. +- */ +-- skb_pull(skb, signal_len); +-+ skb_pull(skb, siglen); +- +- /* this may be a signal-only packet +- */ +- if (skb->len == 0) +- fws->stats.header_only_pkt++; +-- +-- return 0; +- } +- +- static u8 brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo, +---- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.h +-@@ -21,8 +21,7 @@ +- int brcmf_fws_init(struct brcmf_pub *drvr); +- void brcmf_fws_deinit(struct brcmf_pub *drvr); +- bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); +--int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len, +-- struct sk_buff *skb); +-+void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb); +- int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb); +- +- void brcmf_fws_reset_interface(struct brcmf_if *ifp); +diff --git a/package/kernel/mac80211/patches/394-0012-brcmfmac-introduce-brcmf_net_detach-function.patch b/package/kernel/mac80211/patches/394-0012-brcmfmac-introduce-brcmf_net_detach-function.patch +deleted file mode 100644 +index ba92c67..0000000 +--- a/package/kernel/mac80211/patches/394-0012-brcmfmac-introduce-brcmf_net_detach-function.patch ++++ /dev/null +@@ -1,99 +0,0 @@ +-From: Arend van Spriel +-Date: Wed, 26 Aug 2015 22:15:04 +0200 +-Subject: [PATCH] brcmfmac: introduce brcmf_net_detach() function +- +-In case of error during brcmf_bus_start() the network interfaces were +-freed using free_netdev(). However, the interfaces may have additional +-memory allocated which is not freed. The netdev has destructor set to +-brcmf_cfg80211_free_netdev() which frees the additional memory if +-allocated and call free_netdev(). The brcmf_net_detach() either calls +-brcmf_cfg80211_free_netdev() directly or uses unregister_netdev() when +-struct net_device::reg_state indicates the netdev was registered. +- +-Reported-by: Daniel (Deognyoun) Kim +-Reviewed-by: Hante Meuleman +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -4746,7 +4746,8 @@ void brcmf_cfg80211_free_netdev(struct n +- ifp = netdev_priv(ndev); +- vif = ifp->vif; +- +-- brcmf_free_vif(vif); +-+ if (vif) +-+ brcmf_free_vif(vif); +- free_netdev(ndev); +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/core.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -718,8 +718,6 @@ int brcmf_net_attach(struct brcmf_if *if +- } +- +- brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); +-- +-- ndev->destructor = brcmf_cfg80211_free_netdev; +- return 0; +- +- fail: +-@@ -729,6 +727,14 @@ fail: +- return -EBADE; +- } +- +-+static void brcmf_net_detach(struct net_device *ndev) +-+{ +-+ if (ndev->reg_state == NETREG_REGISTERED) +-+ unregister_netdev(ndev); +-+ else +-+ brcmf_cfg80211_free_netdev(ndev); +-+} +-+ +- static int brcmf_net_p2p_open(struct net_device *ndev) +- { +- brcmf_dbg(TRACE, "Enter\n"); +-@@ -805,8 +811,7 @@ struct brcmf_if *brcmf_add_if(struct brc +- ifp->ndev->name); +- if (ifidx) { +- netif_stop_queue(ifp->ndev); +-- unregister_netdev(ifp->ndev); +-- free_netdev(ifp->ndev); +-+ brcmf_net_detach(ifp->ndev); +- drvr->iflist[bssidx] = NULL; +- } else { +- brcmf_err("ignore IF event\n"); +-@@ -828,6 +833,7 @@ struct brcmf_if *brcmf_add_if(struct brc +- if (!ndev) +- return ERR_PTR(-ENOMEM); +- +-+ ndev->destructor = brcmf_cfg80211_free_netdev; +- ifp = netdev_priv(ndev); +- ifp->ndev = ndev; +- /* store mapping ifidx to bssidx */ +-@@ -879,8 +885,7 @@ static void brcmf_del_if(struct brcmf_pu +- cancel_work_sync(&ifp->setmacaddr_work); +- cancel_work_sync(&ifp->multicast_work); +- } +-- /* unregister will take care of freeing it */ +-- unregister_netdev(ifp->ndev); +-+ brcmf_net_detach(ifp->ndev); +- } +- } +- +-@@ -1056,11 +1061,11 @@ fail: +- brcmf_fws_deinit(drvr); +- } +- if (drvr->iflist[0]) { +-- free_netdev(ifp->ndev); +-+ brcmf_net_detach(ifp->ndev); +- drvr->iflist[0] = NULL; +- } +- if (p2p_ifp) { +-- free_netdev(p2p_ifp->ndev); +-+ brcmf_net_detach(p2p_ifp->ndev); +- drvr->iflist[1] = NULL; +- } +- return ret; +diff --git a/package/kernel/mac80211/patches/395-brcmfmac-Reset-PCIE-devices-after-recognition.patch b/package/kernel/mac80211/patches/395-brcmfmac-Reset-PCIE-devices-after-recognition.patch +deleted file mode 100644 +index 5a7e447..0000000 +--- a/package/kernel/mac80211/patches/395-brcmfmac-Reset-PCIE-devices-after-recognition.patch ++++ /dev/null +@@ -1,193 +0,0 @@ +-From: Hante Meuleman +-Date: Thu, 27 Aug 2015 16:14:06 +0200 +-Subject: [PATCH] brcmfmac: Reset PCIE devices after recognition. +- +-When PCIE type devices are being FW reloaded without being properly +-reset then the device ends up in a locked state, requiring the +-device to be completely powered down. This patch adds a reset +-through watchdog at the moment the device (cores) has been +-recognized. This will solve warm reboot issues. +- +-Cc: Rafal Milecki +-Reviewed-by: Arend Van Spriel +-Reviewed-by: Franky (Zhenhui) Lin +-Reviewed-by: Pieter-Paul Giesberts +-Signed-off-by: Hante Meuleman +-Signed-off-by: Arend van Spriel +---- +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c +-@@ -101,6 +101,9 @@ +- /* ARM Cortex M3 core, ID 0x82a */ +- #define BCM4329_CORE_ARM_BASE 0x18002000 +- +-+/* Max possibly supported memory size (limited by IO mapped memory) */ +-+#define BRCMF_CHIP_MAX_MEMSIZE (4 * 1024 * 1024) +-+ +- #define CORE_SB(base, field) \ +- (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) +- #define SBCOREREV(sbidh) \ +-@@ -687,6 +690,12 @@ static int brcmf_chip_get_raminfo(struct +- brcmf_err("RAM size is undetermined\n"); +- return -ENOMEM; +- } +-+ +-+ if (ci->pub.ramsize > BRCMF_CHIP_MAX_MEMSIZE) { +-+ brcmf_err("RAM size is incorrect\n"); +-+ return -ENOMEM; +-+ } +-+ +- return 0; +- } +- +-@@ -899,6 +908,15 @@ static int brcmf_chip_recognition(struct +- +- /* assure chip is passive for core access */ +- brcmf_chip_set_passive(&ci->pub); +-+ +-+ /* Call bus specific reset function now. Cores have been determined +-+ * but further access may require a chip specific reset at this point. +-+ */ +-+ if (ci->ops->reset) { +-+ ci->ops->reset(ci->ctx, &ci->pub); +-+ brcmf_chip_set_passive(&ci->pub); +-+ } +-+ +- return brcmf_chip_get_raminfo(ci); +- } +- +---- a/drivers/net/wireless/brcm80211/brcmfmac/chip.h +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.h +-@@ -73,6 +73,7 @@ struct brcmf_buscore_ops { +- u32 (*read32)(void *ctx, u32 addr); +- void (*write32)(void *ctx, u32 addr, u32 value); +- int (*prepare)(void *ctx); +-+ int (*reset)(void *ctx, struct brcmf_chip *chip); +- int (*setup)(void *ctx, struct brcmf_chip *chip); +- void (*activate)(void *ctx, struct brcmf_chip *chip, u32 rstvec); +- }; +---- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +-@@ -74,6 +74,8 @@ enum brcmf_pcie_state { +- #define BRCMF_PCIE_REG_INTMASK 0x94 +- #define BRCMF_PCIE_REG_SBMBX 0x98 +- +-+#define BRCMF_PCIE_REG_LINK_STATUS_CTRL 0xBC +-+ +- #define BRCMF_PCIE_PCIE2REG_INTMASK 0x24 +- #define BRCMF_PCIE_PCIE2REG_MAILBOXINT 0x48 +- #define BRCMF_PCIE_PCIE2REG_MAILBOXMASK 0x4C +-@@ -466,6 +468,7 @@ brcmf_pcie_select_core(struct brcmf_pcie +- +- static void brcmf_pcie_reset_device(struct brcmf_pciedev_info *devinfo) +- { +-+ struct brcmf_core *core; +- u16 cfg_offset[] = { BRCMF_PCIE_CFGREG_STATUS_CMD, +- BRCMF_PCIE_CFGREG_PM_CSR, +- BRCMF_PCIE_CFGREG_MSI_CAP, +-@@ -484,32 +487,38 @@ static void brcmf_pcie_reset_device(stru +- if (!devinfo->ci) +- return; +- +-+ /* Disable ASPM */ +- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); +-- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, +-- BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL); +-- lsc = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA); +-+ pci_read_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, +-+ &lsc); +- val = lsc & (~BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB); +-- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, val); +-+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, +-+ val); +- +-+ /* Watchdog reset */ +- brcmf_pcie_select_core(devinfo, BCMA_CORE_CHIPCOMMON); +- WRITECC32(devinfo, watchdog, 4); +- msleep(100); +- +-+ /* Restore ASPM */ +- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); +-- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, +-- BRCMF_PCIE_CFGREG_LINK_STATUS_CTRL); +-- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, lsc); +-+ pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_LINK_STATUS_CTRL, +-+ lsc); +- +-- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); +-- for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) { +-- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, +-- cfg_offset[i]); +-- val = brcmf_pcie_read_reg32(devinfo, +-- BRCMF_PCIE_PCIE2REG_CONFIGDATA); +-- brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n", +-- cfg_offset[i], val); +-- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGDATA, +-- val); +-+ core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); +-+ if (core->rev <= 13) { +-+ for (i = 0; i < ARRAY_SIZE(cfg_offset); i++) { +-+ brcmf_pcie_write_reg32(devinfo, +-+ BRCMF_PCIE_PCIE2REG_CONFIGADDR, +-+ cfg_offset[i]); +-+ val = brcmf_pcie_read_reg32(devinfo, +-+ BRCMF_PCIE_PCIE2REG_CONFIGDATA); +-+ brcmf_dbg(PCIE, "config offset 0x%04x, value 0x%04x\n", +-+ cfg_offset[i], val); +-+ brcmf_pcie_write_reg32(devinfo, +-+ BRCMF_PCIE_PCIE2REG_CONFIGDATA, +-+ val); +-+ } +- } +- } +- +-@@ -519,8 +528,6 @@ static void brcmf_pcie_attach(struct brc +- u32 config; +- +- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); +-- if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) +-- brcmf_pcie_reset_device(devinfo); +- /* BAR1 window may not be sized properly */ +- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); +- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0); +-@@ -1636,6 +1643,23 @@ static int brcmf_pcie_buscoreprep(void * +- } +- +- +-+static int brcmf_pcie_buscore_reset(void *ctx, struct brcmf_chip *chip) +-+{ +-+ struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; +-+ u32 val; +-+ +-+ devinfo->ci = chip; +-+ brcmf_pcie_reset_device(devinfo); +-+ +-+ val = brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT); +-+ if (val != 0xffffffff) +-+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_MAILBOXINT, +-+ val); +-+ +-+ return 0; +-+} +-+ +-+ +- static void brcmf_pcie_buscore_activate(void *ctx, struct brcmf_chip *chip, +- u32 rstvec) +- { +-@@ -1647,6 +1671,7 @@ static void brcmf_pcie_buscore_activate( +- +- static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { +- .prepare = brcmf_pcie_buscoreprep, +-+ .reset = brcmf_pcie_buscore_reset, +- .activate = brcmf_pcie_buscore_activate, +- .read32 = brcmf_pcie_buscore_read32, +- .write32 = brcmf_pcie_buscore_write32, +-@@ -1814,7 +1839,6 @@ brcmf_pcie_remove(struct pci_dev *pdev) +- brcmf_pcie_intr_disable(devinfo); +- +- brcmf_detach(&pdev->dev); +-- brcmf_pcie_reset_device(devinfo); +- +- kfree(bus->bus_priv.pcie); +- kfree(bus->msgbuf->flowrings); +diff --git a/package/kernel/mac80211/patches/400-ath_move_debug_code.patch b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch +index 298f722..72e9a41 100644 +--- a/package/kernel/mac80211/patches/400-ath_move_debug_code.patch ++++ b/package/kernel/mac80211/patches/400-ath_move_debug_code.patch +@@ -14,7 +14,7 @@ + ccflags-y += -D__CHECK_ENDIAN__ + --- a/drivers/net/wireless/ath/ath.h + +++ b/drivers/net/wireless/ath/ath.h +-@@ -316,13 +316,6 @@ void _ath_dbg(struct ath_common *common, ++@@ -318,13 +318,6 @@ void _ath_dbg(struct ath_common *common, + #endif /* CPTCFG_ATH_DEBUG */ + + /** Returns string describing opmode, or NULL if unknown mode. */ +diff --git a/package/kernel/mac80211/patches/402-ath_regd_optional.patch b/package/kernel/mac80211/patches/402-ath_regd_optional.patch +index 2dac505..f918c18 100644 +--- a/package/kernel/mac80211/patches/402-ath_regd_optional.patch ++++ b/package/kernel/mac80211/patches/402-ath_regd_optional.patch +@@ -59,7 +59,7 @@ + ---help--- + --- a/.local-symbols + +++ b/.local-symbols +-@@ -89,6 +89,7 @@ RTL8187_LEDS= ++@@ -137,6 +137,7 @@ RTL8187_LEDS= + ATH_COMMON= + ATH_CARDS= + ATH_DEBUG= +diff --git a/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch b/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch +index 1476953..8b52ac3 100644 +--- a/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch ++++ b/package/kernel/mac80211/patches/404-regd_no_assoc_hints.patch +@@ -1,6 +1,6 @@ + --- a/net/wireless/reg.c + +++ b/net/wireless/reg.c +-@@ -2368,6 +2368,8 @@ void regulatory_hint_country_ie(struct w ++@@ -2390,6 +2390,8 @@ void regulatory_hint_country_ie(struct w + enum environment_cap env = ENVIRON_ANY; + struct regulatory_request *request = NULL, *lr; + +@@ -9,7 +9,7 @@ + /* IE len must be evenly divisible by 2 */ + if (country_ie_len & 0x01) + return; +-@@ -2571,6 +2573,7 @@ static void restore_regulatory_settings( ++@@ -2596,6 +2598,7 @@ static void restore_regulatory_settings( + + void regulatory_hint_disconnect(void) + { +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 93760f9..1a62484 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 +-@@ -715,6 +715,7 @@ static const struct ieee80211_iface_limi ++@@ -722,6 +722,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/440-ath5k_channel_bw_debugfs.patch b/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch +index aa521d2..42d43a4 100644 +--- a/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch ++++ b/package/kernel/mac80211/patches/440-ath5k_channel_bw_debugfs.patch +@@ -121,7 +121,7 @@ drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++ + debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah, + --- a/drivers/net/wireless/ath/ath5k/ath5k.h + +++ b/drivers/net/wireless/ath/ath5k/ath5k.h +-@@ -1371,6 +1371,7 @@ struct ath5k_hw { ++@@ -1370,6 +1370,7 @@ struct ath5k_hw { + u8 ah_coverage_class; + bool ah_ack_bitrate_high; + u8 ah_bwmode; +diff --git a/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch b/package/kernel/mac80211/patches/500-ath9k_eeprom_debugfs.patch +index c6f50be..a7f9d9f 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 +-@@ -1299,6 +1299,53 @@ void ath9k_deinit_debug(struct ath_softc ++@@ -1301,6 +1301,53 @@ void ath9k_deinit_debug(struct ath_softc + ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); + } + +@@ -54,7 +54,7 @@ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +-@@ -1318,6 +1365,8 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1320,6 +1367,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); + +diff --git a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch +index 0bdcae4..b4e9762 100644 +--- a/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch ++++ b/package/kernel/mac80211/patches/501-ath9k_ahb_init.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -1023,23 +1023,23 @@ static int __init ath9k_init(void) ++@@ -1031,23 +1031,23 @@ static int __init ath9k_init(void) + { + int error; + +diff --git a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch +index ed2cfee..d2a3b96 100644 +--- a/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch ++++ b/package/kernel/mac80211/patches/510-ath9k_intr_mitigation_tweak.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -389,13 +389,8 @@ static void ath9k_hw_init_config(struct ++@@ -390,13 +390,8 @@ static void ath9k_hw_init_config(struct + + ah->config.rx_intr_mitigation = true; + +@@ -14,5 +14,5 @@ + + ah->config.rimt_last = 250; + + ah->config.rimt_first = 500; + +- /* +- * We need this for PCI devices only (Cardbus, PCI, miniPCI) ++ if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) ++ ah->config.pll_pwrsave = 7; +diff --git a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch +index d4104f0..6766111 100644 +--- a/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch ++++ b/package/kernel/mac80211/patches/511-ath9k_reduce_rxbuf.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/ath9k.h + +++ b/drivers/net/wireless/ath/ath9k/ath9k.h +-@@ -87,7 +87,7 @@ int ath_descdma_setup(struct ath_softc * ++@@ -88,7 +88,7 @@ int ath_descdma_setup(struct ath_softc * + (_l) &= ((_sz) - 1); \ + } while (0) + +diff --git a/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch b/package/kernel/mac80211/patches/512-ath9k_channelbw_debugfs.patch +index c0fbf5e..5ecf528 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 +-@@ -1346,6 +1346,52 @@ static const struct file_operations fops ++@@ -1348,6 +1348,52 @@ static const struct file_operations fops + .owner = THIS_MODULE + }; + +@@ -53,7 +53,7 @@ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +-@@ -1367,6 +1413,8 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1369,6 +1415,8 @@ int ath9k_init_debug(struct ath_hw *ah) + + debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, + &fops_eeprom); +diff --git a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch +index 40b5c81..c84d1bc 100644 +--- a/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch ++++ b/package/kernel/mac80211/patches/513-ath9k_add_pci_ids.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -647,6 +647,7 @@ int ath9k_hw_init(struct ath_hw *ah) ++@@ -651,6 +651,7 @@ int ath9k_hw_init(struct ath_hw *ah) + + /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */ + switch (ah->hw_version.devid) { +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 0c50a0b..99bf7e8 100644 +--- a/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch ++++ b/package/kernel/mac80211/patches/522-mac80211_configure_antenna_gain.patch +@@ -18,7 +18,7 @@ + const u8 *addr); + --- a/include/net/mac80211.h + +++ b/include/net/mac80211.h +-@@ -1171,6 +1171,7 @@ enum ieee80211_smps_mode { ++@@ -1252,6 +1252,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 +@@ -26,7 +26,7 @@ + * + * @chandef: the channel definition to tune to + * @radar_enabled: whether radar detection is enabled +-@@ -1192,6 +1193,7 @@ struct ieee80211_conf { ++@@ -1273,6 +1274,7 @@ struct ieee80211_conf { + u32 flags; + int power_level, dynamic_ps_timeout; + int max_sleep_period; +@@ -36,7 +36,7 @@ + u8 ps_dtim_period; + --- a/include/uapi/linux/nl80211.h + +++ b/include/uapi/linux/nl80211.h +-@@ -1760,6 +1760,9 @@ enum nl80211_commands { ++@@ -1761,6 +1761,9 @@ enum nl80211_commands { + * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device + * is operating in an indoor environment. + * +@@ -46,7 +46,7 @@ + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use +-@@ -2129,6 +2132,8 @@ enum nl80211_attrs { ++@@ -2130,6 +2133,8 @@ enum nl80211_attrs { + + NL80211_ATTR_REG_INDOOR, + +@@ -57,7 +57,7 @@ + __NL80211_ATTR_AFTER_LAST, + --- a/net/mac80211/cfg.c + +++ b/net/mac80211/cfg.c +-@@ -2208,6 +2208,19 @@ static int ieee80211_get_tx_power(struct ++@@ -2233,6 +2233,19 @@ static int ieee80211_get_tx_power(struct + return 0; + } + +@@ -77,7 +77,7 @@ + static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, + const u8 *addr) + { +-@@ -3771,6 +3784,7 @@ const struct cfg80211_ops mac80211_confi ++@@ -3845,6 +3858,7 @@ const struct cfg80211_ops mac80211_confi + .set_wiphy_params = ieee80211_set_wiphy_params, + .set_tx_power = ieee80211_set_tx_power, + .get_tx_power = ieee80211_get_tx_power, +@@ -87,7 +87,7 @@ + CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) + --- a/net/mac80211/ieee80211_i.h + +++ b/net/mac80211/ieee80211_i.h +-@@ -1333,6 +1333,7 @@ struct ieee80211_local { ++@@ -1318,6 +1318,7 @@ struct ieee80211_local { + int dynamic_ps_forced_timeout; + + int user_power_level; /* in dBm, for all interfaces */ +@@ -97,7 +97,7 @@ + + --- a/net/mac80211/main.c + +++ b/net/mac80211/main.c +-@@ -98,7 +98,7 @@ static u32 ieee80211_hw_conf_chan(struct ++@@ -95,7 +95,7 @@ static u32 ieee80211_hw_conf_chan(struct + struct ieee80211_sub_if_data *sdata; + struct cfg80211_chan_def chandef = {}; + u32 changed = 0; +@@ -106,7 +106,7 @@ + u32 offchannel_flag; + + offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; +-@@ -155,6 +155,12 @@ static u32 ieee80211_hw_conf_chan(struct ++@@ -152,6 +152,12 @@ static u32 ieee80211_hw_conf_chan(struct + } + rcu_read_unlock(); + +@@ -119,7 +119,7 @@ + if (local->hw.conf.power_level != power) { + changed |= IEEE80211_CONF_CHANGE_POWER; + local->hw.conf.power_level = power; +-@@ -578,6 +584,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ ++@@ -581,6 +587,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_ + IEEE80211_RADIOTAP_MCS_HAVE_BW; + local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI | + IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; +@@ -129,7 +129,7 @@ + local->user_power_level = IEEE80211_UNSET_POWER_LEVEL; + --- a/net/wireless/nl80211.c + +++ b/net/wireless/nl80211.c +-@@ -400,6 +400,7 @@ static const struct nla_policy nl80211_p ++@@ -402,6 +402,7 @@ static const struct nla_policy nl80211_p + [NL80211_ATTR_NETNS_FD] = { .type = NLA_U32 }, + [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 }, + [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG }, +@@ -137,7 +137,7 @@ + }; + + /* policy for the key attributes */ +-@@ -2206,6 +2207,20 @@ static int nl80211_set_wiphy(struct sk_b ++@@ -2207,6 +2208,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 b0fb9fe..8aab45a 100644 +--- a/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch ++++ b/package/kernel/mac80211/patches/530-ath9k_extra_leds.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/ath9k.h + +++ b/drivers/net/wireless/ath/ath9k/ath9k.h +-@@ -814,6 +814,9 @@ static inline int ath9k_dump_btcoex(stru ++@@ -806,6 +806,9 @@ static inline int ath9k_dump_btcoex(stru + void ath_init_leds(struct ath_softc *sc); + void ath_deinit_leds(struct ath_softc *sc); + void ath_fill_led_pin(struct ath_softc *sc); +@@ -10,7 +10,7 @@ + #else + static inline void ath_init_leds(struct ath_softc *sc) + { +-@@ -953,6 +956,13 @@ void ath_ant_comb_scan(struct ath_softc ++@@ -945,6 +948,13 @@ void ath_ant_comb_scan(struct ath_softc + + #define ATH9K_NUM_CHANCTX 2 /* supports 2 operating channels */ + +@@ -24,7 +24,7 @@ + struct ath_softc { + struct ieee80211_hw *hw; + struct device *dev; +-@@ -1004,9 +1014,8 @@ struct ath_softc { ++@@ -996,9 +1006,8 @@ struct ath_softc { + spinlock_t chan_lock; + + #ifdef CPTCFG_MAC80211_LEDS +@@ -165,7 +165,7 @@ + void ath_fill_led_pin(struct ath_softc *sc) + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -935,7 +935,7 @@ int ath9k_init_device(u16 devid, struct ++@@ -943,7 +943,7 @@ int ath9k_init_device(u16 devid, struct + + #ifdef CPTCFG_MAC80211_LEDS + /* must be initialized before ieee80211_register_hw */ +@@ -176,7 +176,7 @@ + #endif + --- a/drivers/net/wireless/ath/ath9k/debug.c + +++ b/drivers/net/wireless/ath/ath9k/debug.c +-@@ -1391,6 +1391,61 @@ static const struct file_operations fops ++@@ -1393,6 +1393,61 @@ static const struct file_operations fops + .llseek = default_llseek, + }; + +@@ -238,7 +238,7 @@ + + int ath9k_init_debug(struct ath_hw *ah) + { +-@@ -1415,6 +1470,10 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1417,6 +1472,10 @@ int ath9k_init_debug(struct ath_hw *ah) + &fops_eeprom); + debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, + sc, &fops_chanbw); +diff --git a/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch b/package/kernel/mac80211/patches/542-ath9k_debugfs_diag.patch +index 631a692..2b2c763 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 +-@@ -1447,6 +1447,50 @@ static const struct file_operations fops ++@@ -1449,6 +1449,50 @@ static const struct file_operations fops + #endif + + +@@ -51,7 +51,7 @@ + int ath9k_init_debug(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +-@@ -1474,6 +1518,8 @@ int ath9k_init_debug(struct ath_hw *ah) ++@@ -1476,6 +1520,8 @@ int ath9k_init_debug(struct ath_hw *ah) + debugfs_create_file("gpio_led", S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_gpio_led); + #endif +@@ -62,7 +62,7 @@ + debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, + --- a/drivers/net/wireless/ath/ath9k/hw.h + +++ b/drivers/net/wireless/ath/ath9k/hw.h +-@@ -513,6 +513,12 @@ enum { ++@@ -519,6 +519,12 @@ enum { + ATH9K_RESET_COLD, + }; + +@@ -75,7 +75,7 @@ + struct ath9k_hw_version { + u32 magic; + u16 devid; +-@@ -794,6 +800,8 @@ struct ath_hw { ++@@ -804,6 +810,8 @@ struct ath_hw { + u32 rfkill_polarity; + u32 ah_flags; + +@@ -84,7 +84,7 @@ + bool reset_power_on; + bool htc_reset_init; + +-@@ -1055,6 +1063,7 @@ void ath9k_hw_check_nav(struct ath_hw *a ++@@ -1066,6 +1074,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); +@@ -94,7 +94,7 @@ + struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -1804,6 +1804,20 @@ u32 ath9k_hw_get_tsf_offset(struct times ++@@ -1808,6 +1808,20 @@ u32 ath9k_hw_get_tsf_offset(struct times + } + EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); + +@@ -115,7 +115,7 @@ + int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, + struct ath9k_hw_cal_data *caldata, bool fastcc) + { +-@@ -2012,6 +2026,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++@@ -2016,6 +2030,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 a8f1999..49b6367 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 @@ + --- a/drivers/net/wireless/ath/ath9k/hw.h + +++ b/drivers/net/wireless/ath/ath9k/hw.h +-@@ -710,6 +710,7 @@ struct ath_spec_scan { ++@@ -720,6 +720,7 @@ struct ath_spec_scan { + * @config_pci_powersave: + * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC + * +@@ -8,7 +8,7 @@ + * @spectral_scan_config: set parameters for spectral scan and enable/disable it + * @spectral_scan_trigger: trigger a spectral scan run + * @spectral_scan_wait: wait for a spectral scan run to finish +-@@ -732,6 +733,7 @@ struct ath_hw_ops { ++@@ -742,6 +743,7 @@ struct ath_hw_ops { + struct ath_hw_antcomb_conf *antconf); + void (*antdiv_comb_conf_set)(struct ath_hw *ah, + struct ath_hw_antcomb_conf *antconf); +@@ -55,7 +55,7 @@ + ops->spectral_scan_config = ar9003_hw_spectral_scan_config; + --- a/drivers/net/wireless/ath/ath9k/init.c + +++ b/drivers/net/wireless/ath/ath9k/init.c +-@@ -703,7 +703,8 @@ static void ath9k_init_txpower_limits(st ++@@ -710,7 +710,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); + +@@ -65,7 +65,7 @@ + } + + static const struct ieee80211_iface_limit if_limits[] = { +-@@ -895,6 +896,18 @@ static void ath9k_set_hw_capab(struct at ++@@ -903,6 +904,18 @@ static void ath9k_set_hw_capab(struct at + SET_IEEE80211_PERM_ADDR(hw, common->macaddr); + } + +@@ -84,7 +84,7 @@ + int ath9k_init_device(u16 devid, struct ath_softc *sc, + const struct ath_bus_ops *bus_ops) + { +-@@ -940,6 +953,8 @@ int ath9k_init_device(u16 devid, struct ++@@ -948,6 +961,8 @@ int ath9k_init_device(u16 devid, struct + ARRAY_SIZE(ath9k_tpt_blink)); + #endif + +@@ -110,7 +110,7 @@ + static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable) + --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c + +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +-@@ -1316,9 +1316,30 @@ void ar5008_hw_init_rate_txpower(struct ++@@ -1327,9 +1327,30 @@ void ar5008_hw_init_rate_txpower(struct + } + } + +@@ -141,7 +141,7 @@ + static const u32 ar5416_cca_regs[6] = { + AR_PHY_CCA, + AR_PHY_CH1_CCA, +-@@ -1333,6 +1354,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ ++@@ -1344,6 +1365,8 @@ int ar5008_hw_attach_phy_ops(struct ath_ + if (ret) + return ret; + +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 240b898..6ca642a 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 +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/hw.c + +++ b/drivers/net/wireless/ath/ath9k/hw.c +-@@ -245,6 +245,19 @@ void ath9k_hw_get_channel_centers(struct ++@@ -246,6 +246,19 @@ void ath9k_hw_get_channel_centers(struct + centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); + } + +@@ -20,7 +20,7 @@ + /******************/ + /* Chip Revisions */ + /******************/ +-@@ -1382,6 +1395,9 @@ static bool ath9k_hw_set_reset(struct at ++@@ -1386,6 +1399,9 @@ static bool ath9k_hw_set_reset(struct at + if (AR_SREV_9100(ah)) + udelay(50); + +@@ -30,7 +30,7 @@ + return true; + } + +-@@ -1481,6 +1497,9 @@ static bool ath9k_hw_chip_reset(struct a ++@@ -1485,6 +1501,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; + } + +-@@ -1782,8 +1801,14 @@ static int ath9k_hw_do_fastcc(struct ath ++@@ -1786,8 +1805,14 @@ static int ath9k_hw_do_fastcc(struct ath + if (AR_SREV_9271(ah)) + ar9002_hw_load_ani_reg(ah, chan); + +@@ -55,7 +55,7 @@ + return -EINVAL; + } + +-@@ -2037,6 +2062,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st ++@@ -2041,6 +2066,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st + ath9k_hw_set_radar_params(ah); + } + +diff --git a/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch b/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch +index 9610372..bc0aca6 100644 +--- a/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch ++++ b/package/kernel/mac80211/patches/545-ath9k_ani_ws_detect.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c + +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c +-@@ -945,55 +945,6 @@ static bool ar5008_hw_ani_control_new(st ++@@ -956,55 +956,6 @@ static bool ar5008_hw_ani_control_new(st + * on == 0 means more noise imm + */ + u32 on = param ? 1 : 0; +diff --git a/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch b/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch +index c0dc4fe..15863a6 100644 +--- a/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch ++++ b/package/kernel/mac80211/patches/600-0001-rt2x00-rt2800lib-move-rt2800_drv_data-declaration-in.patch +@@ -20,32 +20,14 @@ Changes since v1: --- + drivers/net/wireless/rt2x00/rt2800lib.h | 11 +++++++++++ + 2 files changed, 11 insertions(+), 13 deletions(-) + +---- a/drivers/net/wireless/rt2x00/rt2800.h +-+++ b/drivers/net/wireless/rt2x00/rt2800.h +-@@ -2960,17 +2960,4 @@ enum rt2800_eeprom_word { +- */ +- #define BCN_TBTT_OFFSET 64 +- +--/* +-- * RT2800 driver data structure +-- */ +--struct rt2800_drv_data { +-- u8 calibration_bw20; +-- u8 calibration_bw40; +-- u8 bbp25; +-- u8 bbp26; +-- u8 txmixer_gain_24g; +-- u8 txmixer_gain_5g; +-- unsigned int tbtt_tick; +--}; +-- +- #endif /* RT2800_H */ + --- a/drivers/net/wireless/rt2x00/rt2800lib.h + +++ b/drivers/net/wireless/rt2x00/rt2800lib.h +-@@ -20,6 +20,17 @@ ++@@ -20,6 +20,20 @@ + #ifndef RT2800LIB_H + #define RT2800LIB_H + +++#include "rt2800.h" +++ + +/* RT2800 driver data structure */ + +struct rt2800_drv_data { + + u8 calibration_bw20; +@@ -55,8 +37,30 @@ Changes since v1: --- + + u8 txmixer_gain_24g; + + u8 txmixer_gain_5g; + + unsigned int tbtt_tick; +++ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); + +}; + + + struct rt2800_ops { + void (*register_read)(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, u32 *value); ++--- a/drivers/net/wireless/rt2x00/rt2800.h +++++ b/drivers/net/wireless/rt2x00/rt2800.h ++@@ -2969,18 +2969,4 @@ enum rt2800_eeprom_word { ++ #define WCID_END 222 ++ #define STA_IDS_SIZE (WCID_END - WCID_START + 2) ++ ++-/* ++- * RT2800 driver data structure ++- */ ++-struct rt2800_drv_data { ++- u8 calibration_bw20; ++- u8 calibration_bw40; ++- u8 bbp25; ++- u8 bbp26; ++- u8 txmixer_gain_24g; ++- u8 txmixer_gain_5g; ++- unsigned int tbtt_tick; ++- DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); ++-}; ++- ++ #endif /* RT2800_H */ +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 6bad6ac..9165eec 100644 +--- 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 +@@ -24,7 +24,7 @@ Changes since v1: + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7747,6 +7747,7 @@ static int rt2800_probe_rt(struct rt2x00 ++@@ -7721,6 +7721,7 @@ static int rt2800_probe_rt(struct rt2x00 + + int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) + { +@@ -32,7 +32,7 @@ Changes since v1: + int retval; + u32 reg; + +-@@ -7754,6 +7755,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++@@ -7728,6 +7729,9 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (retval) + return retval; + +@@ -44,9 +44,9 @@ Changes since v1: + */ + --- a/drivers/net/wireless/rt2x00/rt2800lib.h + +++ b/drivers/net/wireless/rt2x00/rt2800lib.h +-@@ -20,6 +20,10 @@ +- #ifndef RT2800LIB_H +- #define RT2800LIB_H ++@@ -22,6 +22,10 @@ ++ ++ #include "rt2800.h" + + +enum rt2800_flag { + + RT2800_HAS_HIGH_SHARED_MEM, +@@ -55,16 +55,16 @@ Changes since v1: + /* RT2800 driver data structure */ + struct rt2800_drv_data { + u8 calibration_bw20; +-@@ -29,6 +33,8 @@ struct rt2800_drv_data { +- u8 txmixer_gain_24g; ++@@ -32,6 +36,8 @@ struct rt2800_drv_data { + u8 txmixer_gain_5g; + unsigned int tbtt_tick; ++ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); + + + + unsigned long rt2800_flags; + }; + + struct rt2800_ops { +-@@ -61,6 +67,13 @@ struct rt2800_ops { ++@@ -64,6 +70,13 @@ struct rt2800_ops { + __le32 *(*drv_get_txwi)(struct queue_entry *entry); + }; + +diff --git a/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch +index 9f8dfcc..5671515 100644 +--- a/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch ++++ b/package/kernel/mac80211/patches/600-0003-rt2x00-rt2800-serialize-shared-memory-access.patch +@@ -175,7 +175,7 @@ Changes since v1: --- + + /* + * Update WCID information +-@@ -1437,8 +1467,11 @@ int rt2800_config_pairwise_key(struct rt ++@@ -1405,8 +1435,11 @@ int rt2800_config_pairwise_key(struct rt + sizeof(key_entry.rx_mic)); + + offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); +@@ -187,7 +187,7 @@ Changes since v1: --- + } + + /* +-@@ -4908,14 +4941,19 @@ static int rt2800_init_registers(struct ++@@ -4884,14 +4917,19 @@ static int rt2800_init_registers(struct + /* + * ASIC will keep garbage value after boot, clear encryption keys. + */ +@@ -207,7 +207,7 @@ Changes since v1: --- + } + + /* +-@@ -5041,8 +5079,10 @@ static int rt2800_wait_bbp_ready(struct ++@@ -5017,8 +5055,10 @@ static int rt2800_wait_bbp_ready(struct + * BBP was enabled after firmware was loaded, + * but we need to reactivate it now. + */ +@@ -218,7 +218,7 @@ Changes since v1: --- + msleep(1); + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { +-@@ -6738,11 +6778,19 @@ int rt2800_enable_radio(struct rt2x00_de ++@@ -6714,11 +6754,19 @@ int rt2800_enable_radio(struct rt2x00_de + /* + * Send signal during boot time to initialize firmware. + */ +@@ -239,7 +239,7 @@ Changes since v1: --- + msleep(1); + + /* +-@@ -7751,6 +7799,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++@@ -7725,6 +7773,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r + int retval; + u32 reg; + +@@ -248,22 +248,22 @@ Changes since v1: --- + retval = rt2800_probe_rt(rt2x00dev); + if (retval) + return retval; +-@@ -7830,8 +7880,11 @@ void rt2800_get_tkip_seq(struct ieee8021 +- u32 offset; ++@@ -7808,8 +7858,11 @@ void rt2800_get_key_seq(struct ieee80211 ++ return; + +- offset = MAC_IVEIV_ENTRY(hw_key_idx); ++ offset = MAC_IVEIV_ENTRY(key->hw_key_idx); + + + + rt2800_shared_mem_lock(rt2x00dev); + rt2800_register_multiread(rt2x00dev, offset, + &iveiv_entry, sizeof(iveiv_entry)); + + rt2800_shared_mem_unlock(rt2x00dev); + +- memcpy(iv16, &iveiv_entry.iv[0], sizeof(*iv16)); +- memcpy(iv32, &iveiv_entry.iv[4], sizeof(*iv32)); ++ memcpy(&seq->tkip.iv16, &iveiv_entry.iv[0], 2); ++ memcpy(&seq->tkip.iv32, &iveiv_entry.iv[4], 4); + --- a/drivers/net/wireless/rt2x00/rt2800lib.h + +++ b/drivers/net/wireless/rt2x00/rt2800lib.h +-@@ -35,6 +35,11 @@ struct rt2800_drv_data { +- unsigned int tbtt_tick; ++@@ -38,6 +38,11 @@ struct rt2800_drv_data { ++ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); + + unsigned long rt2800_flags; + + +@@ -274,7 +274,7 @@ Changes since v1: --- + }; + + struct rt2800_ops { +-@@ -65,6 +70,10 @@ struct rt2800_ops { ++@@ -68,6 +73,10 @@ struct rt2800_ops { + const u8 *data, const size_t len); + int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); + __le32 *(*drv_get_txwi)(struct queue_entry *entry); +@@ -285,7 +285,7 @@ Changes since v1: --- + }; + + static inline bool rt2800_has_high_shared_mem(struct rt2x00_dev *rt2x00dev) +-@@ -74,6 +83,29 @@ static inline bool rt2800_has_high_share ++@@ -77,6 +86,29 @@ static inline bool rt2800_has_high_share + return test_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); + } + +@@ -486,7 +486,7 @@ Changes since v1: --- + /* + * Queue handlers. + */ +-@@ -294,8 +315,10 @@ static int rt2800usb_write_firmware(stru ++@@ -299,8 +320,10 @@ static int rt2800usb_write_firmware(stru + data + offset, length); + } + +@@ -497,7 +497,7 @@ Changes since v1: --- + + /* + * Send firmware request to device to load firmware, +-@@ -310,7 +333,10 @@ static int rt2800usb_write_firmware(stru ++@@ -315,7 +338,10 @@ static int rt2800usb_write_firmware(stru + } + + msleep(10); +@@ -508,7 +508,7 @@ Changes since v1: --- + + return 0; + } +-@@ -328,8 +354,10 @@ static int rt2800usb_init_registers(stru ++@@ -333,8 +359,10 @@ static int rt2800usb_init_registers(stru + if (rt2800_wait_csr_ready(rt2x00dev)) + return -EBUSY; + +@@ -519,7 +519,7 @@ Changes since v1: --- + + reg = 0; + rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); +-@@ -859,6 +887,9 @@ static const struct rt2800_ops rt2800usb ++@@ -863,6 +891,9 @@ static const struct rt2800_ops rt2800usb + .drv_write_firmware = rt2800usb_write_firmware, + .drv_init_registers = rt2800usb_init_registers, + .drv_get_txwi = rt2800usb_get_txwi, +diff --git a/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch +index e7eb630..d04998a 100644 +--- a/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch ++++ b/package/kernel/mac80211/patches/600-0005-rt2x00-rt2800lib-add-hw_beacon_count-field-to-struct.patch +@@ -24,7 +24,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -4638,6 +4638,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner); ++@@ -4614,6 +4614,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner); + */ + static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) + { +@@ -32,7 +32,7 @@ Signed-off-by: Gabor Juhos + u32 reg; + u16 eeprom; + unsigned int i; +-@@ -5003,7 +5004,7 @@ static int rt2800_init_registers(struct ++@@ -4979,7 +4980,7 @@ static int rt2800_init_registers(struct + /* + * Clear all beacons + */ +@@ -41,7 +41,7 @@ Signed-off-by: Gabor Juhos + rt2800_clear_beacon_register(rt2x00dev, i); + + if (rt2x00_is_usb(rt2x00dev)) { +-@@ -7852,6 +7853,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++@@ -7826,6 +7827,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (rt2x00_rt(rt2x00dev, RT3593)) + __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); + +@@ -52,11 +52,11 @@ Signed-off-by: Gabor Juhos + */ + --- a/drivers/net/wireless/rt2x00/rt2800lib.h + +++ b/drivers/net/wireless/rt2x00/rt2800lib.h +-@@ -33,6 +33,7 @@ struct rt2800_drv_data { ++@@ -35,6 +35,7 @@ struct rt2800_drv_data { + u8 txmixer_gain_24g; + u8 txmixer_gain_5g; + unsigned int tbtt_tick; + + unsigned int hw_beacon_count; ++ DECLARE_BITMAP(sta_ids, STA_IDS_SIZE); + + unsigned long rt2800_flags; +- +diff --git a/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch +index b79b4be..f5231f0 100644 +--- a/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch ++++ b/package/kernel/mac80211/patches/600-0006-rt2x00-rt2800lib-init-additional-beacon-offset-regis.patch +@@ -34,7 +34,7 @@ Signed-off-by: Gabor Juhos + */ + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -4650,6 +4650,30 @@ static int rt2800_init_registers(struct ++@@ -4626,6 +4626,30 @@ static int rt2800_init_registers(struct + if (ret) + return ret; + +diff --git a/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch +index 180c5e3..4b21eae 100644 +--- a/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch ++++ b/package/kernel/mac80211/patches/600-0007-rt2x00-rt2800lib-fix-max-supported-beacon-count-for-.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7877,7 +7877,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++@@ -7851,7 +7851,10 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (rt2x00_rt(rt2x00dev, RT3593)) + __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); + +diff --git a/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch +index 31aa34a..e77cd86 100644 +--- a/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch ++++ b/package/kernel/mac80211/patches/600-0009-rt2x00-rt2800lib-enable-support-for-RT3883.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7847,6 +7847,7 @@ static int rt2800_probe_rt(struct rt2x00 ++@@ -7821,6 +7821,7 @@ static int rt2800_probe_rt(struct rt2x00 + case RT3390: + case RT3572: + case RT3593: +diff --git a/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch +index a90c590..780c1dd 100644 +--- a/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch ++++ b/package/kernel/mac80211/patches/600-0010-rt2x00-rt2800lib-add-rf_vals-for-RF3853.patch +@@ -31,7 +31,7 @@ Signed-off-by: Gabor Juhos + #define RF5370 0x5370 + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7465,6 +7465,66 @@ static const struct rf_channel rf_vals_3 ++@@ -7441,6 +7441,66 @@ static const struct rf_channel rf_vals_3 + {173, 0x61, 0, 9}, + }; + +@@ -98,7 +98,7 @@ Signed-off-by: Gabor Juhos + static const struct rf_channel rf_vals_5592_xtal20[] = { + /* Channel, N, K, mod, R */ + {1, 482, 4, 10, 3}, +-@@ -7694,6 +7754,11 @@ static int rt2800_probe_hw_mode(struct r ++@@ -7668,6 +7728,11 @@ static int rt2800_probe_hw_mode(struct r + spec->channels = rf_vals_3x; + break; + +diff --git a/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch +index ab2673b..858dece 100644 +--- a/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch ++++ b/package/kernel/mac80211/patches/600-0011-rt2x00-rt2800lib-enable-VCO-calibration-for-RF3853.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -4402,6 +4402,7 @@ void rt2800_vco_calibration(struct rt2x0 ++@@ -4378,6 +4378,7 @@ void rt2800_vco_calibration(struct rt2x0 + case RF3053: + case RF3070: + case RF3290: +@@ -18,7 +18,7 @@ Signed-off-by: Gabor Juhos + case RF5360: + case RF5362: + case RF5370: +-@@ -7873,6 +7874,7 @@ static int rt2800_probe_hw_mode(struct r ++@@ -7847,6 +7848,7 @@ static int rt2800_probe_hw_mode(struct r + case RF3053: + case RF3070: + case RF3290: +diff --git a/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch +index 05ed444..ed82e44 100644 +--- a/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch ++++ b/package/kernel/mac80211/patches/600-0012-rt2x00-rt2800lib-add-channel-configuration-function-.patch +@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -2649,6 +2649,211 @@ static void rt2800_config_channel_rf3053 ++@@ -2625,6 +2625,211 @@ static void rt2800_config_channel_rf3053 + } + } + +@@ -223,7 +223,7 @@ Signed-off-by: Gabor Juhos + #define POWER_BOUND 0x27 + #define POWER_BOUND_5G 0x2b + +-@@ -3261,6 +3466,9 @@ static void rt2800_config_channel(struct ++@@ -3237,6 +3442,9 @@ static void rt2800_config_channel(struct + case RF3322: + rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); + break; +diff --git a/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch +index 3b50775..33cbc4c 100644 +--- a/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch ++++ b/package/kernel/mac80211/patches/600-0013-rt2x00-rt2800lib-enable-RF3853-support.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7430,6 +7430,7 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7406,6 +7406,7 @@ static int rt2800_init_eeprom(struct rt2 + case RF3290: + case RF3320: + case RF3322: +diff --git a/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch +index 4dfb068..c3a4798 100644 +--- a/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch ++++ b/package/kernel/mac80211/patches/600-0014-rt2x00-rt2800lib-add-MAC-register-initialization-for.patch +@@ -35,7 +35,7 @@ Signed-off-by: Gabor Juhos + #define RX_FILTER_CFG 0x1400 + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -5005,6 +5005,12 @@ static int rt2800_init_registers(struct ++@@ -4981,6 +4981,12 @@ static int rt2800_init_registers(struct + rt2800_register_write(rt2x00dev, TX_SW_CFG2, + 0x00000000); + } +@@ -48,7 +48,7 @@ Signed-off-by: Gabor Juhos + } else if (rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392) || + rt2x00_rt(rt2x00dev, RT5592)) { +-@@ -5035,9 +5041,11 @@ static int rt2800_init_registers(struct ++@@ -5011,9 +5017,11 @@ static int rt2800_init_registers(struct + + rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); +@@ -63,7 +63,7 @@ Signed-off-by: Gabor Juhos + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); + else + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); +-@@ -5190,6 +5198,11 @@ static int rt2800_init_registers(struct ++@@ -5166,6 +5174,11 @@ static int rt2800_init_registers(struct + reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002; + rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg); + +diff --git a/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch +index 6663b78..e647777 100644 +--- a/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch ++++ b/package/kernel/mac80211/patches/600-0016-rt2x00-rt2800lib-add-BBP-register-initialization-for.patch +@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -5808,6 +5808,47 @@ static void rt2800_init_bbp_3593(struct ++@@ -5784,6 +5784,47 @@ static void rt2800_init_bbp_3593(struct + rt2800_bbp_write(rt2x00dev, 103, 0xc0); + } + +@@ -59,7 +59,7 @@ Signed-off-by: Gabor Juhos + static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) + { + int ant, div_mode; +-@@ -6026,6 +6067,9 @@ static void rt2800_init_bbp(struct rt2x0 ++@@ -6002,6 +6043,9 @@ static void rt2800_init_bbp(struct rt2x0 + case RT3593: + rt2800_init_bbp_3593(rt2x00dev); + return; +diff --git a/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch +index 6e66f14..0fec3cd 100644 +--- a/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch ++++ b/package/kernel/mac80211/patches/600-0017-rt2x00-rt2800lib-add-RFCSR-initialization-for-RT3883.patch +@@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos + /* + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -6843,6 +6843,144 @@ static void rt2800_init_rfcsr_3593(struc ++@@ -6819,6 +6819,144 @@ static void rt2800_init_rfcsr_3593(struc + /* TODO: enable stream mode support */ + } + +@@ -166,7 +166,7 @@ Signed-off-by: Gabor Juhos + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) + { + rt2800_rf_init_calibration(rt2x00dev, 2); +-@@ -7074,6 +7212,9 @@ static void rt2800_init_rfcsr(struct rt2 ++@@ -7050,6 +7188,9 @@ static void rt2800_init_rfcsr(struct rt2 + case RT3390: + rt2800_init_rfcsr_3390(rt2x00dev); + break; +diff --git a/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch +index 9390f7e..c9d1e06 100644 +--- a/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch ++++ b/package/kernel/mac80211/patches/600-0019-rt2x00-rt2800lib-force-rf-type-to-RF3853-on-RT3883.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7611,6 +7611,8 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7587,6 +7587,8 @@ static int rt2800_init_eeprom(struct rt2 + rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392)) + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); +diff --git a/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch +index 1cba4f6..12b9c33 100644 +--- a/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch ++++ b/package/kernel/mac80211/patches/600-0020-rt2x00-rt2800lib-add-channel-configuration-code-for-.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -3429,6 +3429,36 @@ static char rt2800_txpower_to_dev(struct ++@@ -3405,6 +3405,36 @@ static char rt2800_txpower_to_dev(struct + return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); + } + +@@ -47,7 +47,7 @@ Signed-off-by: Gabor Juhos + static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, +-@@ -3447,6 +3477,12 @@ static void rt2800_config_channel(struct ++@@ -3423,6 +3453,12 @@ static void rt2800_config_channel(struct + rt2800_txpower_to_dev(rt2x00dev, rf->channel, + info->default_power3); + +@@ -60,7 +60,7 @@ Signed-off-by: Gabor Juhos + switch (rt2x00dev->chip.rf) { + case RF2020: + case RF3020: +-@@ -3530,6 +3566,15 @@ static void rt2800_config_channel(struct ++@@ -3506,6 +3542,15 @@ static void rt2800_config_channel(struct + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 77, 0x98); +@@ -76,7 +76,7 @@ Signed-off-by: Gabor Juhos + } else { + rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +-@@ -3542,6 +3587,7 @@ static void rt2800_config_channel(struct ++@@ -3518,6 +3563,7 @@ static void rt2800_config_channel(struct + !rt2x00_rt(rt2x00dev, RT5392)) { + if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { + rt2800_bbp_write(rt2x00dev, 82, 0x62); +@@ -84,7 +84,7 @@ Signed-off-by: Gabor Juhos + rt2800_bbp_write(rt2x00dev, 75, 0x46); + } else { + if (rt2x00_rt(rt2x00dev, RT3593)) +-@@ -3550,19 +3596,22 @@ static void rt2800_config_channel(struct ++@@ -3526,19 +3572,22 @@ static void rt2800_config_channel(struct + rt2800_bbp_write(rt2x00dev, 82, 0x84); + rt2800_bbp_write(rt2x00dev, 75, 0x50); + } +@@ -110,7 +110,7 @@ Signed-off-by: Gabor Juhos + rt2800_bbp_write(rt2x00dev, 83, 0x9a); + + if (rt2x00_has_cap_external_lna_a(rt2x00dev)) +-@@ -3684,6 +3733,23 @@ static void rt2800_config_channel(struct ++@@ -3660,6 +3709,23 @@ static void rt2800_config_channel(struct + + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); + +diff --git a/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch +index 1773128..3f40b4e 100644 +--- a/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch ++++ b/package/kernel/mac80211/patches/600-0021-rt2x00-rt2800lib-fix-txpower_to_dev-function-for-RT3.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -3416,13 +3416,15 @@ static char rt2800_txpower_to_dev(struct ++@@ -3392,13 +3392,15 @@ static char rt2800_txpower_to_dev(struct + unsigned int channel, + char txpower) + { +diff --git a/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch +index 36f0a4c..52baeec 100644 +--- a/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch ++++ b/package/kernel/mac80211/patches/600-0022-rt2x00-rt2800lib-use-correct-txpower-calculation-fun.patch +@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -4635,7 +4635,8 @@ static void rt2800_config_txpower(struct ++@@ -4611,7 +4611,8 @@ static void rt2800_config_txpower(struct + struct ieee80211_channel *chan, + int power_level) + { +diff --git a/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch +index 8119f97..b9dafc6 100644 +--- a/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch ++++ b/package/kernel/mac80211/patches/600-0023-rt2x00-rt2800lib-hardcode-txmixer-gain-values-to-zer.patch +@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7493,7 +7493,8 @@ static u8 rt2800_get_txmixer_gain_24g(st ++@@ -7469,7 +7469,8 @@ static u8 rt2800_get_txmixer_gain_24g(st + { + u16 word; + +@@ -21,7 +21,7 @@ Signed-off-by: Gabor Juhos + return 0; + + rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); +-@@ -7507,7 +7508,8 @@ static u8 rt2800_get_txmixer_gain_5g(str ++@@ -7483,7 +7484,8 @@ static u8 rt2800_get_txmixer_gain_5g(str + { + u16 word; + +diff --git a/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch +index dfbdee7..f09f803 100644 +--- a/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch ++++ b/package/kernel/mac80211/patches/600-0026-rt2x00-rt2800lib-use-correct-beacon-count-for-RT3883.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -8428,7 +8428,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++@@ -8402,7 +8402,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (rt2x00_rt(rt2x00dev, RT3593)) + __set_bit(RT2800_HAS_HIGH_SHARED_MEM, &drv_data->rt2800_flags); + +diff --git a/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch +index 22f7110..f7d23fc 100644 +--- a/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch ++++ b/package/kernel/mac80211/patches/600-0027-rt2x00-rt2800lib-fix-antenna-configuration-for-RT388.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -1961,7 +1961,8 @@ void rt2800_config_ant(struct rt2x00_dev ++@@ -1937,7 +1937,8 @@ void rt2800_config_ant(struct rt2x00_dev + rt2800_bbp_write(rt2x00dev, 3, r3); + rt2800_bbp_write(rt2x00dev, 1, r1); + +diff --git a/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch +index 9945f38..4da750e 100644 +--- a/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch ++++ b/package/kernel/mac80211/patches/600-0028-rt2x00-rt2800lib-fix-LNA-gain-configuration-for-RT38.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -1984,7 +1984,8 @@ static void rt2800_config_lna_gain(struc ++@@ -1960,7 +1960,8 @@ static void rt2800_config_lna_gain(struc + rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); + } else if (libconf->rf.channel <= 128) { +@@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos + rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, + EEPROM_EXT_LNA2_A1); +-@@ -1994,7 +1995,8 @@ static void rt2800_config_lna_gain(struc ++@@ -1970,7 +1971,8 @@ static void rt2800_config_lna_gain(struc + EEPROM_RSSI_BG2_LNA_A1); + } + } else { +diff --git a/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch +index beadea8..628b237 100644 +--- a/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch ++++ b/package/kernel/mac80211/patches/600-0029-rt2x00-rt2800lib-fix-VGC-setup-for-RT3883.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -4835,7 +4835,8 @@ static u8 rt2800_get_default_vgc(struct ++@@ -4811,7 +4811,8 @@ static u8 rt2800_get_default_vgc(struct + else + vgc = 0x2e + rt2x00dev->lna_gain; + } else { /* 5GHZ band */ +@@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos + vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3; + else if (rt2x00_rt(rt2x00dev, RT5592)) + vgc = 0x24 + (2 * rt2x00dev->lna_gain); +-@@ -4855,7 +4856,8 @@ static inline void rt2800_set_vgc(struct ++@@ -4831,7 +4832,8 @@ static inline void rt2800_set_vgc(struct + { + if (qual->vgc_level != vgc_level) { + if (rt2x00_rt(rt2x00dev, RT3572) || +@@ -30,7 +30,7 @@ Signed-off-by: Gabor Juhos + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, + vgc_level); + } else if (rt2x00_rt(rt2x00dev, RT5592)) { +-@@ -4902,6 +4904,11 @@ void rt2800_link_tuner(struct rt2x00_dev ++@@ -4878,6 +4880,11 @@ void rt2800_link_tuner(struct rt2x00_dev + } + break; + +diff --git a/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch +index a6c0f58..216b8b6 100644 +--- a/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch ++++ b/package/kernel/mac80211/patches/600-0030-rt2x00-rt2800lib-fix-EEPROM-LNA-validation-for-RT388.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7630,7 +7630,8 @@ static int rt2800_validate_eeprom(struct ++@@ -7606,7 +7606,8 @@ static int rt2800_validate_eeprom(struct + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); +@@ -20,7 +20,7 @@ Signed-off-by: Gabor Juhos + if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, +-@@ -7650,7 +7651,8 @@ static int rt2800_validate_eeprom(struct ++@@ -7626,7 +7627,8 @@ static int rt2800_validate_eeprom(struct + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); + if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) + rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); +@@ -30,7 +30,7 @@ Signed-off-by: Gabor Juhos + if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, +-@@ -7658,7 +7660,8 @@ static int rt2800_validate_eeprom(struct ++@@ -7634,7 +7636,8 @@ static int rt2800_validate_eeprom(struct + } + rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + +diff --git a/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch +index 910f9ec..515086f 100644 +--- a/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch ++++ b/package/kernel/mac80211/patches/600-0031-rt2x00-rt2800lib-fix-txpower-compensation-for-RT3883.patch +@@ -10,7 +10,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -4005,6 +4005,9 @@ static u8 rt2800_compensate_txpower(stru ++@@ -3981,6 +3981,9 @@ static u8 rt2800_compensate_txpower(stru + if (rt2x00_rt(rt2x00dev, RT3593)) + return min_t(u8, txpower, 0xc); + +diff --git a/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch +index bcdfc67..77e3f1b 100644 +--- a/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch ++++ b/package/kernel/mac80211/patches/600-0032-rt2x00-rt2800lib-enable-RT2800_HAS_HIGH_SHARED_MEM-f.patch +@@ -11,7 +11,7 @@ Signed-off-by: Gabor Juhos + + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -8441,7 +8441,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++@@ -8415,7 +8415,8 @@ int rt2800_probe_hw(struct rt2x00_dev *r + if (retval) + return retval; + +diff --git a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch +index 8f650a2..44b629f 100644 +--- a/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch ++++ b/package/kernel/mac80211/patches/603-rt2x00-introduce-rt2x00eeprom.patch +@@ -1,13 +1,13 @@ + --- a/.local-symbols + +++ b/.local-symbols +-@@ -263,6 +263,7 @@ RT2X00_LIB_FIRMWARE= ++@@ -312,6 +312,7 @@ RT2X00_LIB_FIRMWARE= + RT2X00_LIB_CRYPTO= + RT2X00_LIB_LEDS= + RT2X00_LIB_DEBUGFS= + +RT2X00_LIB_EEPROM= + RT2X00_DEBUG= +- RTL_CARDS= +- RTL8192CE= ++ WL_MEDIATEK= ++ MT7601U= + --- a/drivers/net/wireless/rt2x00/Kconfig + +++ b/drivers/net/wireless/rt2x00/Kconfig + @@ -69,6 +69,7 @@ config RT2800PCI +@@ -48,7 +48,7 @@ + obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o + --- a/drivers/net/wireless/rt2x00/rt2800lib.h + +++ b/drivers/net/wireless/rt2x00/rt2800lib.h +-@@ -43,6 +43,8 @@ struct rt2800_drv_data { ++@@ -46,6 +46,8 @@ struct rt2800_drv_data { + } shmem_lock; + }; + +@@ -57,7 +57,7 @@ + struct rt2800_ops { + void (*register_read)(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, u32 *value); +-@@ -176,6 +178,15 @@ static inline int rt2800_read_eeprom(str ++@@ -179,6 +181,15 @@ static inline int rt2800_read_eeprom(str + { + const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + +diff --git a/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch +index a35bd55..16a579d 100644 +--- a/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch ++++ b/package/kernel/mac80211/patches/608-add_platform_data_mac_addr.patch +@@ -41,7 +41,7 @@ + * Interrupt context handlers. + --- a/drivers/net/wireless/rt2x00/rt61pci.c + +++ b/drivers/net/wireless/rt2x00/rt61pci.c +-@@ -2392,6 +2392,7 @@ static int rt61pci_validate_eeprom(struc ++@@ -2390,6 +2390,7 @@ static int rt61pci_validate_eeprom(struc + u32 reg; + u16 word; + u8 *mac; +@@ -49,7 +49,7 @@ + s8 value; + + rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, ®); +-@@ -2412,7 +2413,11 @@ static int rt61pci_validate_eeprom(struc ++@@ -2410,7 +2411,11 @@ static int rt61pci_validate_eeprom(struc + /* + * Start validation of the data that has been read. + */ +diff --git a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch +index 067d2ea..39b1ccc 100644 +--- a/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch ++++ b/package/kernel/mac80211/patches/610-rt2x00-fix-rt3352-ext-pa.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -3552,11 +3552,18 @@ static void rt2800_config_channel(struct ++@@ -3528,11 +3528,18 @@ static void rt2800_config_channel(struct + /* + * Change BBP settings + */ +@@ -19,7 +19,7 @@ + } else if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rf->channel > 14) { + /* Disable CCK Packet detection on 5GHz */ +-@@ -6618,6 +6625,12 @@ static void rt2800_init_rfcsr_3290(struc ++@@ -6594,6 +6601,12 @@ static void rt2800_init_rfcsr_3290(struc + + static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) + { +@@ -32,7 +32,7 @@ + rt2800_rf_init_calibration(rt2x00dev, 30); + + rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); +-@@ -6653,15 +6666,30 @@ static void rt2800_init_rfcsr_3352(struc ++@@ -6629,15 +6642,30 @@ static void rt2800_init_rfcsr_3352(struc + rt2800_rfcsr_write(rt2x00dev, 31, 0x80); + rt2800_rfcsr_write(rt2x00dev, 32, 0x80); + rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +@@ -66,7 +66,7 @@ + rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); +-@@ -6669,15 +6697,20 @@ static void rt2800_init_rfcsr_3352(struc ++@@ -6645,15 +6673,20 @@ static void rt2800_init_rfcsr_3352(struc + rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); + rt2800_rfcsr_write(rt2x00dev, 48, 0x14); + rt2800_rfcsr_write(rt2x00dev, 49, 0x00); +@@ -96,7 +96,7 @@ + rt2800_rfcsr_write(rt2x00dev, 59, 0x00); + rt2800_rfcsr_write(rt2x00dev, 60, 0x00); + rt2800_rfcsr_write(rt2x00dev, 61, 0x00); +-@@ -7698,6 +7731,7 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7674,6 +7707,7 @@ static int rt2800_init_eeprom(struct rt2 + * RT53xx: defined in "EEPROM_CHIP_ID" field + */ + if (rt2x00_rt(rt2x00dev, RT3290) || +@@ -104,7 +104,7 @@ + rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392)) + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); +-@@ -7793,7 +7827,8 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7769,7 +7803,8 @@ static int rt2800_init_eeprom(struct rt2 + /* + * Detect if this device has Bluetooth co-existence. + */ +@@ -114,7 +114,7 @@ + __set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags); + + /* +-@@ -7822,6 +7857,22 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7798,6 +7833,22 @@ static int rt2800_init_eeprom(struct rt2 + EIRP_MAX_TX_POWER_LIMIT) + __set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags); + +diff --git a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch +index 1dcca36..dcecba4 100644 +--- a/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch ++++ b/package/kernel/mac80211/patches/611-rt2x00-rf_vals-rt3352-xtal20.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -8209,6 +8209,27 @@ static const struct rf_channel rf_vals_5 ++@@ -8185,6 +8185,27 @@ static const struct rf_channel rf_vals_5 + {196, 83, 0, 12, 1}, + }; + +@@ -28,7 +28,7 @@ + static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) + { + struct hw_mode_spec *spec = &rt2x00dev->spec; +-@@ -8297,7 +8318,10 @@ static int rt2800_probe_hw_mode(struct r ++@@ -8271,7 +8292,10 @@ static int rt2800_probe_hw_mode(struct r + case RF5390: + case RF5392: + spec->num_channels = 14; +@@ -40,7 +40,7 @@ + break; + + case RF3052: +-@@ -8481,6 +8505,19 @@ static int rt2800_probe_rt(struct rt2x00 ++@@ -8455,6 +8479,19 @@ static int rt2800_probe_rt(struct rt2x00 + return 0; + } + +@@ -60,7 +60,7 @@ + int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) + { + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +-@@ -8523,6 +8560,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r ++@@ -8497,6 +8534,15 @@ int rt2800_probe_hw(struct rt2x00_dev *r + rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + + /* +diff --git a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch +index c779a17..9f11862 100644 +--- a/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch ++++ b/package/kernel/mac80211/patches/615-rt2x00-fix_20mhz_clk.patch +@@ -8,7 +8,7 @@ + + #include "rt2x00.h" + #include "rt2800lib.h" +-@@ -8507,13 +8508,14 @@ static int rt2800_probe_rt(struct rt2x00 ++@@ -8481,13 +8482,14 @@ static int rt2800_probe_rt(struct rt2x00 + + int rt2800_probe_clk(struct rt2x00_dev *rt2x00dev) + { +diff --git a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch +index 840b3bc..9679d71 100644 +--- a/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch ++++ b/package/kernel/mac80211/patches/616-rt2x00-support-rt5350.patch +@@ -10,7 +10,7 @@ + #define RF5370 0x5370 + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -3038,6 +3038,13 @@ static void rt2800_config_channel_rf53xx ++@@ -3014,6 +3014,13 @@ static void rt2800_config_channel_rf53xx + + rt2800_rfcsr_write(rt2x00dev, 59, + r59_non_bt[idx]); +@@ -24,7 +24,7 @@ + } + } + } +-@@ -3516,6 +3523,7 @@ static void rt2800_config_channel(struct ++@@ -3492,6 +3499,7 @@ static void rt2800_config_channel(struct + rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info); + break; + case RF3070: +@@ -32,7 +32,7 @@ + case RF5360: + case RF5362: + case RF5370: +-@@ -3534,6 +3542,7 @@ static void rt2800_config_channel(struct ++@@ -3510,6 +3518,7 @@ static void rt2800_config_channel(struct + if (rt2x00_rf(rt2x00dev, RF3070) || + rt2x00_rf(rt2x00dev, RF3290) || + rt2x00_rf(rt2x00dev, RF3322) || +@@ -40,7 +40,7 @@ + rt2x00_rf(rt2x00dev, RF5360) || + rt2x00_rf(rt2x00dev, RF5362) || + rt2x00_rf(rt2x00dev, RF5370) || +-@@ -3812,7 +3821,8 @@ static void rt2800_config_channel(struct ++@@ -3788,7 +3797,8 @@ static void rt2800_config_channel(struct + /* + * Clear update flag + */ +@@ -50,7 +50,7 @@ + rt2800_bbp_read(rt2x00dev, 49, &bbp); + rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0); + rt2800_bbp_write(rt2x00dev, 49, bbp); +-@@ -4698,6 +4708,7 @@ void rt2800_vco_calibration(struct rt2x0 ++@@ -4674,6 +4684,7 @@ void rt2800_vco_calibration(struct rt2x0 + case RF3070: + case RF3290: + case RF3853: +@@ -58,7 +58,7 @@ + case RF5360: + case RF5362: + case RF5370: +-@@ -5111,6 +5122,8 @@ static int rt2800_init_registers(struct ++@@ -5087,6 +5098,8 @@ static int rt2800_init_registers(struct + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); +@@ -67,7 +67,7 @@ + } else { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +-@@ -5766,9 +5779,13 @@ static void rt2800_init_bbp_3352(struct ++@@ -5742,9 +5755,13 @@ static void rt2800_init_bbp_3352(struct + + rt2800_bbp_write(rt2x00dev, 82, 0x62); + +@@ -84,7 +84,7 @@ + + rt2800_bbp_write(rt2x00dev, 86, 0x38); + +-@@ -5782,9 +5799,13 @@ static void rt2800_init_bbp_3352(struct ++@@ -5758,9 +5775,13 @@ static void rt2800_init_bbp_3352(struct + + rt2800_bbp_write(rt2x00dev, 104, 0x92); + +@@ -101,7 +101,7 @@ + + rt2800_bbp_write(rt2x00dev, 120, 0x50); + +-@@ -5809,6 +5830,13 @@ static void rt2800_init_bbp_3352(struct ++@@ -5785,6 +5806,13 @@ static void rt2800_init_bbp_3352(struct + rt2800_bbp_write(rt2x00dev, 143, 0xa2); + + rt2800_bbp_write(rt2x00dev, 148, 0xc8); +@@ -115,7 +115,7 @@ + } + + static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) +-@@ -6150,6 +6178,7 @@ static void rt2800_init_bbp(struct rt2x0 ++@@ -6126,6 +6154,7 @@ static void rt2800_init_bbp(struct rt2x0 + rt2800_init_bbp_3290(rt2x00dev); + break; + case RT3352: +@@ -123,7 +123,7 @@ + rt2800_init_bbp_3352(rt2x00dev); + break; + case RT3390: +-@@ -7101,6 +7130,76 @@ static void rt2800_init_rfcsr_3883(struc ++@@ -7077,6 +7106,76 @@ static void rt2800_init_rfcsr_3883(struc + rt2800_rfcsr_write(rt2x00dev, 20, rfcsr); + } + +@@ -200,7 +200,7 @@ + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) + { + rt2800_rf_init_calibration(rt2x00dev, 2); +-@@ -7341,6 +7440,9 @@ static void rt2800_init_rfcsr(struct rt2 ++@@ -7317,6 +7416,9 @@ static void rt2800_init_rfcsr(struct rt2 + case RT3593: + rt2800_init_rfcsr_3593(rt2x00dev); + break; +@@ -210,7 +210,7 @@ + case RT5390: + rt2800_init_rfcsr_5390(rt2x00dev); + break; +-@@ -7600,6 +7702,12 @@ static int rt2800_validate_eeprom(struct ++@@ -7576,6 +7678,12 @@ static int rt2800_validate_eeprom(struct + rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); + rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); + rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word); +@@ -223,7 +223,7 @@ + } else if (rt2x00_rt(rt2x00dev, RT2860) || + rt2x00_rt(rt2x00dev, RT2872)) { + /* +-@@ -7738,6 +7846,8 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7714,6 +7822,8 @@ static int rt2800_init_eeprom(struct rt2 + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); + else if (rt2x00_rt(rt2x00dev, RT3883)) + rf = RF3853; +@@ -232,7 +232,7 @@ + else + rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); + +-@@ -7757,6 +7867,7 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7733,6 +7843,7 @@ static int rt2800_init_eeprom(struct rt2 + case RF3320: + case RF3322: + case RF3853: +@@ -240,7 +240,7 @@ + case RF5360: + case RF5362: + case RF5370: +-@@ -8312,6 +8423,7 @@ static int rt2800_probe_hw_mode(struct r ++@@ -8286,6 +8397,7 @@ static int rt2800_probe_hw_mode(struct r + case RF3290: + case RF3320: + case RF3322: +@@ -248,7 +248,7 @@ + case RF5360: + case RF5362: + case RF5370: +-@@ -8451,6 +8563,7 @@ static int rt2800_probe_hw_mode(struct r ++@@ -8425,6 +8537,7 @@ static int rt2800_probe_hw_mode(struct r + case RF3070: + case RF3290: + case RF3853: +@@ -256,7 +256,7 @@ + case RF5360: + case RF5362: + case RF5370: +-@@ -8491,6 +8604,7 @@ static int rt2800_probe_rt(struct rt2x00 ++@@ -8465,6 +8578,7 @@ static int rt2800_probe_rt(struct rt2x00 + case RT3572: + case RT3593: + case RT3883: +diff --git a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch +index 13f2048..b085c5e 100644 +--- a/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch ++++ b/package/kernel/mac80211/patches/619-rt2x00-change-led-polarity-from-OF.patch +@@ -8,7 +8,7 @@ + + #include "rt2x00.h" + #include "rt2800lib.h" +-@@ -7957,6 +7958,17 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7933,6 +7934,17 @@ static int rt2800_init_eeprom(struct rt2 + rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); + rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); + +diff --git a/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch +index aaa8367..259cb1f 100644 +--- a/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch ++++ b/package/kernel/mac80211/patches/620-rt2x00-rt3352-rf-id.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -7841,10 +7841,11 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7817,10 +7817,11 @@ static int rt2800_init_eeprom(struct rt2 + * RT53xx: defined in "EEPROM_CHIP_ID" field + */ + if (rt2x00_rt(rt2x00dev, RT3290) || +diff --git a/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch b/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch +index bb2fc1c..77d63fe 100644 +--- a/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch ++++ b/package/kernel/mac80211/patches/621-rt2x00-ht20_40_fix.patch +@@ -11,7 +11,7 @@ + * RFCSR 31: + --- a/drivers/net/wireless/rt2x00/rt2800lib.c + +++ b/drivers/net/wireless/rt2x00/rt2800lib.c +-@@ -3551,8 +3551,13 @@ static void rt2800_config_channel(struct ++@@ -3527,8 +3527,13 @@ static void rt2800_config_channel(struct + rt2x00_rf(rt2x00dev, RF5390) || + rt2x00_rf(rt2x00dev, RF5392)) { + rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +diff --git a/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch b/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch +index 9e29034..3b8b756 100644 +--- a/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch ++++ b/package/kernel/mac80211/patches/801-libertas-configure-sysfs-links.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/libertas/cfg.c + +++ b/drivers/net/wireless/libertas/cfg.c +-@@ -2084,6 +2084,8 @@ struct wireless_dev *lbs_cfg_alloc(struc ++@@ -2083,6 +2083,8 @@ struct wireless_dev *lbs_cfg_alloc(struc + goto err_wiphy_new; + } + +diff --git a/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch b/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch +index 252fa81..dace56b 100644 +--- a/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch ++++ b/package/kernel/mac80211/patches/802-libertas-set-wireless-macaddr.patch +@@ -1,6 +1,6 @@ + --- a/drivers/net/wireless/libertas/cfg.c + +++ b/drivers/net/wireless/libertas/cfg.c +-@@ -2174,6 +2174,8 @@ int lbs_cfg_register(struct lbs_private ++@@ -2173,6 +2173,8 @@ int lbs_cfg_register(struct lbs_private + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + wdev->wiphy->reg_notifier = lbs_reg_notifier; + +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 ac58dba..dd82ce5 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. */ +-@@ -3302,8 +3302,8 @@ static int b43_chip_init(struct b43_wlde ++@@ -3300,8 +3300,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); +-@@ -4003,7 +4003,6 @@ static int b43_op_config(struct ieee8021 ++@@ -4001,7 +4001,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); +-@@ -4046,11 +4045,9 @@ static int b43_op_config(struct ieee8021 ++@@ -4044,11 +4043,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) { +-@@ -5213,6 +5210,47 @@ static int b43_op_get_survey(struct ieee ++@@ -5209,6 +5206,47 @@ static int b43_op_get_survey(struct ieee + return 0; + } + +@@ -90,7 +90,7 @@ + static const struct ieee80211_ops b43_hw_ops = { + .tx = b43_op_tx, + .conf_tx = b43_op_conf_tx, +-@@ -5234,6 +5272,8 @@ static const struct ieee80211_ops b43_hw ++@@ -5230,6 +5268,8 @@ static const struct ieee80211_ops b43_hw + .sw_scan_complete = b43_op_sw_scan_complete_notifier, + .get_survey = b43_op_get_survey, + .rfkill_poll = b43_rfkill_poll, +@@ -99,7 +99,7 @@ + }; + + /* Hard-reset the chip. Do not call this directly. +-@@ -5542,6 +5582,8 @@ static int b43_one_core_attach(struct b4 ++@@ -5538,6 +5578,8 @@ static int b43_one_core_attach(struct b4 + if (!wldev) + goto out; + +@@ -108,7 +108,7 @@ + wldev->use_pio = b43_modparam_pio; + wldev->dev = dev; + wldev->wl = wl; +-@@ -5632,6 +5674,9 @@ static struct b43_wl *b43_wireless_init( ++@@ -5628,6 +5670,9 @@ static struct b43_wl *b43_wireless_init( + + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; + +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 685a5f9..f9799ce 100644 +--- 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,7 +13,7 @@ Signed-off-by: Rafał Miłecki + + --- a/drivers/net/wireless/brcm80211/brcmfmac/core.c + +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c +-@@ -1213,6 +1213,7 @@ static int __init brcmfmac_module_init(v ++@@ -1189,6 +1189,7 @@ static int __init brcmfmac_module_init(v + #endif + if (!schedule_work(&brcmf_driver_work)) + return -EBUSY; +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 1cba2b3..5fdfa37 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/brcm80211/brcmfmac/cfg80211.c + +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +-@@ -691,9 +691,37 @@ static struct wireless_dev *brcmf_cfg802 ++@@ -692,9 +692,37 @@ static struct wireless_dev *brcmf_cfg802 + u32 *flags, + struct vif_params *params) + { +diff --git a/package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch b/package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch +deleted file mode 100644 +index 856dea8..0000000 +--- a/package/kernel/mac80211/patches/900-wlcore-Add-support-for-DT-platform-data.patch ++++ /dev/null +@@ -1,139 +0,0 @@ +-When running with DT, we no longer have a board file that can set up the +-platform data for wlcore. Allow this data to be passed from DT. +- +-Since some platforms use a gpio-irq, add support for passing either the +-irq number or the gpio number. For the latter case, the driver will +-request the gpio and convert it to the irq number. If an irq is +-specified, it'll be used as is. +- +-[Arik - the pdev_data pointer does not belong to us and is freed when +-the device is released. Dereference to our private data first.] +- +-Signed-off-by: Ido Yariv +-Signed-off-by: Arik Nemtsov +---- +- drivers/net/wireless/ti/wlcore/sdio.c | 71 ++++++++++++++++++++++++++++++++--- +- include/linux/wl12xx.h | 3 +- +- 2 files changed, 67 insertions(+), 7 deletions(-) +- +---- a/drivers/net/wireless/ti/wlcore/sdio.c +-+++ b/drivers/net/wireless/ti/wlcore/sdio.c +-@@ -34,6 +34,7 @@ +- #include +- #include +- #include +-+#include +- +- #include "wlcore.h" +- #include "wl12xx_80211.h" +-@@ -214,6 +215,61 @@ static struct wl1271_if_operations sdio_ +- .set_block_size = wl1271_sdio_set_block_size, +- }; +- +-+static const struct of_device_id wlcore_of_match[] = { +-+ { +-+ .compatible = "wlcore", +-+ }, +-+ {} +-+}; +-+MODULE_DEVICE_TABLE(of, wlcore_of_match); +-+ +-+static struct wl12xx_platform_data *get_platform_data(struct device *dev) +-+{ +-+ struct wl12xx_platform_data *pdata; +-+ struct device_node *np; +-+ u32 gpio; +-+ +-+ pdata = wl12xx_get_platform_data(); +-+ if (!IS_ERR(pdata)) +-+ return kmemdup(pdata, sizeof(*pdata), GFP_KERNEL); +-+ +-+ np = of_find_matching_node(NULL, wlcore_of_match); +-+ if (!np) { +-+ dev_err(dev, "No platform data set\n"); +-+ return NULL; +-+ } +-+ +-+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); +-+ if (!pdata) { +-+ dev_err(dev, "Can't allocate platform data\n"); +-+ return NULL; +-+ } +-+ +-+ if (of_property_read_u32(np, "irq", &pdata->irq)) { +-+ if (!of_property_read_u32(np, "gpio", &gpio) && +-+ !gpio_request_one(gpio, GPIOF_IN, "wlcore_irq")) { +-+ pdata->gpio = gpio; +-+ pdata->irq = gpio_to_irq(gpio); +-+ } +-+ } +-+ +-+ /* Optional fields */ +-+ pdata->use_eeprom = of_property_read_bool(np, "use-eeprom"); +-+ of_property_read_u32(np, "board-ref-clock", &pdata->board_ref_clock); +-+ of_property_read_u32(np, "board-tcxo-clock", &pdata->board_tcxo_clock); +-+ of_property_read_u32(np, "platform-quirks", &pdata->platform_quirks); +-+ +-+ return pdata; +-+} +-+ +-+static void del_platform_data(struct wl12xx_platform_data *pdata) +-+{ +-+ if (pdata->gpio) +-+ gpio_free(pdata->gpio); +-+ +-+ kfree(pdata); +-+} +-+ +- static int wl1271_probe(struct sdio_func *func, +- const struct sdio_device_id *id) +- { +-@@ -245,10 +301,10 @@ static int wl1271_probe(struct sdio_func +- /* Use block mode for transferring over one block size of data */ +- func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; +- +-- pdev_data.pdata = wl12xx_get_platform_data(); +-- if (IS_ERR(pdev_data.pdata)) { +-- ret = PTR_ERR(pdev_data.pdata); +-- dev_err(glue->dev, "missing wlan platform data: %d\n", ret); +-+ pdev_data.pdata = get_platform_data(&func->dev); +-+ if (!pdev_data.pdata) { +-+ ret = -EINVAL; +-+ dev_err(glue->dev, "missing wlan platform data\n"); +- goto out_free_glue; +- } +- +-@@ -279,7 +335,7 @@ static int wl1271_probe(struct sdio_func +- if (!glue->core) { +- dev_err(glue->dev, "can't allocate platform_device"); +- ret = -ENOMEM; +-- goto out_free_glue; +-+ goto out_free_pdata; +- } +- +- glue->core->dev.parent = &func->dev; +-@@ -313,6 +369,9 @@ static int wl1271_probe(struct sdio_func +- out_dev_put: +- platform_device_put(glue->core); +- +-+out_free_pdata: +-+ del_platform_data(pdev_data->pdata); +-+ +- out_free_glue: +- kfree(glue); +- +-@@ -323,11 +382,14 @@ out: +- static void wl1271_remove(struct sdio_func *func) +- { +- struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); +-+ struct wlcore_platdev_data *pdev_data = glue->core->dev.platform_data; +-+ struct wl12xx_platform_data *pdata = pdev_data->pdata; +- +- /* Undo decrement done above in wl1271_probe */ +- pm_runtime_get_noresume(&func->dev); +- +- platform_device_unregister(glue->core); +-+ del_platform_data(pdata); +- kfree(glue); +- } +- +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 501910f..b0536ce 100644 +--- a/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch ++++ b/package/kernel/mac80211/patches/910-01-add-support-for-mt7620.patch +@@ -210,7 +210,7 @@ + case RT5592: + *txwi_size = TXWI_DESC_SIZE_5WORDS; + *rxwi_size = RXWI_DESC_SIZE_6WORDS; +-@@ -3326,6 +3399,312 @@ static void rt2800_config_channel_rf55xx ++@@ -3302,6 +3375,312 @@ static void rt2800_config_channel_rf55xx + rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F); + } + +@@ -258,6 +258,7 @@ + + u32 mac_sys_ctrl, mac_status; + + u32 tx_pin = 0x00150F0F; + + struct hw_mode_spec *spec = &rt2x00dev->spec; +++ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + + + + /* Frequeny plan setting */ + + /* +@@ -383,7 +384,6 @@ + + rfcsr &= (~0x4); + + rt2800_rfcsr_write(rt2x00dev, 28, rfcsr); + + +-+ struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + + /*if (bScan == FALSE)*/ + + if (conf_is_ht40(conf)) { + + txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40, +@@ -523,7 +523,7 @@ + static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev, + const unsigned int word, + const u8 value) +-@@ -3482,7 +3861,7 @@ static void rt2800_config_channel(struct ++@@ -3458,7 +3837,7 @@ static void rt2800_config_channel(struct + struct channel_info *info) + { + u32 reg; +@@ -532,7 +532,7 @@ + u8 bbp, rfcsr; + + info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, +-@@ -3536,6 +3915,9 @@ static void rt2800_config_channel(struct ++@@ -3512,6 +3891,9 @@ static void rt2800_config_channel(struct + case RF5592: + rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info); + break; +@@ -542,7 +542,7 @@ + default: + rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); + } +-@@ -3638,7 +4020,7 @@ static void rt2800_config_channel(struct ++@@ -3614,7 +3996,7 @@ static void rt2800_config_channel(struct + else if (rt2x00_rt(rt2x00dev, RT3593) || + rt2x00_rt(rt2x00dev, RT3883)) + rt2800_bbp_write(rt2x00dev, 82, 0x82); +@@ -551,7 +551,7 @@ + rt2800_bbp_write(rt2x00dev, 82, 0xf2); + + if (rt2x00_rt(rt2x00dev, RT3593) || +-@@ -3660,7 +4042,7 @@ static void rt2800_config_channel(struct ++@@ -3636,7 +4018,7 @@ static void rt2800_config_channel(struct + if (rt2x00_rt(rt2x00dev, RT3572)) + rt2800_rfcsr_write(rt2x00dev, 8, 0); + +@@ -560,7 +560,7 @@ + + switch (rt2x00dev->default_ant.tx_chain_num) { + case 3: +-@@ -3709,6 +4091,7 @@ static void rt2800_config_channel(struct ++@@ -3685,6 +4067,7 @@ static void rt2800_config_channel(struct + + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); + rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); +@@ -568,7 +568,7 @@ + + rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + +-@@ -4725,6 +5108,14 @@ void rt2800_vco_calibration(struct rt2x0 ++@@ -4701,6 +5084,14 @@ void rt2800_vco_calibration(struct rt2x0 + rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); + rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); + break; +@@ -583,7 +583,7 @@ + default: + return; + } +-@@ -5125,9 +5516,42 @@ static int rt2800_init_registers(struct ++@@ -5101,9 +5492,42 @@ static int rt2800_init_registers(struct + } else if (rt2x00_rt(rt2x00dev, RT5390) || + rt2x00_rt(rt2x00dev, RT5392) || + rt2x00_rt(rt2x00dev, RT5592)) { +@@ -629,7 +629,7 @@ + } else if (rt2x00_rt(rt2x00dev, RT5350)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); + } else { +-@@ -6159,6 +6583,225 @@ static void rt2800_init_bbp_5592(struct ++@@ -6135,6 +6559,225 @@ static void rt2800_init_bbp_5592(struct + rt2800_bbp_write(rt2x00dev, 103, 0xc0); + } + +@@ -855,7 +855,7 @@ + static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) + { + unsigned int i; +-@@ -6201,7 +6844,10 @@ static void rt2800_init_bbp(struct rt2x0 ++@@ -6177,7 +6820,10 @@ static void rt2800_init_bbp(struct rt2x0 + return; + case RT5390: + case RT5392: +@@ -867,7 +867,7 @@ + break; + case RT5592: + rt2800_init_bbp_5592(rt2x00dev); +-@@ -7415,6 +8061,295 @@ static void rt2800_init_rfcsr_5592(struc ++@@ -7391,6 +8037,296 @@ static void rt2800_init_rfcsr_5592(struc + rt2800_led_open_drain_enable(rt2x00dev); + } + +@@ -875,6 +875,8 @@ + +{ + + u16 freq; + + u8 rfvalue; +++ struct hw_mode_spec *spec = &rt2x00dev->spec; +++ + + /* Initialize RF central register to default value */ + + rt2800_rfcsr_write(rt2x00dev, 0, 0x02); + + rt2800_rfcsr_write(rt2x00dev, 1, 0x03); +@@ -921,7 +923,6 @@ + + rt2800_rfcsr_write(rt2x00dev, 42, 0x5B); + + rt2800_rfcsr_write(rt2x00dev, 43, 0x00); + + +-+ struct hw_mode_spec *spec = &rt2x00dev->spec; + + rt2800_rfcsr_write(rt2x00dev, 11, 0x21); + + if (spec->clk_is_20mhz) + + rt2800_rfcsr_write(rt2x00dev, 13, 0x03); +@@ -1163,7 +1164,7 @@ + static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) + { + if (rt2800_is_305x_soc(rt2x00dev)) { +-@@ -7450,7 +8385,10 @@ static void rt2800_init_rfcsr(struct rt2 ++@@ -7426,7 +8362,10 @@ static void rt2800_init_rfcsr(struct rt2 + rt2800_init_rfcsr_5350(rt2x00dev); + break; + case RT5390: +@@ -1175,7 +1176,7 @@ + break; + case RT5392: + rt2800_init_rfcsr_5392(rt2x00dev); +-@@ -7882,6 +8820,7 @@ static int rt2800_init_eeprom(struct rt2 ++@@ -7858,6 +8797,7 @@ static int rt2800_init_eeprom(struct rt2 + case RF5390: + case RF5392: + case RF5592: +@@ -1183,7 +1184,7 @@ + break; + default: + rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n", +-@@ -8448,6 +9387,7 @@ static int rt2800_probe_hw_mode(struct r ++@@ -8422,6 +9362,7 @@ static int rt2800_probe_hw_mode(struct r + case RF5372: + case RF5390: + case RF5392: +@@ -1191,7 +1192,7 @@ + spec->num_channels = 14; + if (spec->clk_is_20mhz) + spec->channels = rf_vals_xtal20mhz_3x; +-@@ -8588,6 +9528,7 @@ static int rt2800_probe_hw_mode(struct r ++@@ -8562,6 +9503,7 @@ static int rt2800_probe_hw_mode(struct r + case RF5372: + case RF5390: + case RF5392: +diff --git a/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch b/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch +deleted file mode 100644 +index 4c04d4f..0000000 +--- a/package/kernel/mac80211/patches/920-ath10k_allow_fallback_to_board_bin_on_empty_otp_stream.patch ++++ /dev/null +@@ -1,20 +0,0 @@ +---- a/drivers/net/wireless/ath/ath10k/core.c +-+++ b/drivers/net/wireless/ath/ath10k/core.c +-@@ -387,9 +387,14 @@ static int ath10k_download_and_run_otp(s +- +- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); +- +-- if (!skip_otp && result != 0) { +-- ath10k_err(ar, "otp calibration failed: %d", result); +-- return -EINVAL; +-+ if (!skip_otp) { +-+ if (result == 2) { +-+ ath10k_warn(ar, "otp stream is empty, using board.bin contents"); +-+ return 0; +-+ } else if (result != 0) { +-+ ath10k_err(ar, "otp calibration failed: %d", result); +-+ return -EINVAL; +-+ } +- } +- +- return 0; +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 eed3814..93196e1 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 + + --- a/drivers/net/wireless/ath/ath10k/core.c + +++ b/drivers/net/wireless/ath/ath10k/core.c +-@@ -1323,6 +1323,16 @@ int ath10k_core_register(struct ath10k * ++@@ -1520,6 +1520,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 8003f86..34910a0 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 +-@@ -5416,6 +5416,21 @@ struct ath10k_vif *ath10k_get_arvif(stru ++@@ -6804,6 +6804,21 @@ struct ath10k_vif *ath10k_get_arvif(stru + return arvif_iter.arvif; + } + +@@ -22,7 +22,7 @@ + int ath10k_mac_register(struct ath10k *ar) + { + static const u32 cipher_suites[] = { +-@@ -5590,6 +5605,12 @@ int ath10k_mac_register(struct ath10k *a ++@@ -7025,6 +7040,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); + +diff --git a/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch +new file mode 100644 +index 0000000..75d8212 +--- /dev/null ++++ b/package/kernel/mac80211/patches/940-mwl8k_init_devices_synchronously.patch +@@ -0,0 +1,20 @@ ++--- a/drivers/net/wireless/mwl8k.c +++++ b/drivers/net/wireless/mwl8k.c ++@@ -6261,6 +6261,8 @@ static int mwl8k_probe(struct pci_dev *p ++ ++ priv->running_bsses = 0; ++ +++ wait_for_completion(&priv->firmware_loading_complete); +++ ++ return rc; ++ ++ err_stop_firmware: ++@@ -6294,8 +6296,6 @@ static void mwl8k_remove(struct pci_dev ++ return; ++ priv = hw->priv; ++ ++- wait_for_completion(&priv->firmware_loading_complete); ++- ++ if (priv->fw_state == FW_STATE_ERROR) { ++ mwl8k_hw_reset(priv); ++ goto unmap; diff --git a/patches/openwrt/0022-hostapd-work-around-unconditional-libopenssl-build-dependency.patch b/patches/openwrt/0022-hostapd-work-around-unconditional-libopenssl-build-dependency.patch index 0d51e607..289a94a1 100644 --- a/patches/openwrt/0022-hostapd-work-around-unconditional-libopenssl-build-dependency.patch +++ b/patches/openwrt/0022-hostapd-work-around-unconditional-libopenssl-build-dependency.patch @@ -8,7 +8,7 @@ not only wpad-mesh. Fix this by applying the same workaround as in ustream-ssl. diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile -index 3dff7b4..d86bb43 100644 +index c16cb11..c39b6b4 100644 --- a/package/network/services/hostapd/Makefile +++ b/package/network/services/hostapd/Makefile @@ -177,7 +177,7 @@ endef diff --git a/patches/openwrt/0005-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch b/patches/openwrt/0023-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch similarity index 63% rename from patches/openwrt/0005-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch rename to patches/openwrt/0023-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch index 9d937c29..1c700253 100644 --- a/patches/openwrt/0005-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch +++ b/patches/openwrt/0023-ath10k-add-Candelatech-community-firmware-as-an-additional-choice.patch @@ -3,10 +3,10 @@ Date: Tue, 10 Mar 2015 13:17:14 +0100 Subject: ath10k: add Candelatech community firmware as an additional choice diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile -index a1eedce..1c0aebe 100644 +index 04dfd3b..5d77ebf 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile -@@ -604,6 +604,14 @@ This module adds support for wireless adapters based on +@@ -603,6 +603,14 @@ This module adds support for wireless adapters based on Atheros USB AR9271 and AR7010 family of chipsets. endef @@ -21,10 +21,10 @@ index a1eedce..1c0aebe 100644 define KernelPackage/ath10k $(call KernelPackage/mac80211/Default) TITLE:=Atheros 802.11ac wireless cards support -@@ -624,21 +632,37 @@ endef +@@ -622,6 +630,17 @@ endef + define KernelPackage/ath10k/config if PACKAGE_kmod-ath10k - + choice + prompt "ath10k firmware flavour" + default ATH10K_AP_FW @@ -36,60 +36,39 @@ index a1eedce..1c0aebe 100644 + help + Use the ath10k firmware optimized for access point operation. + Supports only AP mode, will crash in IBSS (ad-hoc) mode. -+ - config ATH10K_STA_FW - bool "Firmware optimized for STA operation" -- default n - help - Use the ath10k firmware optimized for wireless client instead -- of access point operation. -+ of access point operation. Might be unstable in AP mode. -+ + + config ATH10K_API2_FW + bool "Firmware optimized for AP operation (v10.1 / API v2)" +@@ -630,6 +649,13 @@ define KernelPackage/ath10k/config + Use the ath10k firmware from the 10.1 SDK using API v2 optimized + for access point operation if the default firmware keeps crashing. + + config ATH10K_CT_COMMUNITY_FW + bool "Firmware by Candela Technologies (community version)" + help + Supports both AP and IBSS (ad-hoc) mode. Doesn't support + encryption when using multiple VIFs. - - config ATH10K_API2_FW - bool "Firmware optimized for AP operation (v10.1 / API v2)" -- default n -- depends on !ATH10K_STA_FW - help - Use the ath10k firmware from the 10.1 SDK using API v2 optimized - for access point operation if the default firmware keeps crashing. - ++ + endchoice endif endef -@@ -1866,18 +1890,25 @@ define KernelPackage/ath10k/install - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/ath10k/QCA988X/hw2.0/board.bin \ - $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ -+ifeq ($(CONFIG_ATH10K_AP_FW),y) -+ $(INSTALL_DATA) \ -+ $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/firmware-4.bin_10.2.4.45 \ -+ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-4.bin -+endif - ifeq ($(CONFIG_ATH10K_STA_FW),y) - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/main/firmware-2.bin_999.999.0.636 \ - $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin --else ifeq ($(CONFIG_ATH10K_API2_FW),y) -+endif -+ifeq ($(CONFIG_ATH10K_API2_FW),y) +@@ -1885,11 +1911,17 @@ ifeq ($(CONFIG_ATH10K_API2_FW),y) $(INSTALL_DATA) \ $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.1/firmware-2.bin_10.1.467.2-1 \ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin -else +endif -+ifeq ($(CONFIG_ATH10K_CT_COMMUNITY_FW),y) ++ifeq ($(CONFIG_ATH10K_AP_FW),y) $(INSTALL_DATA) \ -- $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/firmware-4.bin_10.2.4.45 \ -- $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-4.bin + $(PKG_BUILD_DIR)/$(PKG_ATH10K_LINUX_FIRMWARE_SUBDIR)/10.2.4/untested/firmware-5.bin_10.2.4.70-2 \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-5.bin + endif ++ifeq ($(CONFIG_ATH10K_CT_COMMUNITY_FW),y) ++ $(INSTALL_DATA) \ + $(DL_DIR)/$(ATH10K_CT_COMMUNITY_FW) \ + $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-2.bin - endif ++endif endef + define KernelPackage/mt7601u/install