PKG_NAME:=mac80211
-PKG_VERSION:=2017-11-01
-PKG_RELEASE:=9
+PKG_VERSION:=v4.18.5
+PKG_RELEASE:=1
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
-PKG_HASH:=8437ab7886b988c8152e7a4db30b7f41009e49a3b2cb863edd05da1ecd7eb05a
+PKG_HASH:=9c13660e98b9397260266f98c9db76bdad2b48462cb376b5862dfbd18369edf2
PKG_SOURCE:=backports-$(PKG_VERSION).tar.xz
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/backports-$(PKG_VERSION)
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 +mt7601u-firmware
+ DEPENDS+= @BROKEN +kmod-mac80211 +@DRIVER_11N_SUPPORT @USB_SUPPORT +kmod-usb-core +mt7601u-firmware
FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/mediatek/mt7601u/mt7601u.ko
AUTOLOAD:=$(call AutoProbe,mt7601u)
endef
endif
endif
+define Build/Patch
+ $(if $(QUILT),rm -rf $(PKG_BUILD_DIR)/patches; mkdir -p $(PKG_BUILD_DIR)/patches)
+ $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/build,build/)
+ $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/subsys,subsys/)
+ $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath,ath/)
+ $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rt2x00,rt2x00/)
+ $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/)
+ $(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/)
+ $(if $(QUILT),touch $(PKG_BUILD_DIR)/.quilt_used)
+endef
+
+define Quilt/Refresh/Package
+ $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/build,build/)
+ $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/subsys,subsys/)
+ $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/ath,ath/)
+ $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/rt2x00,rt2x00/)
+ $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/mwl,mwl/)
+ $(call Quilt/RefreshDir,$(PKG_BUILD_DIR),$(PATCH_DIR)/brcm,brcm/)
+endef
+
define Build/Compile
$(SH_FUNC) var2file "$(call shvar,mac80211_config)" $(PKG_BUILD_DIR)/.config
$(MAKE) $(MAKE_OPTS) allnoconfig
+++ /dev/null
---- a/kconf/Makefile
-+++ b/kconf/Makefile
-@@ -1,9 +1,9 @@
--CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
-+CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS
-
- LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o
-
- conf: conf.o zconf.tab.o
--mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE
-+mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags)
- mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
- mconf: CFLAGS += $(mconf_CFLAGS)
-
+++ /dev/null
---- a/Makefile
-+++ b/Makefile
-@@ -5,7 +5,7 @@
- ifeq ($(KERNELRELEASE),)
-
- MAKEFLAGS += --no-print-directory
--SHELL := /bin/bash
-+SHELL := /usr/bin/env bash
- BACKPORT_DIR := $(shell pwd)
-
- KMODDIR ?= updates
-@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/
- KERNEL_CONFIG := $(KLIB_BUILD)/.config
- KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile
- CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//')
-+STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5)
-
- export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG
-
-@@ -36,7 +37,8 @@ mrproper:
- @rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel
- @rm -f backport-include/backport/autoconf.h
-
--.DEFAULT:
-+.SILENT: $(STAMP_KERNEL_CONFIG)
-+$(STAMP_KERNEL_CONFIG):
- @set -e ; test -f local-symbols || ( \
- echo "/--------------" ;\
- echo "| You shouldn't run make in the backports tree, but only in" ;\
-@@ -60,57 +62,61 @@ mrproper:
- echo "| (that isn't currently running.)" ;\
- echo "\\--" ;\
- false)
-- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\
-- then \
-- echo -n "Generating local configuration database from kernel ..." ;\
-- grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
-- while read l ; do \
-- if [ "$${l:0:7}" != "CONFIG_" ] ; then \
-- continue ;\
-- fi ;\
-- l=$${l:7} ;\
-- n=$${l%%=*} ;\
-- v=$${l#*=} ;\
-- if [ "$$v" = "m" ] ; then \
-- echo config $$n ;\
-- echo ' tristate' ;\
-- elif [ "$$v" = "y" ] ; then \
-- echo config $$n ;\
-- echo ' bool' ;\
-- else \
-- continue ;\
-- fi ;\
-- echo " default $$v" ;\
-- echo "" ;\
-- done \
-- ) > Kconfig.kernel ;\
-- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
-- 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 19 | sed 's/^/3./')" ;\
-- kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
-- print=0 ;\
-- for v in $$kvers ; do \
-- if [ "$$print" = "1" ] ; then \
-- echo config KERNEL_$$(echo $$v | tr . _) ;\
-- echo " def_bool y" ;\
-- fi ;\
-- if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
-- done > Kconfig.versions ;\
-- # RHEL as well, sadly we need to grep for it ;\
-- RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
-- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
-- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
-- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
-- for v in $$(seq 0 $$RHEL_MINOR) ; do \
-- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
-- echo " def_bool y" ;\
-- done >> Kconfig.versions ;\
-- echo " done." ;\
-- fi ;\
-- echo "$(CONFIG_MD5)" > .kernel_config_md5
-+ @rm -f .kernel_config_md5_*
-+ @touch $@
-+
-+Kconfig.kernel: $(STAMP_KERNEL_CONFIG) local-symbols
-+ @printf "Generating local configuration database from kernel ..."
-+ @grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
-+ while read l ; do \
-+ if [ "$${l:0:7}" != "CONFIG_" ] ; then \
-+ continue ;\
-+ fi ;\
-+ l=$${l:7} ;\
-+ n=$${l%%=*} ;\
-+ v=$${l#*=} ;\
-+ if [ "$$v" = "m" ] ; then \
-+ echo config $$n ;\
-+ echo ' tristate' ;\
-+ elif [ "$$v" = "y" ] ; then \
-+ echo config $$n ;\
-+ echo ' bool' ;\
-+ else \
-+ continue ;\
-+ fi ;\
-+ echo " default $$v" ;\
-+ echo "" ;\
-+ done \
-+ ) > $@
-+ @echo " done."
-+
-+Kconfig.versions: Kconfig.kernel
-+ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
-+ 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 19 | sed 's/^/3./')" ;\
-+ kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
-+ print=0 ;\
-+ for v in $$kvers ; do \
-+ if [ "$$print" = "1" ] ; then \
-+ echo config KERNEL_$$(echo $$v | tr . _) ;\
-+ echo " def_bool y" ;\
-+ fi ;\
-+ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
-+ done > $@
-+ @RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
-+ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
-+ RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
-+ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
-+ for v in $$(seq 0 $$RHEL_MINOR) ; do \
-+ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
-+ echo " def_bool y" ;\
-+ done >> $@
-+
-+.DEFAULT:
-+ @$(MAKE) Kconfig.versions
- @$(MAKE) -f Makefile.real "$@"
-
- .PHONY: defconfig-help
---- a/Makefile.real
-+++ b/Makefile.real
-@@ -59,7 +59,7 @@ defconfig-%::
-
- backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
- @$(MAKE) oldconfig
-- @echo -n "Building backport-include/backport/autoconf.h ..."
-+ @printf "Building backport-include/backport/autoconf.h ..."
- @grep -f local-symbols .config | ( \
- echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\
- echo "#define COMPAT_AUTOCONF_INCLUDED" ;\
-@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c
- esac ;\
- done ;\
- echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\
-- ) > backport-include/backport/autoconf.h
-+ ) > $@.new
-+ @if cmp -s $@ $@.new; then \
-+ rm -f $@.new; \
-+ else \
-+ mv $@.new $@; \
-+ fi
- @echo " done."
-
- .PHONY: modules
+++ /dev/null
---- a/kconf/conf.c
-+++ b/kconf/conf.c
-@@ -594,40 +594,12 @@ int main(int ac, char **av)
- case oldconfig:
- case listnewconfig:
- case olddefconfig:
-- conf_read(NULL);
-- break;
- case allnoconfig:
- case allyesconfig:
- case allmodconfig:
- case alldefconfig:
- case randconfig:
-- name = getenv("KCONFIG_ALLCONFIG");
-- if (!name)
-- break;
-- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
-- if (conf_read_simple(name, S_DEF_USER)) {
-- fprintf(stderr,
-- _("*** Can't read seed configuration \"%s\"!\n"),
-- name);
-- exit(1);
-- }
-- break;
-- }
-- switch (input_mode) {
-- case allnoconfig: name = "allno.config"; break;
-- case allyesconfig: name = "allyes.config"; break;
-- case allmodconfig: name = "allmod.config"; break;
-- case alldefconfig: name = "alldef.config"; break;
-- case randconfig: name = "allrandom.config"; break;
-- default: break;
-- }
-- if (conf_read_simple(name, S_DEF_USER) &&
-- conf_read_simple("all.config", S_DEF_USER)) {
-- fprintf(stderr,
-- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
-- name);
-- exit(1);
-- }
-+ conf_read(NULL);
- break;
- default:
- break;
---- a/kconf/confdata.c
-+++ b/kconf/confdata.c
-@@ -1170,6 +1170,8 @@ bool conf_set_all_new_symbols(enum conf_
- }
- bool has_changed = false;
-
-+ sym_clear_all_valid();
-+
- for_all_symbols(i, sym) {
- if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
- continue;
-@@ -1213,8 +1215,6 @@ bool conf_set_all_new_symbols(enum conf_
-
- }
-
-- sym_clear_all_valid();
--
- /*
- * We have different type of choice blocks.
- * If curr.tri equals to mod then we can select several
+++ /dev/null
---- a/compat/main.c
-+++ b/compat/main.c
-@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL");
- #error "You need a CPTCFG_VERSION"
- #endif
-
--static char *backported_kernel_name = CPTCFG_KERNEL_NAME;
--
--module_param(backported_kernel_name, charp, 0400);
--MODULE_PARM_DESC(backported_kernel_name,
-- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")");
--
--#ifdef BACKPORTS_GIT_TRACKED
--static char *backports_tracker_id = BACKPORTS_GIT_TRACKED;
--module_param(backports_tracker_id, charp, 0400);
--MODULE_PARM_DESC(backports_tracker_id,
-- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")");
--#else
--static char *backported_kernel_version = CPTCFG_KERNEL_VERSION;
--static char *backports_version = CPTCFG_VERSION;
--
--module_param(backported_kernel_version, charp, 0400);
--MODULE_PARM_DESC(backported_kernel_version,
-- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")");
--
--module_param(backports_version, charp, 0400);
--MODULE_PARM_DESC(backports_version,
-- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")");
--
--#endif
--
- void backport_dependency_symbol(void)
- {
- }
+++ /dev/null
---- a/backport-include/linux/kconfig.h
-+++ b/backport-include/linux/kconfig.h
-@@ -5,6 +5,8 @@
- #include_next <linux/kconfig.h>
- #endif
-
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
-+
- #ifndef __ARG_PLACEHOLDER_1
- #define __ARG_PLACEHOLDER_1 0,
- #define config_enabled(cfg) _config_enabled(cfg)
-@@ -16,6 +18,7 @@
- * 3.1 - 3.3 had a broken version of this, so undef
- * (they didn't have __ARG_PLACEHOLDER_1)
- */
-+
- #undef IS_ENABLED
- #define IS_ENABLED(option) \
- (config_enabled(option) || config_enabled(option##_MODULE))
-@@ -31,6 +34,8 @@
- #undef IS_BUILTIN
- #define IS_BUILTIN(option) config_enabled(option)
-
-+#endif
-+
- #ifndef IS_REACHABLE
- /*
- * IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled
+++ /dev/null
---- a/compat/Makefile
-+++ b/compat/Makefile
-@@ -70,8 +70,6 @@ quiet_cmd_build_OID_registry = GEN $
- cmd_build_OID_registry = perl $(src)/build_OID_registry $< $@
- compat-$(CPTCFG_BPAUTO_ASN1_DECODER) += lib-asn1_decoder.o
- compat-$(CPTCFG_BPAUTO_BUILD_SYSTEM_DATA_VERIFICATION) += lib-oid_registry.o
--skcipher-objs += crypto-skcipher.o
--obj-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += skcipher.o
- compat-$(CPTCFG_BPAUTO_RHASHTABLE) += lib-rhashtable.o
- cordic-objs += lib-cordic.o
- obj-$(CPTCFG_BPAUTO_BUILD_CORDIC) += cordic.o
+++ /dev/null
---- a/compat/backport-4.12.c
-+++ b/compat/backport-4.12.c
-@@ -225,6 +225,7 @@ int bp_extack_genl_register_family(struc
-
- /* copy this since the family might access it directly */
- family->attrbuf = copy->family.attrbuf;
-+ family->mcgrp_offset = copy->family.mcgrp_offset;
-
- mutex_lock(&copies_mutex);
- list_add_tail(©->list, &copies_list);
+++ /dev/null
---- a/backport-include/linux/verification.h
-+++ b/backport-include/linux/verification.h
-@@ -1,7 +1,7 @@
- #ifndef __BP_VERIFICATION_H
- #define __BP_VERIFICATION_H
- #include <linux/version.h>
--#ifndef CPTCFG_BPAUTO_BUILD_SYSTEM_DATA_VERIFICATION
-+#if LINUX_VERSION_IS_GEQ(4,7,0) && !defined(CPTCFG_BPAUTO_BUILD_SYSTEM_DATA_VERIFICATION)
- #include_next <linux/verification.h>
- #else
- #include <linux/key.h>
+++ /dev/null
---- a/compat/backport-4.12.c
-+++ b/compat/backport-4.12.c
-@@ -224,6 +224,7 @@ int bp_extack_genl_register_family(struc
- }
-
- /* copy this since the family might access it directly */
-+ family->id = copy->family.id;
- family->attrbuf = copy->family.attrbuf;
- family->mcgrp_offset = copy->family.mcgrp_offset;
-
+++ /dev/null
---- a/backport-include/linux/rfkill.h
-+++ b/backport-include/linux/rfkill.h
-@@ -2,6 +2,12 @@
- #define __COMPAT_RFKILL_H
- #include <linux/version.h>
-
-+#undef CONFIG_RFKILL
-+#undef CONFIG_RFKILL_FULL
-+#undef CONFIG_RFKILL_LEDS
-+#undef CONFIG_RFKILL_MODULE
-+#undef CONFIG_RFKILL_FULL_MODULE
-+
- #if LINUX_VERSION_IS_GEQ(3,10,0)
- #include_next <linux/rfkill.h>
- #else
+++ /dev/null
---- a/Makefile
-+++ b/Makefile
-@@ -2,7 +2,7 @@
- # Makefile for the output source package
- #
-
--ifeq ($(KERNELRELEASE),)
-+ifeq ($(KERNELVERSION),)
-
- MAKEFLAGS += --no-print-directory
- SHELL := /usr/bin/env bash
+++ /dev/null
---- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
-+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
-@@ -11506,6 +11506,15 @@ static const struct attribute_group ipw_
- .attrs = ipw_sysfs_entries,
- };
-
-+#if LINUX_VERSION_IS_LESS(4,10,0)
-+static int __change_mtu(struct net_device *ndev, int new_mtu){
-+ if (new_mtu < 68 || new_mtu > LIBIPW_DATA_LEN)
-+ return -EINVAL;
-+ ndev->mtu = new_mtu;
-+ return 0;
-+}
-+#endif
-+
- #ifdef CPTCFG_IPW2200_PROMISCUOUS
- static int ipw_prom_open(struct net_device *dev)
- {
-@@ -11554,15 +11563,6 @@ static netdev_tx_t ipw_prom_hard_start_x
- return NETDEV_TX_OK;
- }
-
--#if LINUX_VERSION_IS_LESS(4,10,0)
--static int __change_mtu(struct net_device *ndev, int new_mtu){
-- if (new_mtu < 68 || new_mtu > LIBIPW_DATA_LEN)
-- return -EINVAL;
-- ndev->mtu = new_mtu;
-- return 0;
--}
--#endif
--
- static const struct net_device_ops ipw_prom_netdev_ops = {
- #if LINUX_VERSION_IS_LESS(4,10,0)
- .ndo_change_mtu = __change_mtu,
+++ /dev/null
---- a/drivers/net/wireless/ralink/rt2x00/Kconfig
-+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
-@@ -225,36 +225,37 @@ config RT2800SOC
-
-
- config RT2800_LIB
-- tristate
-+ tristate "RT2800 USB/PCI support"
- depends on m
-
- config RT2800_LIB_MMIO
-- tristate
-+ tristate "RT2800 MMIO support"
- depends on m
- select RT2X00_LIB_MMIO
- select RT2800_LIB
-
- config RT2X00_LIB_MMIO
-- tristate
-+ tristate "RT2x00 MMIO support"
- depends on m
-
- config RT2X00_LIB_PCI
-- tristate
-+ tristate "RT2x00 PCI support"
- depends on m
- select RT2X00_LIB
-
- config RT2X00_LIB_SOC
-- tristate
-+ tristate "RT2x00 SoC support"
-+ depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
- depends on m
- select RT2X00_LIB
-
- config RT2X00_LIB_USB
-- tristate
-+ tristate "RT2x00 USB support"
- depends on m
- select RT2X00_LIB
-
- config RT2X00_LIB
-- tristate
-+ tristate "RT2x00 support"
- depends on m
-
- config RT2X00_LIB_FIRMWARE
+++ /dev/null
---- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
-+++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
-@@ -1,5 +1,5 @@
- config BRCMUTIL
-- tristate
-+ tristate "Broadcom 802.11 driver utility functions"
- depends on m
-
- config BRCMSMAC
+++ /dev/null
---- a/net/wireless/Kconfig
-+++ b/net/wireless/Kconfig
-@@ -181,7 +181,7 @@ config CFG80211_WEXT_EXPORT
- wext compatibility symbols to be exported.
-
- config LIB80211
-- tristate
-+ tristate "lib80211"
- depends on m
- default n
- help
-@@ -191,15 +191,15 @@ config LIB80211
- Drivers should select this themselves if needed.
-
- config LIB80211_CRYPT_WEP
-- tristate
-+ tristate "lib80211 WEP support"
- depends on m
-
- config LIB80211_CRYPT_CCMP
-- tristate
-+ tristate "lib80211 CCMP support"
- depends on m
-
- config LIB80211_CRYPT_TKIP
-- tristate
-+ tristate "lib80211 TKIP support"
- depends on m
-
- config LIB80211_DEBUG
+++ /dev/null
---- a/local-symbols
-+++ b/local-symbols
-@@ -388,45 +388,6 @@ USB_IPHETH=
- USB_SIERRA_NET=
- USB_VL600=
- USB_NET_CH9200=
--SSB_POSSIBLE=
--SSB=
--SSB_SPROM=
--SSB_BLOCKIO=
--SSB_PCIHOST_POSSIBLE=
--SSB_PCIHOST=
--SSB_B43_PCI_BRIDGE=
--SSB_PCMCIAHOST_POSSIBLE=
--SSB_PCMCIAHOST=
--SSB_SDIOHOST_POSSIBLE=
--SSB_SDIOHOST=
--SSB_HOST_SOC=
--SSB_SILENT=
--SSB_DEBUG=
--SSB_SERIAL=
--SSB_DRIVER_PCICORE_POSSIBLE=
--SSB_DRIVER_PCICORE=
--SSB_PCICORE_HOSTMODE=
--SSB_DRIVER_MIPS=
--SSB_SFLASH=
--SSB_EMBEDDED=
--SSB_DRIVER_EXTIF=
--SSB_DRIVER_GIGE=
--SSB_DRIVER_GPIO=
--BCMA_POSSIBLE=
--BCMA=
--BCMA_BLOCKIO=
--BCMA_HOST_PCI_POSSIBLE=
--BCMA_HOST_PCI=
--BCMA_HOST_SOC=
--BCMA_DRIVER_PCI=
--BCMA_DRIVER_PCI_HOSTMODE=
--BCMA_DRIVER_MIPS=
--BCMA_PFLASH=
--BCMA_SFLASH=
--BCMA_NFLASH=
--BCMA_DRIVER_GMAC_CMN=
--BCMA_DRIVER_GPIO=
--BCMA_DEBUG=
- NFC=
- NFC_DIGITAL=
- NFC_NCI=
---- a/drivers/net/wireless/broadcom/b43/main.c
-+++ b/drivers/net/wireless/broadcom/b43/main.c
-@@ -2876,7 +2876,7 @@ static struct ssb_device *b43_ssb_gpio_d
- {
- struct ssb_bus *bus = dev->dev->sdev->bus;
-
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
- return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
- #else
- return bus->chipco.dev;
-@@ -4893,7 +4893,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. */
--#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE)
-+#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
- if (dev->dev->bus_type == B43_BUS_SSB &&
- dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
- dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
---- a/drivers/net/wireless/broadcom/b43legacy/main.c
-+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
-@@ -1937,7 +1937,7 @@ static int b43legacy_gpio_init(struct b4
- if (dev->dev->id.revision >= 2)
- mask |= 0x0010; /* FIXME: This is redundant. */
-
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
- pcidev = bus->pcicore.dev;
- #endif
- gpiodev = bus->chipco.dev ? : pcidev;
-@@ -1956,7 +1956,7 @@ static void b43legacy_gpio_cleanup(struc
- struct ssb_bus *bus = dev->dev->bus;
- struct ssb_device *gpiodev, *pcidev = NULL;
-
--#ifdef CPTCFG_SSB_DRIVER_PCICORE
-+#ifdef CONFIG_SSB_DRIVER_PCICORE
- pcidev = bus->pcicore.dev;
- #endif
- gpiodev = bus->chipco.dev ? : pcidev;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
-@@ -42,6 +42,6 @@ brcmsmac-y := \
- brcms_trace_events.o \
- debug.o
-
--brcmsmac-$(CPTCFG_BCMA_DRIVER_GPIO) += led.o
-+brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
-
- obj-$(CPTCFG_BRCMSMAC) += brcmsmac.o
---- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
-@@ -22,7 +22,7 @@ struct brcms_led {
- bool active_low;
- };
-
--#ifdef CPTCFG_BCMA_DRIVER_GPIO
-+#ifdef CONFIG_BCMA_DRIVER_GPIO
- void brcms_led_unregister(struct brcms_info *wl);
- int brcms_led_register(struct brcms_info *wl);
- #else
---- 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/usb/Kconfig"
-
--source "$BACKPORT_DIR/drivers/ssb/Kconfig"
--source "$BACKPORT_DIR/drivers/bcma/Kconfig"
--
- source "$BACKPORT_DIR/net/nfc/Kconfig"
-
- #source "$BACKPORT_DIR/drivers/media/Kconfig"
---- a/Makefile.kernel
-+++ b/Makefile.kernel
-@@ -42,8 +42,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/
+++ /dev/null
---- a/drivers/net/wireless/ath/Kconfig
-+++ b/drivers/net/wireless/ath/Kconfig
-@@ -1,5 +1,5 @@
- config ATH_COMMON
-- tristate
-+ tristate "ath.ko"
- depends on m
-
- config WLAN_VENDOR_ATH
+++ /dev/null
---- a/drivers/net/wireless/ath/ath10k/Kconfig
-+++ b/drivers/net/wireless/ath/ath10k/Kconfig
-@@ -65,6 +65,12 @@ config ATH10K_TRACING
- ---help---
- Select this to ath10k use tracing infrastructure.
-
-+config ATH10K_THERMAL
-+ bool "Atheros ath10k thermal monitoring support"
-+ depends on THERMAL
-+ ---help---
-+ Select this to ath10k use hwmon for thermal measurement.
-+
- config ATH10K_DFS_CERTIFIED
- bool "Atheros DFS support for certified platforms"
- depends on ATH10K && CFG80211_CERTIFICATION_ONUS
---- a/drivers/net/wireless/ath/ath10k/Makefile
-+++ b/drivers/net/wireless/ath/ath10k/Makefile
-@@ -17,7 +17,7 @@ ath10k_core-y += mac.o \
- ath10k_core-$(CPTCFG_ATH10K_DEBUGFS) += spectral.o
- ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o
- ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
--ath10k_core-$(CONFIG_THERMAL) += thermal.o
-+ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
- ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o
- ath10k_core-$(CONFIG_PM) += wow.o
-
---- a/drivers/net/wireless/ath/ath10k/thermal.h
-+++ b/drivers/net/wireless/ath/ath10k/thermal.h
-@@ -36,7 +36,7 @@ struct ath10k_thermal {
- int temperature;
- };
-
--#if IS_REACHABLE(CONFIG_THERMAL)
-+#if IS_REACHABLE(CPTCFG_ATH10K_THERMAL)
- int ath10k_thermal_register(struct ath10k *ar);
- void ath10k_thermal_unregister(struct ath10k *ar);
- void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
---- a/local-symbols
-+++ b/local-symbols
-@@ -139,6 +139,7 @@ ATH10K_SDIO=
- ATH10K_USB=
- ATH10K_DEBUG=
- ATH10K_DEBUGFS=
-+ATH10K_THERMAL=
- ATH10K_TRACING=
- ATH10K_DFS_CERTIFIED=
- WCN36XX=
+++ /dev/null
-From d06f26c5c8a41f246a9c40862a77a55725cedbd3 Mon Sep 17 00:00:00 2001
-From: Sven Eckelmann <sven.eckelmann@openmesh.com>
-Date: Fri, 8 Dec 2017 11:37:42 +0100
-Subject: ath10k: search DT for qcom,ath10k-calibration-variant
-
-Board Data File (BDF) is loaded upon driver boot-up procedure. The right
-board data file is identified on QCA4019 using bus, bmi-chip-id and
-bmi-board-id.
-
-The problem, however, can occur when the (default) board data file cannot
-fulfill with the vendor requirements and it is necessary to use a different
-board data file.
-
-This problem was solved for SMBIOS by adding a special SMBIOS type 0xF8.
-Something similar has to be provided for systems without SMBIOS but with
-device trees. No solution was specified by QCA and therefore a new one has
-to be found for ath10k.
-
-The device tree requires addition strings to define the variant name
-
- wifi@a000000 {
- status = "okay";
- qcom,ath10k-calibration-variant = "RT-AC58U";
- };
-
- wifi@a800000 {
- status = "okay";
- qcom,ath10k-calibration-variant = "RT-AC58U";
- };
-
-This would create the boarddata identifiers for the board-2.bin search
-
- * bus=ahb,bmi-chip-id=0,bmi-board-id=16,variant=RT-AC58U
- * bus=ahb,bmi-chip-id=0,bmi-board-id=17,variant=RT-AC58U
-
-Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
-Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
----
- drivers/net/wireless/ath/ath10k/core.c | 40 ++++++++++++++++++++++++++++------
- 1 file changed, 33 insertions(+), 7 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/core.c
-+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -860,6 +860,28 @@ static int ath10k_core_check_smbios(stru
- return 0;
- }
-
-+static int ath10k_core_check_dt(struct ath10k *ar)
-+{
-+ struct device_node *node;
-+ const char *variant = NULL;
-+
-+ node = ar->dev->of_node;
-+ if (!node)
-+ return -ENOENT;
-+
-+ of_property_read_string(node, "qcom,ath10k-calibration-variant",
-+ &variant);
-+ if (!variant)
-+ return -ENODATA;
-+
-+ if (strscpy(ar->id.bdf_ext, variant, sizeof(ar->id.bdf_ext)) < 0)
-+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
-+ "bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
-+ variant);
-+
-+ return 0;
-+}
-+
- static int ath10k_download_and_run_otp(struct ath10k *ar)
- {
- u32 result, address = ar->hw_params.patch_load_addr;
-@@ -1231,19 +1253,19 @@ static int ath10k_core_create_board_name
- /* strlen(',variant=') + strlen(ar->id.bdf_ext) */
- char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };
-
-+ if (ar->id.bdf_ext[0] != '\0')
-+ scnprintf(variant, sizeof(variant), ",variant=%s",
-+ ar->id.bdf_ext);
-+
- if (ar->id.bmi_ids_valid) {
- scnprintf(name, name_len,
-- "bus=%s,bmi-chip-id=%d,bmi-board-id=%d",
-+ "bus=%s,bmi-chip-id=%d,bmi-board-id=%d%s",
- ath10k_bus_str(ar->hif.bus),
- ar->id.bmi_chip_id,
-- ar->id.bmi_board_id);
-+ ar->id.bmi_board_id, variant);
- goto out;
- }
-
-- if (ar->id.bdf_ext[0] != '\0')
-- scnprintf(variant, sizeof(variant), ",variant=%s",
-- ar->id.bdf_ext);
--
- scnprintf(name, name_len,
- "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
- ath10k_bus_str(ar->hif.bus),
-@@ -2343,7 +2365,11 @@ static int ath10k_core_probe_fw(struct a
-
- ret = ath10k_core_check_smbios(ar);
- if (ret)
-- ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not set.\n");
-+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "SMBIOS bdf variant name not set.\n");
-+
-+ ret = ath10k_core_check_dt(ar);
-+ if (ret)
-+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "DT bdf variant name not set.\n");
-
- ret = ath10k_core_fetch_board_file(ar);
- if (ret) {
+++ /dev/null
-From 606204bb863fa3b0bb54929d79b4dc46338f9180 Mon Sep 17 00:00:00 2001
-From: Sathishkumar Muruganandam <murugana@codeaurora.org>
-Date: Tue, 27 Mar 2018 11:26:46 +0300
-Subject: [PATCH] ath10k: suppress "Unknown eventid: 36925" warnings
-
-FW has Smart Logging feature enabled by default for detecting failures
-and processing FATAL_CONDITION_EVENTID (36925 - 0x903D) back to host.
-
-Since ath10k doesn't implement the Smart Logging and FATAL CONDITION
-EVENT processing yet, suppressing the unknown event ID warning by moving
-this under ATH10K_DBG_WMI.
-
-Simulated the same issue by having associated STA powered off when
-ping flood was running from AP backbone. This triggerd STA KICKOUT
-in AP followed by FATAL CONDITION event 36925.
-
-Issue was reproduced and verified in below DUT
-------------------------------------------------
-AP mode of OpenWRT QCA9984 running 6.0.8 with FW ver 10.4-3.5.3-00053
-
-Signed-off-by: Sathishkumar Muruganandam <murugana@codeaurora.org>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/wmi.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -5462,6 +5462,7 @@ static void ath10k_wmi_10_4_op_rx(struct
- case WMI_10_4_WOW_WAKEUP_HOST_EVENTID:
- case WMI_10_4_PEER_RATECODE_LIST_EVENTID:
- case WMI_10_4_WDS_PEER_EVENTID:
-+ case WMI_10_4_DEBUG_FATAL_CONDITION_EVENTID:
- ath10k_dbg(ar, ATH10K_DBG_WMI,
- "received event id %d not implemented\n", id);
- break;
+++ /dev/null
-From patchwork Mon May 28 11:25:06 2018
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: Revert "rt2800: use TXOP_BACKOFF for probe frames"
-From: Stanislaw Gruszka <sgruszka@redhat.com>
-X-Patchwork-Id: 10431861
-Message-Id: <1527506706-6488-1-git-send-email-sgruszka@redhat.com>
-To: linux-wireless@vger.kernel.org
-Date: Mon, 28 May 2018 13:25:06 +0200
-
-This reverts commit fb47ada8dc3c30c8e7b415da155742b49536c61e.
-
-In some situations when we set TXOP_BACKOFF, the probe frame is
-not sent at all. What it worse then sending probe frame as part
-of AMPDU and can degrade 11n performance to 11g rates.
-
-Cc: stable@vger.kernel.org
-Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
----
- drivers/net/wireless/ralink/rt2x00/rt2x00queue.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00queue.c
-@@ -372,16 +372,15 @@ static void rt2x00queue_create_tx_descri
-
- /*
- * Determine IFS values
-- * - Use TXOP_BACKOFF for probe and management frames except beacons
-+ * - Use TXOP_BACKOFF for management frames except beacons
- * - Use TXOP_SIFS for fragment bursts
- * - Use TXOP_HTTXOP for everything else
- *
- * Note: rt2800 devices won't use CTS protection (if used)
- * for frames not transmitted with TXOP_HTTXOP
- */
-- if ((ieee80211_is_mgmt(hdr->frame_control) &&
-- !ieee80211_is_beacon(hdr->frame_control)) ||
-- (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE))
-+ if (ieee80211_is_mgmt(hdr->frame_control) &&
-+ !ieee80211_is_beacon(hdr->frame_control))
- txdesc->u.ht.txop = TXOP_BACKOFF;
- else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
- txdesc->u.ht.txop = TXOP_SIFS;
+++ /dev/null
---- a/net/mac80211/Makefile
-+++ b/net/mac80211/Makefile
-@@ -6,7 +6,6 @@ mac80211-y := \
- driver-ops.o \
- sta_info.o \
- wep.o \
-- aead_api.o \
- wpa.o \
- scan.o offchannel.o \
- ht.o agg-tx.o agg-rx.o \
-@@ -16,8 +15,8 @@ mac80211-y := \
- rate.o \
- michael.o \
- tkip.o \
-+ aes_ccm.o \
- aes_cmac.o \
-- aes_gmac.o \
- fils_aead.o \
- cfg.o \
- ethtool.o \
---- a/net/mac80211/aead_api.c
-+++ /dev/null
-@@ -1,115 +0,0 @@
--/*
-- * Copyright 2003-2004, Instant802 Networks, Inc.
-- * Copyright 2005-2006, Devicescape Software, Inc.
-- * Copyright 2014-2015, Qualcomm Atheros, Inc.
-- *
-- * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
-- *
-- * This program is free software; you can redistribute it and/or modify
-- * it under the terms of the GNU General Public License version 2 as
-- * published by the Free Software Foundation.
-- */
--
--#include <linux/kernel.h>
--#include <linux/types.h>
--#include <linux/err.h>
--#include <linux/scatterlist.h>
--#include <crypto/aead.h>
--
--#include "aead_api.h"
--
--int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
-- u8 *data, size_t data_len, u8 *mic)
--{
-- size_t mic_len = crypto_aead_authsize(tfm);
-- struct scatterlist sg[3];
-- struct aead_request *aead_req;
-- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
-- u8 *__aad;
--
-- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
-- if (!aead_req)
-- return -ENOMEM;
--
-- __aad = (u8 *)aead_req + reqsize;
-- memcpy(__aad, aad, aad_len);
--
-- sg_init_table(sg, 3);
-- sg_set_buf(&sg[0], __aad, aad_len);
-- 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);
--
-- crypto_aead_encrypt(aead_req);
-- kzfree(aead_req);
--
-- return 0;
--}
--
--int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
-- u8 *data, size_t data_len, u8 *mic)
--{
-- size_t mic_len = crypto_aead_authsize(tfm);
-- struct scatterlist sg[3];
-- struct aead_request *aead_req;
-- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
-- u8 *__aad;
-- int err;
--
-- if (data_len == 0)
-- return -EINVAL;
--
-- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
-- if (!aead_req)
-- return -ENOMEM;
--
-- __aad = (u8 *)aead_req + reqsize;
-- memcpy(__aad, aad, aad_len);
--
-- sg_init_table(sg, 3);
-- sg_set_buf(&sg[0], __aad, aad_len);
-- 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);
--
-- err = crypto_aead_decrypt(aead_req);
-- kzfree(aead_req);
--
-- return err;
--}
--
--struct crypto_aead *
--aead_key_setup_encrypt(const char *alg, const u8 key[],
-- size_t key_len, size_t mic_len)
--{
-- struct crypto_aead *tfm;
-- int err;
--
-- tfm = crypto_alloc_aead(alg, 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;
--
-- return tfm;
--
--free_aead:
-- crypto_free_aead(tfm);
-- return ERR_PTR(err);
--}
--
--void aead_key_free(struct crypto_aead *tfm)
--{
-- crypto_free_aead(tfm);
--}
---- a/net/mac80211/aead_api.h
-+++ /dev/null
-@@ -1,27 +0,0 @@
--/*
-- * 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 _AEAD_API_H
--#define _AEAD_API_H
--
--#include <crypto/aead.h>
--#include <linux/crypto.h>
--
--struct crypto_aead *
--aead_key_setup_encrypt(const char *alg, const u8 key[],
-- size_t key_len, size_t mic_len);
--
--int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-- size_t aad_len, u8 *data,
-- size_t data_len, u8 *mic);
--
--int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
-- size_t aad_len, u8 *data,
-- size_t data_len, u8 *mic);
--
--void aead_key_free(struct crypto_aead *tfm);
--
--#endif /* _AEAD_API_H */
---- a/net/mac80211/aes_ccm.h
-+++ b/net/mac80211/aes_ccm.h
-@@ -10,39 +10,17 @@
- #ifndef AES_CCM_H
- #define AES_CCM_H
-
--#include "aead_api.h"
-+#include <linux/crypto.h>
-
--#define CCM_AAD_LEN 32
--
--static inline struct crypto_aead *
--ieee80211_aes_key_setup_encrypt(const u8 key[], size_t key_len, size_t mic_len)
--{
-- return aead_key_setup_encrypt("ccm(aes)", key, key_len, mic_len);
--}
--
--static inline int
--ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm,
-- u8 *b_0, u8 *aad, u8 *data,
-- size_t data_len, u8 *mic)
--{
-- return aead_encrypt(tfm, b_0, aad + 2,
-- be16_to_cpup((__be16 *)aad),
-- data, data_len, mic);
--}
--
--static inline int
--ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm,
-- u8 *b_0, u8 *aad, u8 *data,
-- size_t data_len, u8 *mic)
--{
-- return aead_decrypt(tfm, b_0, aad + 2,
-- be16_to_cpup((__be16 *)aad),
-- data, data_len, mic);
--}
--
--static inline void ieee80211_aes_key_free(struct crypto_aead *tfm)
--{
-- return aead_key_free(tfm);
--}
-+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_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_cipher *tfm);
-
- #endif /* AES_CCM_H */
---- /dev/null
-+++ b/net/mac80211/aes_gcm.c
-@@ -0,0 +1,109 @@
-+/*
-+ * 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 <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/err.h>
-+#include <crypto/aead.h>
-+
-+#include <net/mac80211.h>
-+#include "key.h"
-+#include "aes_gcm.h"
-+
-+int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-+ u8 *data, size_t data_len, u8 *mic)
-+{
-+ struct scatterlist sg[3];
-+ struct aead_request *aead_req;
-+ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
-+ u8 *__aad;
-+
-+ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
-+ if (!aead_req)
-+ return -ENOMEM;
-+
-+ __aad = (u8 *)aead_req + reqsize;
-+ memcpy(__aad, aad, GCM_AAD_LEN);
-+
-+ 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, IEEE80211_GCMP_MIC_LEN);
-+
-+ aead_request_set_tfm(aead_req, tfm);
-+ aead_request_set_crypt(aead_req, sg, sg, data_len, j_0);
-+ aead_request_set_ad(aead_req, sg[0].length);
-+
-+ crypto_aead_encrypt(aead_req);
-+ kzfree(aead_req);
-+ return 0;
-+}
-+
-+int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-+ u8 *data, size_t data_len, u8 *mic)
-+{
-+ struct scatterlist sg[3];
-+ struct aead_request *aead_req;
-+ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
-+ u8 *__aad;
-+ int err;
-+
-+ if (data_len == 0)
-+ return -EINVAL;
-+
-+ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
-+ if (!aead_req)
-+ return -ENOMEM;
-+
-+ __aad = (u8 *)aead_req + reqsize;
-+ memcpy(__aad, aad, GCM_AAD_LEN);
-+
-+ 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, IEEE80211_GCMP_MIC_LEN);
-+
-+ aead_request_set_tfm(aead_req, tfm);
-+ aead_request_set_crypt(aead_req, sg, sg,
-+ data_len + IEEE80211_GCMP_MIC_LEN, j_0);
-+ aead_request_set_ad(aead_req, sg[0].length);
-+
-+ err = crypto_aead_decrypt(aead_req);
-+ kzfree(aead_req);
-+
-+ return err;
-+}
-+
-+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)
-+ goto free_aead;
-+ err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN);
-+ if (err)
-+ goto free_aead;
-+
-+ return tfm;
-+
-+free_aead:
-+ 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
-+++ b/net/mac80211/aes_gcm.h
-@@ -9,38 +9,30 @@
- #ifndef AES_GCM_H
- #define AES_GCM_H
-
--#include "aead_api.h"
-+#include <linux/crypto.h>
-
--#define GCM_AAD_LEN 32
--
--static inline int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm,
-- u8 *j_0, u8 *aad, u8 *data,
-- size_t data_len, u8 *mic)
-+static inline void
-+ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
-+ u8 *data, size_t data_len, u8 *mic)
- {
-- return aead_encrypt(tfm, j_0, aad + 2,
-- be16_to_cpup((__be16 *)aad),
-- data, data_len, 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)
-+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 aead_decrypt(tfm, j_0, aad + 2,
-- be16_to_cpup((__be16 *)aad),
-- data, data_len, mic);
-+ return -EOPNOTSUPP;
- }
-
- static inline struct crypto_aead *
- ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len)
- {
-- return aead_key_setup_encrypt("gcm(aes)", key,
-- key_len, IEEE80211_GCMP_MIC_LEN);
-+ return NULL;
- }
-
--static inline void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
-+static inline void
-+ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
- {
-- return aead_key_free(tfm);
- }
-
- #endif /* AES_GCM_H */
---- a/net/mac80211/wpa.c
-+++ b/net/mac80211/wpa.c
-@@ -306,7 +306,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;
-@@ -336,14 +337,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)
-@@ -351,6 +346,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] */
-@@ -407,7 +404,7 @@ static int ccmp_encrypt_skb(struct ieee8
- u8 *pos;
- u8 pn[6];
- u64 pn64;
-- u8 aad[CCM_AAD_LEN];
-+ u8 aad[2 * AES_BLOCK_SIZE];
- u8 b_0[AES_BLOCK_SIZE];
-
- if (info->control.hw_key &&
-@@ -462,9 +459,11 @@ static int ccmp_encrypt_skb(struct ieee8
- return 0;
-
- pos += IEEE80211_CCMP_HDR_LEN;
-- ccmp_special_blocks(skb, pn, b_0, aad);
-- return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
-- skb_put(skb, mic_len));
-+ 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);
-+
-+ return 0;
- }
-
-
-@@ -537,13 +536,13 @@ 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,
- skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
- data_len,
-- skb->data + skb->len - mic_len))
-+ skb->data + skb->len - mic_len, mic_len))
- return RX_DROP_UNUSABLE;
- }
-
-@@ -639,7 +638,7 @@ static int gcmp_encrypt_skb(struct ieee8
- u8 *pos;
- u8 pn[6];
- u64 pn64;
-- u8 aad[GCM_AAD_LEN];
-+ u8 aad[2 * AES_BLOCK_SIZE];
- u8 j_0[AES_BLOCK_SIZE];
-
- if (info->control.hw_key &&
-@@ -696,8 +695,10 @@ static int gcmp_encrypt_skb(struct ieee8
-
- pos += IEEE80211_GCMP_HDR_LEN;
- gcmp_special_blocks(skb, pn, j_0, aad);
-- return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
-- skb_put(skb, IEEE80211_GCMP_MIC_LEN));
-+ 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
-@@ -1121,9 +1122,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct
- struct ieee80211_key *key = tx->key;
- struct ieee80211_mmie_16 *mmie;
- struct ieee80211_hdr *hdr;
-- u8 aad[GMAC_AAD_LEN];
-+ u8 aad[20];
- u64 pn64;
-- u8 nonce[GMAC_NONCE_LEN];
-+ u8 nonce[12];
-
- if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
- return TX_DROP;
-@@ -1169,7 +1170,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
- struct ieee80211_key *key = rx->key;
- struct ieee80211_mmie_16 *mmie;
-- u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN];
-+ 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))
---- /dev/null
-+++ b/net/mac80211/aes_ccm.c
-@@ -0,0 +1,144 @@
-+/*
-+ * Copyright 2003-2004, Instant802 Networks, Inc.
-+ * Copyright 2005-2006, Devicescape Software, Inc.
-+ *
-+ * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/err.h>
-+#include <crypto/aead.h>
-+#include <crypto/aes.h>
-+
-+#include <net/mac80211.h>
-+#include "key.h"
-+#include "aes_ccm.h"
-+
-+static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0,
-+ u8 *a, u8 *b)
-+{
-+ 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);
-+
-+ /* 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 *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];
-+ }
-+
-+ for (i = 0; i < mic_len; i++)
-+ mic[i] = b[i] ^ s_0[i];
-+}
-+
-+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)
-+{
-+ 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 0;
-+}
-+
-+struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
-+ size_t key_len,
-+ size_t mic_len)
-+{
-+ struct crypto_cipher *tfm;
-+
-+ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
-+ if (!IS_ERR(tfm))
-+ crypto_cipher_setkey(tfm, key, key_len);
-+
-+ return tfm;
-+}
-+
-+
-+void ieee80211_aes_key_free(struct crypto_cipher *tfm)
-+{
-+ crypto_free_cipher(tfm);
-+}
---- 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
-- depends on CRYPTO_CCM
-- depends on CRYPTO_GCM
- depends on CRYPTO_CMAC
- depends on CRC32
- ---help---
---- a/net/mac80211/aes_gmac.h
-+++ b/net/mac80211/aes_gmac.h
-@@ -15,10 +15,22 @@
- #define GMAC_MIC_LEN 16
- #define GMAC_NONCE_LEN 12
-
--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
-@@ -88,7 +88,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 {
+++ /dev/null
-Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects
-
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -1058,7 +1058,6 @@ static int ieee80211_stop_ap(struct wiph
- sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
-
- __sta_info_flush(sdata, true);
-- ieee80211_free_keys(sdata, true);
-
- sdata->vif.bss_conf.enable_beacon = false;
- sdata->vif.bss_conf.ssid_len = 0;
+++ /dev/null
---- a/net/wireless/sysfs.c
-+++ b/net/wireless/sysfs.c
-@@ -24,18 +24,35 @@ static inline struct cfg80211_registered
- return container_of(dev, struct cfg80211_registered_device, wiphy.dev);
- }
-
--#define SHOW_FMT(name, fmt, member) \
-+#define SHOW_FMT(name, fmt, member, mode) \
- static ssize_t name ## _show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
- { \
- return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
- } \
--static DEVICE_ATTR_RO(name)
-+static DEVICE_ATTR_##mode(name)
-
--SHOW_FMT(index, "%d", wiphy_idx);
--SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
--SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
-+static ssize_t macaddress_store(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t len)
-+{
-+ u8 mac[ETH_ALEN];
-+
-+ if (!mac_pton(buf, mac))
-+ return -EINVAL;
-+
-+ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
-+ return -EINVAL;
-+
-+ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN);
-+
-+ return strnlen(buf, len);
-+}
-+
-+SHOW_FMT(index, "%d", wiphy_idx, RO);
-+SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW);
-+SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO);
-
- static ssize_t name_show(struct device *dev,
- struct device_attribute *attr,
+++ /dev/null
-Disable FILS support, since it pulls in crypto hash support
-
---- a/net/mac80211/fils_aead.h
-+++ b/net/mac80211/fils_aead.h
-@@ -10,7 +10,7 @@
- #ifndef FILS_AEAD_H
- #define FILS_AEAD_H
-
--#if LINUX_VERSION_IS_GEQ(4,3,0)
-+#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */
- int fils_encrypt_assoc_req(struct sk_buff *skb,
- struct ieee80211_mgd_assoc_data *assoc_data);
- int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
---- a/net/mac80211/fils_aead.c
-+++ b/net/mac80211/fils_aead.c
-@@ -1,4 +1,4 @@
--#if LINUX_VERSION_IS_GEQ(4,3,0)
-+#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */
- /*
- * FILS AEAD for (Re)Association Request/Response frames
- * Copyright 2016, Qualcomm Atheros, Inc.
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -550,7 +550,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
- NL80211_FEATURE_MAC_ON_CREATE |
- NL80211_FEATURE_USERSPACE_MPM |
- NL80211_FEATURE_FULL_AP_CLIENT_STATE;
--#if LINUX_VERSION_IS_GEQ(4,3,0)
-+#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */
- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
- #endif
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 7 Oct 2017 09:37:28 +0200
-Subject: [PATCH] Revert "mac80211: aes-cmac: switch to shash CMAC
- driver"
-
-This reverts commit 26717828b75dd5c46e97f7f4a9b937d038bb2852.
-Reduces mac80211 dependencies for LEDE
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/aes_cmac.c
-+++ b/net/mac80211/aes_cmac.c
-@@ -22,50 +22,126 @@
- #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
- #define AAD_LEN 20
-
--static const u8 zero[CMAC_TLEN_256];
-
--void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
-- const u8 *data, size_t data_len, u8 *mic)
-+void gf_mulx(u8 *pad)
-+{
-+ int i, carry;
-+
-+ carry = pad[0] & 0x80;
-+ for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
-+ pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
-+ pad[AES_BLOCK_SIZE - 1] <<= 1;
-+ if (carry)
-+ pad[AES_BLOCK_SIZE - 1] ^= 0x87;
-+}
-+
-+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)
- {
-- SHASH_DESC_ON_STACK(desc, tfm);
-- u8 out[AES_BLOCK_SIZE];
-+ u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
-+ const u8 *pos, *end;
-+ size_t i, e, left, total_len;
-+
-+ memset(cbc, 0, AES_BLOCK_SIZE);
-+
-+ total_len = 0;
-+ for (e = 0; e < num_elem; e++)
-+ total_len += len[e];
-+ left = total_len;
-+
-+ e = 0;
-+ pos = addr[0];
-+ end = pos + len[0];
-+
-+ while (left >= AES_BLOCK_SIZE) {
-+ for (i = 0; i < AES_BLOCK_SIZE; i++) {
-+ cbc[i] ^= *pos++;
-+ if (pos >= end) {
-+ e++;
-+ pos = addr[e];
-+ end = pos + len[e];
-+ }
-+ }
-+ if (left > AES_BLOCK_SIZE)
-+ crypto_cipher_encrypt_one(tfm, cbc, cbc);
-+ left -= AES_BLOCK_SIZE;
-+ }
-+
-+ memset(pad, 0, AES_BLOCK_SIZE);
-+ crypto_cipher_encrypt_one(tfm, pad, pad);
-+ gf_mulx(pad);
-+
-+ if (left || total_len == 0) {
-+ for (i = 0; i < left; i++) {
-+ cbc[i] ^= *pos++;
-+ if (pos >= end) {
-+ e++;
-+ pos = addr[e];
-+ end = pos + len[e];
-+ }
-+ }
-+ cbc[left] ^= 0x80;
-+ gf_mulx(pad);
-+ }
-+
-+ for (i = 0; i < AES_BLOCK_SIZE; i++)
-+ pad[i] ^= cbc[i];
-+ crypto_cipher_encrypt_one(tfm, pad, pad);
-+ memcpy(mac, pad, mac_len);
-+}
-
-- desc->tfm = tfm;
-
-- crypto_shash_init(desc);
-- crypto_shash_update(desc, aad, AAD_LEN);
-- crypto_shash_update(desc, data, data_len - CMAC_TLEN);
-- crypto_shash_finup(desc, zero, CMAC_TLEN, out);
-+void ieee80211_aes_cmac(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];
-+
-+ memset(zero, 0, CMAC_TLEN);
-+ addr[0] = aad;
-+ len[0] = AAD_LEN;
-+ addr[1] = data;
-+ len[1] = data_len - CMAC_TLEN;
-+ addr[2] = zero;
-+ len[2] = CMAC_TLEN;
-
-- memcpy(mic, out, CMAC_TLEN);
-+ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN);
- }
-
--void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
-+void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
- const u8 *data, size_t data_len, u8 *mic)
- {
-- SHASH_DESC_ON_STACK(desc, tfm);
-+ 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;
-
-- desc->tfm = tfm;
--
-- crypto_shash_init(desc);
-- crypto_shash_update(desc, aad, AAD_LEN);
-- crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
-- crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
-+ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256);
- }
-
--struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
-- size_t key_len)
-+struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
-+ size_t key_len)
- {
-- struct crypto_shash *tfm;
-+ struct crypto_cipher *tfm;
-
-- tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
-+ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
- if (!IS_ERR(tfm))
-- crypto_shash_setkey(tfm, key, key_len);
-+ crypto_cipher_setkey(tfm, key, key_len);
-
- return tfm;
- }
-
--void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm)
-+
-+void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm)
- {
-- crypto_free_shash(tfm);
-+ crypto_free_cipher(tfm);
- }
---- a/net/mac80211/aes_cmac.h
-+++ b/net/mac80211/aes_cmac.h
-@@ -10,14 +10,13 @@
- #define AES_CMAC_H
-
- #include <linux/crypto.h>
--#include <crypto/hash.h>
-
--struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
-- size_t key_len);
--void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
-+struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
-+ size_t key_len);
-+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_shash *tfm, const u8 *aad,
-+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_shash *tfm);
-+void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm);
-
- #endif /* AES_CMAC_H */
---- a/net/mac80211/key.h
-+++ b/net/mac80211/key.h
-@@ -93,7 +93,7 @@ struct ieee80211_key {
- } ccmp;
- struct {
- u8 rx_pn[IEEE80211_CMAC_PN_LEN];
-- struct crypto_shash *tfm;
-+ struct crypto_cipher *tfm;
- u32 replays; /* dot11RSNAStatsCMACReplays */
- u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
- } aes_cmac;
+++ /dev/null
---- a/net/mac80211/Kconfig
-+++ b/net/mac80211/Kconfig
-@@ -5,7 +5,6 @@ config MAC80211
- depends on CRYPTO
- depends on CRYPTO_ARC4
- depends on CRYPTO_AES
-- depends on CRYPTO_CMAC
- depends on CRC32
- ---help---
- This option enables the hardware independent IEEE 802.11
+++ /dev/null
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3750,6 +3750,12 @@ out:
- netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
- {
-+#if defined(sk_pacing_shift) || LINUX_VERSION_IS_GEQ(4,15,0)
-+ if (skb->sk && sk_fullsock(skb->sk) &&
-+ skb->sk->sk_pacing_shift != 6)
-+ skb->sk->sk_pacing_shift = 6;
-+#endif
-+
- if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) {
- struct sk_buff_head queue;
-
+++ /dev/null
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -292,7 +292,7 @@ void ieee80211_restart_hw(struct ieee802
- }
- EXPORT_SYMBOL(ieee80211_restart_hw);
-
--#ifdef CONFIG_INET
-+#ifdef __disabled__CONFIG_INET
- static int ieee80211_ifa_changed(struct notifier_block *nb,
- unsigned long data, void *arg)
- {
-@@ -351,7 +351,7 @@ static int ieee80211_ifa_changed(struct
- }
- #endif
-
--#if IS_ENABLED(CONFIG_IPV6)
-+#if IS_ENABLED(__disabled__CONFIG_IPV6)
- static int ieee80211_ifa6_changed(struct notifier_block *nb,
- unsigned long data, void *arg)
- {
-@@ -1114,14 +1114,14 @@ int ieee80211_register_hw(struct ieee802
- if (result)
- goto fail_flows;
-
--#ifdef CONFIG_INET
-+#ifdef __disabled__CONFIG_INET
- local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
- result = register_inetaddr_notifier(&local->ifa_notifier);
- if (result)
- goto fail_ifa;
- #endif
-
--#if IS_ENABLED(CONFIG_IPV6)
-+#if IS_ENABLED(__disabled__CONFIG_IPV6)
- local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
- result = register_inet6addr_notifier(&local->ifa6_notifier);
- if (result)
-@@ -1130,13 +1130,13 @@ int ieee80211_register_hw(struct ieee802
-
- return 0;
-
--#if IS_ENABLED(CONFIG_IPV6)
-+#if IS_ENABLED(__disabled__CONFIG_IPV6)
- fail_ifa6:
--#ifdef CONFIG_INET
-+#ifdef __disabled__CONFIG_INET
- unregister_inetaddr_notifier(&local->ifa_notifier);
- #endif
- #endif
--#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
-+#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6)
- fail_ifa:
- #endif
- ieee80211_txq_teardown_flows(local);
-@@ -1166,10 +1166,10 @@ void ieee80211_unregister_hw(struct ieee
- tasklet_kill(&local->tx_pending_tasklet);
- tasklet_kill(&local->tasklet);
-
--#ifdef CONFIG_INET
-+#ifdef __disabled__CONFIG_INET
- unregister_inetaddr_notifier(&local->ifa_notifier);
- #endif
--#if IS_ENABLED(CONFIG_IPV6)
-+#if IS_ENABLED(__disabled__CONFIG_IPV6)
- unregister_inet6addr_notifier(&local->ifa6_notifier);
- #endif
-
+++ /dev/null
-From: Thomas Hebb <tommyhebb@gmail.com>
-Subject: [PATCH] ath10k: search all IEs for variant before falling back
-Date: Wed, 21 Feb 2018 11:43:39 -0500
-
-commit f2593cb1b291 ("ath10k: Search SMBIOS for OEM board file
-extension") added a feature to ath10k that allows Board Data File
-(BDF) conflicts between multiple devices that use the same device IDs
-but have different calibration requirements to be resolved by allowing
-a "variant" string to be stored in SMBIOS [and later device tree, added
-by commit d06f26c5c8a4 ("ath10k: search DT for qcom,ath10k-calibration-
-variant")] that gets appended to the ID stored in board-2.bin.
-
-This original patch had a regression, however. Namely that devices with
-a variant present in SMBIOS that didn't need custom BDFs could no longer
-find the default BDF, which has no variant appended. The patch was
-reverted and re-applied with a fix for this issue in commit 1657b8f84ed9
-("search SMBIOS for OEM board file extension").
-
-But the fix to fall back to a default BDF introduced another issue: the
-driver currently parses IEs in board-2.bin one by one, and for each one
-it first checks to see if it matches the ID with the variant appended.
-If it doesn't, it checks to see if it matches the "fallback" ID with no
-variant. If a matching BDF is found at any point during this search, the
-search is terminated and that BDF is used. The issue is that it's very
-possible (and is currently the case for board-2.bin files present in the
-ath10k-firmware repository) for the default BDF to occur in an earlier
-IE than the variant-specific BDF. In this case, the current code will
-happily choose the default BDF even though a better-matching BDF is
-present later in the file.
-
-This patch fixes the issue by first searching the entire file for the ID
-with variant, and searching for the fallback ID only if that search
-fails. It also includes some code cleanup in the area, as
-ath10k_core_fetch_board_data_api_n() no longer does its own string
-mangling to remove the variant from an ID, instead leaving that job to a
-new flag passed to ath10k_core_create_board_name().
-
-I've tested this patch on a QCA4019 and verified that the driver behaves
-correctly for 1) both fallback and variant BDFs present, 2) only fallback
-BDF present, and 3) no matching BDFs present.
-
-Fixes: 1657b8f84ed9 ("ath10k: search SMBIOS for OEM board file extension")
-Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
----
- drivers/net/wireless/ath/ath10k/core.c | 134 ++++++++++++++++++---------------
- 1 file changed, 72 insertions(+), 62 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/core.c
-+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -1132,14 +1132,61 @@ out:
- return ret;
- }
-
-+static int ath10k_core_search_bd(struct ath10k *ar,
-+ const char *boardname,
-+ const u8 *data,
-+ size_t len)
-+{
-+ size_t ie_len;
-+ struct ath10k_fw_ie *hdr;
-+ int ret = -ENOENT, ie_id;
-+
-+ while (len > sizeof(struct ath10k_fw_ie)) {
-+ hdr = (struct ath10k_fw_ie *)data;
-+ ie_id = le32_to_cpu(hdr->id);
-+ ie_len = le32_to_cpu(hdr->len);
-+
-+ len -= sizeof(*hdr);
-+ data = hdr->data;
-+
-+ if (len < ALIGN(ie_len, 4)) {
-+ ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n",
-+ ie_id, ie_len, len);
-+ return -EINVAL;
-+ }
-+
-+ switch (ie_id) {
-+ case ATH10K_BD_IE_BOARD:
-+ ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
-+ boardname);
-+ if (ret == -ENOENT)
-+ /* no match found, continue */
-+ break;
-+
-+ /* either found or error, so stop searching */
-+ goto out;
-+ }
-+
-+ /* jump over the padding */
-+ ie_len = ALIGN(ie_len, 4);
-+
-+ len -= ie_len;
-+ data += ie_len;
-+ }
-+
-+out:
-+ /* return result of parse_bd_ie_board() or -ENOENT */
-+ return ret;
-+}
-+
- static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
- const char *boardname,
-+ const char *fallback_boardname,
- const char *filename)
- {
-- size_t len, magic_len, ie_len;
-- struct ath10k_fw_ie *hdr;
-+ size_t len, magic_len;
- const u8 *data;
-- int ret, ie_id;
-+ int ret;
-
- ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
- ar->hw_params.fw.dir,
-@@ -1177,69 +1224,23 @@ static int ath10k_core_fetch_board_data_
- data += magic_len;
- len -= magic_len;
-
-- while (len > sizeof(struct ath10k_fw_ie)) {
-- hdr = (struct ath10k_fw_ie *)data;
-- ie_id = le32_to_cpu(hdr->id);
-- ie_len = le32_to_cpu(hdr->len);
--
-- len -= sizeof(*hdr);
-- data = hdr->data;
--
-- if (len < ALIGN(ie_len, 4)) {
-- ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n",
-- ie_id, ie_len, len);
-- ret = -EINVAL;
-- goto err;
-- }
-+ /* attempt to find boardname in the IE list */
-+ ret = ath10k_core_search_bd(ar, boardname, data, len);
-
-- switch (ie_id) {
-- case ATH10K_BD_IE_BOARD:
-- ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len,
-- boardname);
-- if (ret == -ENOENT && ar->id.bdf_ext[0] != '\0') {
-- /* try default bdf if variant was not found */
-- char *s, *v = ",variant=";
-- char boardname2[100];
--
-- strlcpy(boardname2, boardname,
-- sizeof(boardname2));
--
-- s = strstr(boardname2, v);
-- if (s)
-- *s = '\0'; /* strip ",variant=%s" */
--
-- ret = ath10k_core_parse_bd_ie_board(ar, data,
-- ie_len,
-- boardname2);
-- }
-+ /* if we didn't find it and have a fallback name, try that */
-+ if (ret == -ENOENT && fallback_boardname)
-+ ret = ath10k_core_search_bd(ar, fallback_boardname, data, len);
-
-- if (ret == -ENOENT)
-- /* no match found, continue */
-- break;
-- else if (ret)
-- /* there was an error, bail out */
-- goto err;
--
-- /* board data found */
-- goto out;
-- }
--
-- /* jump over the padding */
-- ie_len = ALIGN(ie_len, 4);
--
-- len -= ie_len;
-- data += ie_len;
-- }
--
--out:
-- if (!ar->normal_mode_fw.board_data || !ar->normal_mode_fw.board_len) {
-+ if (ret == -ENOENT) {
- ath10k_err(ar,
- "failed to fetch board data for %s from %s/%s\n",
- boardname, ar->hw_params.fw.dir, filename);
- ret = -ENODATA;
-- goto err;
- }
-
-+ if (ret)
-+ goto err;
-+
- return 0;
-
- err:
-@@ -1248,12 +1249,12 @@ err:
- }
-
- static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
-- size_t name_len)
-+ size_t name_len, bool with_variant)
- {
- /* strlen(',variant=') + strlen(ar->id.bdf_ext) */
- char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 };
-
-- if (ar->id.bdf_ext[0] != '\0')
-+ if (with_variant && ar->id.bdf_ext[0] != '\0')
- scnprintf(variant, sizeof(variant), ",variant=%s",
- ar->id.bdf_ext);
-
-@@ -1279,17 +1280,26 @@ out:
-
- static int ath10k_core_fetch_board_file(struct ath10k *ar)
- {
-- char boardname[100];
-+ char boardname[100], fallback_boardname[100];
- int ret;
-
-- ret = ath10k_core_create_board_name(ar, boardname, sizeof(boardname));
-+ ret = ath10k_core_create_board_name(ar, boardname,
-+ sizeof(boardname), true);
- if (ret) {
- ath10k_err(ar, "failed to create board name: %d", ret);
- return ret;
- }
-
-+ ret = ath10k_core_create_board_name(ar, fallback_boardname,
-+ sizeof(boardname), false);
-+ if (ret) {
-+ ath10k_err(ar, "failed to create fallback board name: %d", ret);
-+ return ret;
-+ }
-+
- ar->bd_api = 2;
- ret = ath10k_core_fetch_board_data_api_n(ar, boardname,
-+ fallback_boardname,
- ATH10K_BOARD_API2_FILE);
- if (!ret)
- goto success;
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/initvals.c
-+++ b/drivers/net/wireless/ath/ath5k/initvals.c
-@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini
- { AR5K_IMR, 0 },
- { AR5K_IER, AR5K_IER_DISABLE },
- { AR5K_BSR, 0, AR5K_INI_READ },
-+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
- { AR5K_TXCFG, AR5K_DMASIZE_128B },
- { AR5K_RXCFG, AR5K_DMASIZE_128B },
-+#else
-+ /* WAR for AR71xx PCI bug */
-+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
-+ { AR5K_RXCFG, AR5K_DMASIZE_4B },
-+#endif
- { AR5K_CFG, AR5K_INIT_CFG },
- { AR5K_TOPS, 8 },
- { AR5K_RXNOFRM, 8 },
---- a/drivers/net/wireless/ath/ath5k/dma.c
-+++ b/drivers/net/wireless/ath/ath5k/dma.c
-@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
- * guess we can tweak it and see how it goes ;-)
- */
- if (ah->ah_version != AR5K_AR5210) {
-+#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
- AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
- AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
- AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
- AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
-+#else
-+ /* WAR for AR71xx PCI bug */
-+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
-+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
-+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
-+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
-+#endif
- }
-
- /* Pre-enable interrupts on 5211/5212*/
+++ /dev/null
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -2215,7 +2215,7 @@ static int ieee80211_scan(struct wiphy *
- * the frames sent while scanning on other channel will be
- * lost)
- */
-- if (sdata->u.ap.beacon &&
-+ if (0 && sdata->u.ap.beacon &&
- (!(wiphy->features & NL80211_FEATURE_AP_SCAN) ||
- !(req->flags & NL80211_SCAN_FLAG_AP)))
- return -EOPNOTSUPP;
+++ /dev/null
-From: Brian Norris <briannorris@chromium.org>
-Date: Thu, 19 Oct 2017 11:45:19 -0700
-Subject: [PATCH] ath10k: fix build errors with !CONFIG_PM
-
-Build errors have been reported with CONFIG_PM=n:
-
-drivers/net/wireless/ath/ath10k/pci.c:3416:8: error: implicit
-declaration of function 'ath10k_pci_suspend'
-[-Werror=implicit-function-declaration]
-
-drivers/net/wireless/ath/ath10k/pci.c:3428:8: error: implicit
-declaration of function 'ath10k_pci_resume'
-[-Werror=implicit-function-declaration]
-
-These are caused by the combination of the following two commits:
-
-6af1de2e4ec4 ("ath10k: mark PM functions as __maybe_unused")
-96378bd2c6cd ("ath10k: fix core PCI suspend when WoWLAN is supported but
-disabled")
-
-Both build fine on their own.
-
-But now that ath10k_pci_pm_{suspend,resume}() is compiled
-unconditionally, we should also compile ath10k_pci_{suspend,resume}()
-unconditionally.
-
-And drop the #ifdef around ath10k_pci_hif_{suspend,resume}() too; they
-are trivial (empty), so we're not saving much space by compiling them
-out. And the alternatives would be to sprinkle more __maybe_unused, or
-spread the #ifdef's further.
-
-Build tested with the following combinations:
-CONFIG_PM=y && CONFIG_PM_SLEEP=y
-CONFIG_PM=y && CONFIG_PM_SLEEP=n
-CONFIG_PM=n
-
-Fixes: 96378bd2c6cd ("ath10k: fix core PCI suspend when WoWLAN is supported but disabled")
-Fixes: 096ad2a15fd8 ("Merge branch 'ath-next'")
-Signed-off-by: Brian Norris <briannorris@chromium.org>
-Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
----
-
---- a/drivers/net/wireless/ath/ath10k/pci.c
-+++ b/drivers/net/wireless/ath/ath10k/pci.c
-@@ -2577,8 +2577,6 @@ void ath10k_pci_hif_power_down(struct at
- */
- }
-
--#ifdef CONFIG_PM
--
- static int ath10k_pci_hif_suspend(struct ath10k *ar)
- {
- /* Nothing to do; the important stuff is in the driver suspend. */
-@@ -2627,7 +2625,6 @@ static int ath10k_pci_resume(struct ath1
-
- return ret;
- }
--#endif
-
- static bool ath10k_pci_validate_cal(void *data, size_t size)
- {
-@@ -2782,10 +2779,8 @@ static const struct ath10k_hif_ops ath10
- .power_down = ath10k_pci_hif_power_down,
- .read32 = ath10k_pci_read32,
- .write32 = ath10k_pci_write32,
--#ifdef CONFIG_PM
- .suspend = ath10k_pci_hif_suspend,
- .resume = ath10k_pci_hif_resume,
--#endif
- .fetch_cal_eeprom = ath10k_pci_hif_fetch_cal_eeprom,
- };
-
+++ /dev/null
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Mon, 20 Nov 2017 17:01:44 +0100
-Subject: [PATCH] mac80211: properly free requested-but-not-started TX agg
- sessions
-
-When deleting a station or otherwise tearing down all aggregation
-sessions, make sure to delete requested but not yet started ones,
-to avoid the following scenario:
-
- * session is requested, added to tid_start_tx[]
- * ieee80211_ba_session_work() runs, gets past BLOCK_BA check
- * ieee80211_sta_tear_down_BA_sessions() runs, locks &sta->ampdu_mlme.mtx,
- e.g. while deleting the station - deleting all active sessions
- * ieee80211_ba_session_work() continues since tear down flushes it, and
- calls ieee80211_tx_ba_session_handle_start() for the new session, arms
- the timer for it
- * station deletion continues to __cleanup_single_sta() and frees the
- session struct, while the timer is armed
-
-Reported-by: Fengguang Wu <fengguang.wu@intel.com>
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/net/mac80211/agg-tx.c
-+++ b/net/mac80211/agg-tx.c
-@@ -330,6 +330,11 @@ int ___ieee80211_stop_tx_ba_session(stru
-
- spin_lock_bh(&sta->lock);
-
-+ /* free struct pending for start, if present */
-+ tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
-+ kfree(tid_tx);
-+ sta->ampdu_mlme.tid_start_tx[tid] = NULL;
-+
- tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
- if (!tid_tx) {
- spin_unlock_bh(&sta->lock);
+++ /dev/null
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Thu, 4 Jan 2018 15:51:53 +0100
-Subject: [PATCH] mac80211: mesh: drop frames appearing to be from us
-
-If there are multiple mesh stations with the same MAC address,
-they will both get confused and start throwing warnings.
-
-Obviously in this case nothing can actually work anyway, so just
-drop frames that look like they're from ourselves early on.
-
-Reported-by: Gui Iribarren <gui@altermundi.net>
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -3632,6 +3632,8 @@ static bool ieee80211_accept_frame(struc
- }
- return true;
- case NL80211_IFTYPE_MESH_POINT:
-+ if (ether_addr_equal(sdata->vif.addr, hdr->addr2))
-+ return false;
- if (multicast)
- return true;
- return ether_addr_equal(sdata->vif.addr, hdr->addr1);
+++ /dev/null
-From 2fd3877b5bb7d39782c3205a1dcda02023b8514a Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 8 Nov 2017 14:36:31 +0100
-Subject: [PATCH] brcmfmac: handle FWHALT mailbox indication
-
-The firmware uses a mailbox to communicate to the host what is going
-on. In the driver we validate the bit received. Various people seen
-the following message:
-
- brcmfmac: brcmf_sdio_hostmail: Unknown mailbox data content: 0x40012
-
-Bit 4 is cause of this message, but this actually indicates the firmware
-has halted. Handle this bit by giving a more meaningful error message.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 14 ++++++++++----
- 1 file changed, 10 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -260,10 +260,11 @@ struct rte_console {
- #define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */
-
- /* tohostmailboxdata */
--#define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */
--#define HMB_DATA_DEVREADY 2 /* talk to host after enable */
--#define HMB_DATA_FC 4 /* per prio flowcontrol update flag */
--#define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */
-+#define HMB_DATA_NAKHANDLED 0x0001 /* retransmit NAK'd frame */
-+#define HMB_DATA_DEVREADY 0x0002 /* talk to host after enable */
-+#define HMB_DATA_FC 0x0004 /* per prio flowcontrol update flag */
-+#define HMB_DATA_FWREADY 0x0008 /* fw ready for protocol activity */
-+#define HMB_DATA_FWHALT 0x0010 /* firmware halted */
-
- #define HMB_DATA_FCDATA_MASK 0xff000000
- #define HMB_DATA_FCDATA_SHIFT 24
-@@ -1094,6 +1095,10 @@ static u32 brcmf_sdio_hostmail(struct br
- offsetof(struct sdpcmd_regs, tosbmailbox));
- bus->sdcnt.f1regdata += 2;
-
-+ /* dongle indicates the firmware has halted/crashed */
-+ if (hmb_data & HMB_DATA_FWHALT)
-+ brcmf_err("mailbox indicates firmware halted\n");
-+
- /* Dongle recomposed rx frames, accept them again */
- if (hmb_data & HMB_DATA_NAKHANDLED) {
- brcmf_dbg(SDIO, "Dongle reports NAK handled, expect rtx of %d\n",
-@@ -1151,6 +1156,7 @@ static u32 brcmf_sdio_hostmail(struct br
- HMB_DATA_NAKHANDLED |
- HMB_DATA_FC |
- HMB_DATA_FWREADY |
-+ HMB_DATA_FWHALT |
- HMB_DATA_FCDATA_MASK | HMB_DATA_VERSION_MASK))
- brcmf_err("Unknown mailbox data content: 0x%02x\n",
- hmb_data);
+++ /dev/null
-From 6c219b0088158da839a5be63c5b3d96c145501d2 Mon Sep 17 00:00:00 2001
-From: Franky Lin <franky.lin@broadcom.com>
-Date: Wed, 8 Nov 2017 14:36:32 +0100
-Subject: [PATCH] brcmfmac: disable packet filtering in promiscuous mode
-
-Disable arp and nd offload to allow all packets sending to host.
-
-Reported-by: Phil Elwell <phil@raspberrypi.org>
-Tested-by: Phil Elwell <phil@raspberrypi.org>
-Reviewed-by: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 41 ----------------------
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 38 ++++++++++++++++++++
- .../wireless/broadcom/brcm80211/brcmfmac/core.h | 1 +
- 3 files changed, 39 insertions(+), 41 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -472,47 +472,6 @@ send_key_to_dongle(struct brcmf_if *ifp,
- return err;
- }
-
--static s32
--brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
--{
-- s32 err;
-- u32 mode;
--
-- if (enable)
-- mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
-- else
-- mode = 0;
--
-- /* Try to set and enable ARP offload feature, this may fail, then it */
-- /* is simply not supported and err 0 will be returned */
-- err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode);
-- if (err) {
-- brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
-- mode, err);
-- err = 0;
-- } else {
-- err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable);
-- if (err) {
-- brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n",
-- enable, err);
-- err = 0;
-- } else
-- brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n",
-- enable, mode);
-- }
--
-- err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable);
-- if (err) {
-- brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n",
-- enable, err);
-- err = 0;
-- } else
-- brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n",
-- enable, mode);
--
-- return err;
--}
--
- static void
- brcmf_cfg80211_update_proto_addr_mode(struct wireless_dev *wdev)
- {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -71,6 +71,43 @@ struct brcmf_if *brcmf_get_ifp(struct br
- return ifp;
- }
-
-+void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable)
-+{
-+ s32 err;
-+ u32 mode;
-+
-+ if (enable)
-+ mode = BRCMF_ARP_OL_AGENT | BRCMF_ARP_OL_PEER_AUTO_REPLY;
-+ else
-+ mode = 0;
-+
-+ /* Try to set and enable ARP offload feature, this may fail, then it */
-+ /* is simply not supported and err 0 will be returned */
-+ err = brcmf_fil_iovar_int_set(ifp, "arp_ol", mode);
-+ if (err) {
-+ brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
-+ mode, err);
-+ } else {
-+ err = brcmf_fil_iovar_int_set(ifp, "arpoe", enable);
-+ if (err) {
-+ brcmf_dbg(TRACE, "failed to configure (%d) ARP offload err = %d\n",
-+ enable, err);
-+ } else {
-+ brcmf_dbg(TRACE, "successfully configured (%d) ARP offload to 0x%x\n",
-+ enable, mode);
-+ }
-+ }
-+
-+ err = brcmf_fil_iovar_int_set(ifp, "ndoe", enable);
-+ if (err) {
-+ brcmf_dbg(TRACE, "failed to configure (%d) ND offload err = %d\n",
-+ enable, err);
-+ } else {
-+ brcmf_dbg(TRACE, "successfully configured (%d) ND offload to 0x%x\n",
-+ enable, mode);
-+ }
-+}
-+
- static void _brcmf_set_multicast_list(struct work_struct *work)
- {
- struct brcmf_if *ifp;
-@@ -134,6 +171,7 @@ static void _brcmf_set_multicast_list(st
- if (err < 0)
- brcmf_err("Setting BRCMF_C_SET_PROMISC failed, %d\n",
- err);
-+ brcmf_configure_arp_nd_offload(ifp, !cmd_value);
- }
-
- #if IS_ENABLED(CONFIG_IPV6)
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-@@ -203,6 +203,7 @@ int brcmf_netdev_wait_pend8021x(struct b
- /* Return pointer to interface name */
- char *brcmf_ifname(struct brcmf_if *ifp);
- struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
-+void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable);
- int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
- struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
- bool is_p2pdev, const char *name, u8 *mac_addr);
+++ /dev/null
-From 8c6efda22f5f9f73fc948f517424466be01ae84d Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 8 Nov 2017 14:36:33 +0100
-Subject: [PATCH] brcmfmac: cleanup brcmf_cfg80211_escan() function
-
-The function brcmf_cfg80211_escan() was always called with a non-null
-request parameter and null pointer for this_ssid parameter. Clean up
-the function removing the dead code path.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 76 ++++------------------
- 1 file changed, 11 insertions(+), 65 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -1072,18 +1072,10 @@ brcmf_do_escan(struct brcmf_if *ifp, str
-
- static s32
- brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
-- struct cfg80211_scan_request *request,
-- struct cfg80211_ssid *this_ssid)
-+ struct cfg80211_scan_request *request)
- {
-- struct brcmf_if *ifp = vif->ifp;
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-- struct cfg80211_ssid *ssids;
-- u32 passive_scan;
-- bool escan_req;
-- bool spec_scan;
- s32 err;
-- struct brcmf_ssid_le ssid_le;
-- u32 SSID_len;
-
- brcmf_dbg(SCAN, "START ESCAN\n");
-
-@@ -1101,8 +1093,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
- cfg->scan_status);
- return -EAGAIN;
- }
-- if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) {
-- brcmf_err("Connecting: status (%lu)\n", ifp->vif->sme_state);
-+ if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) {
-+ brcmf_err("Connecting: status (%lu)\n", vif->sme_state);
- return -EAGAIN;
- }
-
-@@ -1110,63 +1102,17 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
- if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
- vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
-
-- escan_req = false;
-- if (request) {
-- /* scan bss */
-- ssids = request->ssids;
-- escan_req = true;
-- } else {
-- /* scan in ibss */
-- /* we don't do escan in ibss */
-- ssids = this_ssid;
-- }
--
- cfg->scan_request = request;
- set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
-- if (escan_req) {
-- cfg->escan_info.run = brcmf_run_escan;
-- err = brcmf_p2p_scan_prep(wiphy, request, vif);
-- if (err)
-- goto scan_out;
--
-- err = brcmf_do_escan(vif->ifp, request);
-- if (err)
-- goto scan_out;
-- } else {
-- brcmf_dbg(SCAN, "ssid \"%s\", ssid_len (%d)\n",
-- ssids->ssid, ssids->ssid_len);
-- memset(&ssid_le, 0, sizeof(ssid_le));
-- SSID_len = min_t(u8, sizeof(ssid_le.SSID), ssids->ssid_len);
-- ssid_le.SSID_len = cpu_to_le32(0);
-- spec_scan = false;
-- if (SSID_len) {
-- memcpy(ssid_le.SSID, ssids->ssid, SSID_len);
-- ssid_le.SSID_len = cpu_to_le32(SSID_len);
-- spec_scan = true;
-- } else
-- brcmf_dbg(SCAN, "Broadcast scan\n");
--
-- passive_scan = cfg->active_scan ? 0 : 1;
-- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
-- passive_scan);
-- if (err) {
-- brcmf_err("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
-- goto scan_out;
-- }
-- brcmf_scan_config_mpc(ifp, 0);
-- err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, &ssid_le,
-- sizeof(ssid_le));
-- if (err) {
-- if (err == -EBUSY)
-- brcmf_dbg(INFO, "BUSY: scan for \"%s\" canceled\n",
-- ssid_le.SSID);
-- else
-- brcmf_err("WLC_SCAN error (%d)\n", err);
--
-- brcmf_scan_config_mpc(ifp, 1);
-- goto scan_out;
-- }
-- }
-+
-+ cfg->escan_info.run = brcmf_run_escan;
-+ err = brcmf_p2p_scan_prep(wiphy, request, vif);
-+ if (err)
-+ goto scan_out;
-+
-+ err = brcmf_do_escan(vif->ifp, request);
-+ if (err)
-+ goto scan_out;
-
- /* Arm scan timeout timer */
- mod_timer(&cfg->escan_timeout, jiffies +
-@@ -1191,7 +1137,7 @@ brcmf_cfg80211_scan(struct wiphy *wiphy,
- if (!check_vif_up(vif))
- return -EIO;
-
-- err = brcmf_cfg80211_escan(wiphy, vif, request, NULL);
-+ err = brcmf_cfg80211_escan(wiphy, vif, request);
-
- if (err)
- brcmf_err("scan error (%d)\n", err);
+++ /dev/null
-From df2d8388bc96c0f29d27d121f2a4cd054f8b3900 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 8 Nov 2017 14:36:34 +0100
-Subject: [PATCH] brcmfmac: use msecs_to_jiffies() instead of calculation using
- HZ
-
-Minor cleanup using provided macro to convert milliseconds interval
-to jiffies in brcmf_cfg80211_escan().
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -1115,8 +1115,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
- goto scan_out;
-
- /* Arm scan timeout timer */
-- mod_timer(&cfg->escan_timeout, jiffies +
-- BRCMF_ESCAN_TIMER_INTERVAL_MS * HZ / 1000);
-+ mod_timer(&cfg->escan_timeout,
-+ jiffies + msecs_to_jiffies(BRCMF_ESCAN_TIMER_INTERVAL_MS));
-
- return 0;
-
+++ /dev/null
-From 588378f15cff285ac81c929239ccba01d7f71d50 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 8 Nov 2017 14:36:35 +0100
-Subject: [PATCH] brcmfmac: get rid of brcmf_cfg80211_escan() function
-
-The function brcmf_cfg80211_escan() is only called by brcmf_cfg80211_scan()
-so there is no reason to split in two function especially since the latter
-does not do an awful lot.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 34 +++++++---------------
- 1 file changed, 10 insertions(+), 24 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -1071,13 +1071,16 @@ brcmf_do_escan(struct brcmf_if *ifp, str
- }
-
- static s32
--brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
-- struct cfg80211_scan_request *request)
-+brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
- {
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-- s32 err;
-+ struct brcmf_cfg80211_vif *vif;
-+ s32 err = 0;
-
-- brcmf_dbg(SCAN, "START ESCAN\n");
-+ brcmf_dbg(TRACE, "Enter\n");
-+ vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);
-+ if (!check_vif_up(vif))
-+ return -EIO;
-
- if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
- brcmf_err("Scanning already: status (%lu)\n", cfg->scan_status);
-@@ -1102,6 +1105,8 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
- if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
- vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
-
-+ brcmf_dbg(SCAN, "START ESCAN\n");
-+
- cfg->scan_request = request;
- set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
-
-@@ -1121,31 +1126,12 @@ brcmf_cfg80211_escan(struct wiphy *wiphy
- return 0;
-
- scan_out:
-+ brcmf_err("scan error (%d)\n", err);
- clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status);
- cfg->scan_request = NULL;
- return err;
- }
-
--static s32
--brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
--{
-- struct brcmf_cfg80211_vif *vif;
-- s32 err = 0;
--
-- brcmf_dbg(TRACE, "Enter\n");
-- vif = container_of(request->wdev, struct brcmf_cfg80211_vif, wdev);
-- if (!check_vif_up(vif))
-- return -EIO;
--
-- err = brcmf_cfg80211_escan(wiphy, vif, request);
--
-- if (err)
-- brcmf_err("scan error (%d)\n", err);
--
-- brcmf_dbg(TRACE, "Exit\n");
-- return err;
--}
--
- static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
- {
- s32 err = 0;
+++ /dev/null
-From bbf35414cd23a9d7230bfd7046e1e2c26020e7eb Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 8 Nov 2017 14:36:36 +0100
-Subject: [PATCH] brcmfmac: get rid of struct brcmf_cfg80211_info::active_scan
- field
-
-The field struct brcmf_cfg80211_info::active_scan is set to true upon
-initializing the driver instance, but it is never changed so simply
-get rid of it.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 10 +---------
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h | 2 --
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 5 +----
- 3 files changed, 2 insertions(+), 15 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -1043,7 +1043,6 @@ brcmf_do_escan(struct brcmf_if *ifp, str
- {
- struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
- s32 err;
-- u32 passive_scan;
- struct brcmf_scan_results *results;
- struct escan_info *escan = &cfg->escan_info;
-
-@@ -1051,13 +1050,7 @@ brcmf_do_escan(struct brcmf_if *ifp, str
- escan->ifp = ifp;
- escan->wiphy = cfg->wiphy;
- escan->escan_state = WL_ESCAN_STATE_SCANNING;
-- passive_scan = cfg->active_scan ? 0 : 1;
-- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN,
-- passive_scan);
-- if (err) {
-- brcmf_err("error (%d)\n", err);
-- return err;
-- }
-+
- brcmf_scan_config_mpc(ifp, 0);
- results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf;
- results->version = 0;
-@@ -5767,7 +5760,6 @@ static s32 wl_init_priv(struct brcmf_cfg
-
- cfg->scan_request = NULL;
- cfg->pwr_save = true;
-- cfg->active_scan = true; /* we do active scan per default */
- cfg->dongle_up = false; /* dongle is not up yet */
- err = brcmf_init_priv_mem(cfg);
- if (err)
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
-@@ -283,7 +283,6 @@ struct brcmf_cfg80211_wowl {
- * @scan_status: scan activity on the dongle.
- * @pub: common driver information.
- * @channel: current channel.
-- * @active_scan: current scan mode.
- * @int_escan_map: bucket map for which internal e-scan is done.
- * @ibss_starter: indicates this sta is ibss starter.
- * @pwr_save: indicate whether dongle to support power save mode.
-@@ -316,7 +315,6 @@ struct brcmf_cfg80211_info {
- unsigned long scan_status;
- struct brcmf_pub *pub;
- u32 channel;
-- bool active_scan;
- u32 int_escan_map;
- bool ibss_starter;
- bool pwr_save;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-@@ -692,10 +692,7 @@ static s32 brcmf_p2p_escan(struct brcmf_
-
- /* determine the scan engine parameters */
- sparams->bss_type = DOT11_BSSTYPE_ANY;
-- if (p2p->cfg->active_scan)
-- sparams->scan_type = 0;
-- else
-- sparams->scan_type = 1;
-+ sparams->scan_type = BRCMF_SCANTYPE_ACTIVE;
-
- eth_broadcast_addr(sparams->bssid);
- sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS);
+++ /dev/null
-From bd99a3013bdc00f8fc7534c657b39616792b4467 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 8 Nov 2017 14:36:37 +0100
-Subject: [PATCH] brcmfmac: move configuration of probe request IEs
-
-The configuration of the IEs for probe requests was done in a P2P
-related function, which is not very obvious. Moving it to
-.scan callback function, ie. brcmf_cfg80211_scan().
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 5 +++++
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 6 ++----
- 2 files changed, 7 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -1108,6 +1108,11 @@ brcmf_cfg80211_scan(struct wiphy *wiphy,
- if (err)
- goto scan_out;
-
-+ err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
-+ request->ie, request->ie_len);
-+ if (err)
-+ goto scan_out;
-+
- err = brcmf_do_escan(vif->ifp, request);
- if (err)
- goto scan_out;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-@@ -881,7 +881,7 @@ int brcmf_p2p_scan_prep(struct wiphy *wi
- {
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_p2p_info *p2p = &cfg->p2p;
-- int err = 0;
-+ int err;
-
- if (brcmf_p2p_scan_is_p2p_request(request)) {
- /* find my listen channel */
-@@ -904,9 +904,7 @@ int brcmf_p2p_scan_prep(struct wiphy *wi
- /* override .run_escan() callback. */
- cfg->escan_info.run = brcmf_p2p_run_escan;
- }
-- err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG,
-- request->ie, request->ie_len);
-- return err;
-+ return 0;
- }
-
-
+++ /dev/null
-From fdd0bd88ceaecf729db103ac8836af5805dd2dc1 Mon Sep 17 00:00:00 2001
-From: Chung-Hsien Hsu <stanley.hsu@cypress.com>
-Date: Fri, 10 Nov 2017 17:27:15 +0800
-Subject: [PATCH] brcmfmac: add CLM download support
-
-The firmware for brcmfmac devices includes information regarding
-regulatory constraints. For certain devices this information is kept
-separately in a binary form that needs to be downloaded to the device.
-This patch adds support to download this so-called CLM blob file. It
-uses the same naming scheme as the other firmware files with extension
-of .clm_blob.
-
-The CLM blob file is optional. If the file does not exist, the download
-process will be bypassed. It will not affect the driver loading.
-
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Chung-Hsien Hsu <stanley.hsu@cypress.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 10 ++
- .../wireless/broadcom/brcm80211/brcmfmac/common.c | 157 +++++++++++++++++++++
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 2 +
- .../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 +
- .../broadcom/brcm80211/brcmfmac/fwil_types.h | 31 ++++
- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 19 +++
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 19 +++
- .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 18 +++
- 8 files changed, 258 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-@@ -71,6 +71,7 @@ struct brcmf_bus_dcmd {
- * @wowl_config: specify if dongle is configured for wowl when going to suspend
- * @get_ramsize: obtain size of device memory.
- * @get_memdump: obtain device memory dump in provided buffer.
-+ * @get_fwname: obtain firmware name.
- *
- * This structure provides an abstract interface towards the
- * bus specific driver. For control messages to common driver
-@@ -87,6 +88,8 @@ struct brcmf_bus_ops {
- void (*wowl_config)(struct device *dev, bool enabled);
- size_t (*get_ramsize)(struct device *dev);
- int (*get_memdump)(struct device *dev, void *data, size_t len);
-+ int (*get_fwname)(struct device *dev, uint chip, uint chiprev,
-+ unsigned char *fw_name);
- };
-
-
-@@ -224,6 +227,13 @@ int brcmf_bus_get_memdump(struct brcmf_b
- return bus->ops->get_memdump(bus->dev, data, len);
- }
-
-+static inline
-+int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev,
-+ unsigned char *fw_name)
-+{
-+ return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name);
-+}
-+
- /*
- * interface functions from common layer
- */
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -18,6 +18,7 @@
- #include <linux/string.h>
- #include <linux/netdevice.h>
- #include <linux/module.h>
-+#include <linux/firmware.h>
- #include <brcmu_wifi.h>
- #include <brcmu_utils.h>
- #include "core.h"
-@@ -28,6 +29,7 @@
- #include "tracepoint.h"
- #include "common.h"
- #include "of.h"
-+#include "firmware.h"
-
- MODULE_AUTHOR("Broadcom Corporation");
- MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
-@@ -104,12 +106,140 @@ void brcmf_c_set_joinpref_default(struct
- brcmf_err("Set join_pref error (%d)\n", err);
- }
-
-+static int brcmf_c_download(struct brcmf_if *ifp, u16 flag,
-+ struct brcmf_dload_data_le *dload_buf,
-+ u32 len)
-+{
-+ s32 err;
-+
-+ flag |= (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT);
-+ dload_buf->flag = cpu_to_le16(flag);
-+ dload_buf->dload_type = cpu_to_le16(DL_TYPE_CLM);
-+ dload_buf->len = cpu_to_le32(len);
-+ dload_buf->crc = cpu_to_le32(0);
-+ len = sizeof(*dload_buf) + len - 1;
-+
-+ err = brcmf_fil_iovar_data_set(ifp, "clmload", dload_buf, len);
-+
-+ return err;
-+}
-+
-+static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name)
-+{
-+ struct brcmf_bus *bus = ifp->drvr->bus_if;
-+ struct brcmf_rev_info *ri = &ifp->drvr->revinfo;
-+ u8 fw_name[BRCMF_FW_NAME_LEN];
-+ u8 *ptr;
-+ size_t len;
-+ s32 err;
-+
-+ memset(fw_name, 0, BRCMF_FW_NAME_LEN);
-+ err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name);
-+ if (err) {
-+ brcmf_err("get firmware name failed (%d)\n", err);
-+ goto done;
-+ }
-+
-+ /* generate CLM blob file name */
-+ ptr = strrchr(fw_name, '.');
-+ if (!ptr) {
-+ err = -ENOENT;
-+ goto done;
-+ }
-+
-+ len = ptr - fw_name + 1;
-+ if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) {
-+ err = -E2BIG;
-+ } else {
-+ strlcpy(clm_name, fw_name, len);
-+ strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN);
-+ }
-+done:
-+ return err;
-+}
-+
-+static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
-+{
-+ struct device *dev = ifp->drvr->bus_if->dev;
-+ struct brcmf_dload_data_le *chunk_buf;
-+ const struct firmware *clm = NULL;
-+ u8 clm_name[BRCMF_FW_NAME_LEN];
-+ u32 chunk_len;
-+ u32 datalen;
-+ u32 cumulative_len;
-+ u16 dl_flag = DL_BEGIN;
-+ u32 status;
-+ s32 err;
-+
-+ brcmf_dbg(TRACE, "Enter\n");
-+
-+ memset(clm_name, 0, BRCMF_FW_NAME_LEN);
-+ err = brcmf_c_get_clm_name(ifp, clm_name);
-+ if (err) {
-+ brcmf_err("get CLM blob file name failed (%d)\n", err);
-+ return err;
-+ }
-+
-+ err = request_firmware(&clm, clm_name, dev);
-+ if (err) {
-+ if (err == -ENOENT) {
-+ brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n");
-+ return 0;
-+ }
-+ brcmf_err("request CLM blob file failed (%d)\n", err);
-+ return err;
-+ }
-+
-+ chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL);
-+ if (!chunk_buf) {
-+ err = -ENOMEM;
-+ goto done;
-+ }
-+
-+ datalen = clm->size;
-+ cumulative_len = 0;
-+ do {
-+ if (datalen > MAX_CHUNK_LEN) {
-+ chunk_len = MAX_CHUNK_LEN;
-+ } else {
-+ chunk_len = datalen;
-+ dl_flag |= DL_END;
-+ }
-+ memcpy(chunk_buf->data, clm->data + cumulative_len, chunk_len);
-+
-+ err = brcmf_c_download(ifp, dl_flag, chunk_buf, chunk_len);
-+
-+ dl_flag &= ~DL_BEGIN;
-+
-+ cumulative_len += chunk_len;
-+ datalen -= chunk_len;
-+ } while ((datalen > 0) && (err == 0));
-+
-+ if (err) {
-+ brcmf_err("clmload (%zu byte file) failed (%d); ",
-+ clm->size, err);
-+ /* Retrieve clmload_status and print */
-+ err = brcmf_fil_iovar_int_get(ifp, "clmload_status", &status);
-+ if (err)
-+ brcmf_err("get clmload_status failed (%d)\n", err);
-+ else
-+ brcmf_dbg(INFO, "clmload_status=%d\n", status);
-+ err = -EIO;
-+ }
-+
-+ kfree(chunk_buf);
-+done:
-+ release_firmware(clm);
-+ return err;
-+}
-+
- int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
- {
- s8 eventmask[BRCMF_EVENTING_MASK_LEN];
- u8 buf[BRCMF_DCMD_SMLEN];
- struct brcmf_rev_info_le revinfo;
- struct brcmf_rev_info *ri;
-+ char *clmver;
- char *ptr;
- s32 err;
-
-@@ -148,6 +278,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
- }
- ri->result = err;
-
-+ /* Do any CLM downloading */
-+ err = brcmf_c_process_clm_blob(ifp);
-+ if (err < 0) {
-+ brcmf_err("download CLM blob file failed, %d\n", err);
-+ goto done;
-+ }
-+
- /* query for 'ver' to get version info from firmware */
- memset(buf, 0, sizeof(buf));
- strcpy(buf, "ver");
-@@ -167,6 +304,26 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
- ptr = strrchr(buf, ' ') + 1;
- strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
-
-+ /* Query for 'clmver' to get CLM version info from firmware */
-+ memset(buf, 0, sizeof(buf));
-+ err = brcmf_fil_iovar_data_get(ifp, "clmver", buf, sizeof(buf));
-+ if (err) {
-+ brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err);
-+ } else {
-+ clmver = (char *)buf;
-+ /* store CLM version for adding it to revinfo debugfs file */
-+ memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver));
-+
-+ /* Replace all newline/linefeed characters with space
-+ * character
-+ */
-+ ptr = clmver;
-+ while ((ptr = strnchr(ptr, '\n', sizeof(buf))) != NULL)
-+ *ptr = ' ';
-+
-+ brcmf_dbg(INFO, "CLM version = %s\n", clmver);
-+ }
-+
- /* set mpc */
- err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
- if (err) {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1009,6 +1009,8 @@ static int brcmf_revinfo_read(struct seq
- seq_printf(s, "anarev: %u\n", ri->anarev);
- seq_printf(s, "nvramrev: %08x\n", ri->nvramrev);
-
-+ seq_printf(s, "clmver: %s\n", bus_if->drvr->clmver);
-+
- return 0;
- }
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-@@ -141,6 +141,8 @@ struct brcmf_pub {
- struct notifier_block inetaddr_notifier;
- struct notifier_block inet6addr_notifier;
- struct brcmf_mp_device *settings;
-+
-+ u8 clmver[BRCMF_DCMD_SMLEN];
- };
-
- /* forward declarations */
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
-@@ -155,6 +155,21 @@
- #define BRCMF_MFP_CAPABLE 1
- #define BRCMF_MFP_REQUIRED 2
-
-+/* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each
-+ * ioctl. It is relatively small because firmware has small maximum size input
-+ * playload restriction for ioctls.
-+ */
-+#define MAX_CHUNK_LEN 1400
-+
-+#define DLOAD_HANDLER_VER 1 /* Downloader version */
-+#define DLOAD_FLAG_VER_MASK 0xf000 /* Downloader version mask */
-+#define DLOAD_FLAG_VER_SHIFT 12 /* Downloader version shift */
-+
-+#define DL_BEGIN 0x0002
-+#define DL_END 0x0004
-+
-+#define DL_TYPE_CLM 2
-+
- /* join preference types for join_pref iovar */
- enum brcmf_join_pref_types {
- BRCMF_JOIN_PREF_RSSI = 1,
-@@ -827,6 +842,22 @@ struct brcmf_pno_macaddr_le {
- };
-
- /**
-+ * struct brcmf_dload_data_le - data passing to firmware for downloading
-+ * @flag: flags related to download data.
-+ * @dload_type: type of download data.
-+ * @len: length in bytes of download data.
-+ * @crc: crc of download data.
-+ * @data: download data.
-+ */
-+struct brcmf_dload_data_le {
-+ __le16 flag;
-+ __le16 dload_type;
-+ __le32 len;
-+ __le32 crc;
-+ u8 data[1];
-+};
-+
-+/**
- * struct brcmf_pno_bssid_le - bssid configuration for PNO scan.
- *
- * @bssid: BSS network identifier.
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -1350,6 +1350,24 @@ static int brcmf_pcie_get_memdump(struct
- return 0;
- }
-
-+static int brcmf_pcie_get_fwname(struct device *dev, u32 chip, u32 chiprev,
-+ u8 *fw_name)
-+{
-+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-+ struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
-+ struct brcmf_pciedev_info *devinfo = buspub->devinfo;
-+ int ret = 0;
-+
-+ if (devinfo->fw_name[0] != '\0')
-+ strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
-+ else
-+ ret = brcmf_fw_map_chip_to_name(chip, chiprev,
-+ brcmf_pcie_fwnames,
-+ ARRAY_SIZE(brcmf_pcie_fwnames),
-+ fw_name, NULL);
-+
-+ return ret;
-+}
-
- static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
- .txdata = brcmf_pcie_tx,
-@@ -1359,6 +1377,7 @@ static const struct brcmf_bus_ops brcmf_
- .wowl_config = brcmf_pcie_wowl_config,
- .get_ramsize = brcmf_pcie_get_ramsize,
- .get_memdump = brcmf_pcie_get_memdump,
-+ .get_fwname = brcmf_pcie_get_fwname,
- };
-
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -3985,6 +3985,24 @@ brcmf_sdio_watchdog(unsigned long data)
- }
- }
-
-+static int brcmf_sdio_get_fwname(struct device *dev, u32 chip, u32 chiprev,
-+ u8 *fw_name)
-+{
-+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-+ int ret = 0;
-+
-+ if (sdiodev->fw_name[0] != '\0')
-+ strlcpy(fw_name, sdiodev->fw_name, BRCMF_FW_NAME_LEN);
-+ else
-+ ret = brcmf_fw_map_chip_to_name(chip, chiprev,
-+ brcmf_sdio_fwnames,
-+ ARRAY_SIZE(brcmf_sdio_fwnames),
-+ fw_name, NULL);
-+
-+ return ret;
-+}
-+
- static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
- .stop = brcmf_sdio_bus_stop,
- .preinit = brcmf_sdio_bus_preinit,
-@@ -3995,6 +4013,7 @@ static const struct brcmf_bus_ops brcmf_
- .wowl_config = brcmf_sdio_wowl_config,
- .get_ramsize = brcmf_sdio_bus_get_ramsize,
- .get_memdump = brcmf_sdio_bus_get_memdump,
-+ .get_fwname = brcmf_sdio_get_fwname,
- };
-
- static void brcmf_sdio_firmware_callback(struct device *dev, int err,
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -1128,12 +1128,30 @@ static void brcmf_usb_wowl_config(struct
- device_set_wakeup_enable(devinfo->dev, false);
- }
-
-+static int brcmf_usb_get_fwname(struct device *dev, u32 chip, u32 chiprev,
-+ u8 *fw_name)
-+{
-+ struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
-+ int ret = 0;
-+
-+ if (devinfo->fw_name[0] != '\0')
-+ strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
-+ else
-+ ret = brcmf_fw_map_chip_to_name(chip, chiprev,
-+ brcmf_usb_fwnames,
-+ ARRAY_SIZE(brcmf_usb_fwnames),
-+ fw_name, NULL);
-+
-+ return ret;
-+}
-+
- static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
- .txdata = brcmf_usb_tx,
- .stop = brcmf_usb_down,
- .txctl = brcmf_usb_tx_ctlpkt,
- .rxctl = brcmf_usb_rx_ctlpkt,
- .wowl_config = brcmf_usb_wowl_config,
-+ .get_fwname = brcmf_usb_get_fwname,
- };
-
- static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
+++ /dev/null
-From 5c3de777bdaf48bd0cfb43097c0d0fb85056cab7 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Sat, 25 Nov 2017 21:39:25 +0100
-Subject: [PATCH] brcmfmac: change driver unbind order of the sdio function
- devices
-
-In the function brcmf_sdio_firmware_callback() the driver is
-unbound from the sdio function devices in the error path.
-However, the order in which it is done resulted in a use-after-free
-issue (see brcmf_ops_sdio_remove() in bcmsdh.c). Hence change
-the order and first unbind sdio function #2 device and then
-unbind sdio function #1 device.
-
-Cc: stable@vger.kernel.org # v4.12.x
-Fixes: 7a51461fc2da ("brcmfmac: unbind all devices upon failure in firmware callback")
-Reported-by: Stefan Wahren <stefan.wahren@i2se.com>
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -4121,8 +4121,8 @@ release:
- sdio_release_host(sdiodev->func[1]);
- fail:
- brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
-- device_release_driver(dev);
- device_release_driver(&sdiodev->func[2]->dev);
-+ device_release_driver(dev);
- }
-
- struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
+++ /dev/null
-From 51ef7925e10688c57186d438e784532e063492e4 Mon Sep 17 00:00:00 2001
-From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-Date: Thu, 23 Nov 2017 17:57:04 +0200
-Subject: [PATCH] brcmfmac: Avoid build error with make W=1
-
-When I run make W=1 on gcc (Debian 7.2.0-16) 7.2.0 I got an error for
-the first run, all next ones are okay.
-
- CC [M] drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.o
-drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:2078: error: Cannot parse struct or union!
-scripts/Makefile.build:310: recipe for target 'drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.o' failed
-
-Seems like something happened with W=1 and wrong kernel doc format.
-As a quick fix remove dubious /** in the code.
-
-Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -2070,7 +2070,7 @@ static int brcmf_sdio_txpkt_hdalign(stru
- return head_pad;
- }
-
--/**
-+/*
- * struct brcmf_skbuff_cb reserves first two bytes in sk_buff::cb for
- * bus layer usage.
- */
+++ /dev/null
-From cc124d5cc8d81985c3511892d7a6d546552ff754 Mon Sep 17 00:00:00 2001
-From: Wright Feng <wright.feng@cypress.com>
-Date: Tue, 16 Jan 2018 17:26:50 +0800
-Subject: [PATCH] brcmfmac: fix CLM load error for legacy chips when user
- helper is enabled
-
-For legacy chips without CLM blob files, kernel with user helper function
-returns -EAGAIN when we request_firmware(), and then driver got failed
-when bringing up legacy chips. We expect the CLM blob file for legacy chip
-is not existence in firmware path, but the -ENOENT error is transferred to
--EAGAIN in firmware_class.c with user helper.
-Because of that, we continue with CLM data currently present in firmware
-if getting error from doing request_firmware().
-
-Cc: stable@vger.kernel.org # v4.15.y
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Wright Feng <wright.feng@cypress.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 9 +++------
- 1 file changed, 3 insertions(+), 6 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -182,12 +182,9 @@ static int brcmf_c_process_clm_blob(stru
-
- err = request_firmware(&clm, clm_name, dev);
- if (err) {
-- if (err == -ENOENT) {
-- brcmf_dbg(INFO, "continue with CLM data currently present in firmware\n");
-- return 0;
-- }
-- brcmf_err("request CLM blob file failed (%d)\n", err);
-- return err;
-+ brcmf_info("no clm_blob available(err=%d), device may have limited channels available\n",
-+ err);
-+ return 0;
- }
-
- chunk_buf = kzalloc(sizeof(*chunk_buf) + MAX_CHUNK_LEN - 1, GFP_KERNEL);
+++ /dev/null
-From 9df7ddc3ed25b7d3473f117a0680b9418adb5753 Mon Sep 17 00:00:00 2001
-Message-Id: <9df7ddc3ed25b7d3473f117a0680b9418adb5753.1515610034.git.mschiffer@universe-factory.net>
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Mon, 27 Nov 2017 18:56:22 +0100
-Subject: [PATCH 1/2] ath9k: move spectral scan support under a separate config
- symbol
-
-At the moment, spectral scan support, and with it RELAY, is always enabled
-with ATH9K[_HTC]_DEBUGFS. Spectral scan support is currently the only user
-of RELAY in ath9k, and it unconditionally reserves a relay channel.
-
-Having debugfs support in ath9k is often useful even on very small embedded
-routers, where we'd rather like to avoid the code size and RAM usage of the
-relay support.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
----
- drivers/net/wireless/ath/ath9k/Kconfig | 14 ++++++++++----
- drivers/net/wireless/ath/ath9k/Makefile | 4 ++--
- drivers/net/wireless/ath/ath9k/common-spectral.h | 4 ++--
- 3 files changed, 14 insertions(+), 8 deletions(-)
-
---- a/drivers/net/wireless/ath/ath9k/Kconfig
-+++ b/drivers/net/wireless/ath/ath9k/Kconfig
-@@ -64,13 +64,12 @@ config ATH9K_DEBUGFS
- depends on ATH9K && DEBUG_FS
- select MAC80211_DEBUGFS
- select ATH9K_COMMON_DEBUG
-- depends on RELAY
- ---help---
- Say Y, if you need access to ath9k's statistics for
- interrupts, rate control, etc.
-
-- Also required for changing debug message flags at run time.
-- As well as access to the FFT/spectral data and TX99.
-+ Also required for changing debug message flags at run time and for
-+ TX99.
-
- config ATH9K_STATION_STATISTICS
- bool "Detailed station statistics"
-@@ -181,7 +180,6 @@ config ATH9K_HTC_DEBUGFS
- bool "Atheros ath9k_htc debugging"
- depends on ATH9K_HTC && DEBUG_FS
- select ATH9K_COMMON_DEBUG
-- depends on RELAY
- ---help---
- Say Y, if you need access to ath9k_htc's statistics.
- As well as access to the FFT/spectral data.
-@@ -197,3 +195,11 @@ config ATH9K_HWRNG
-
- Say Y, feeds the entropy directly from the WiFi driver to the input
- pool.
-+
-+config ATH9K_COMMON_SPECTRAL
-+ bool "Atheros ath9k/ath9k_htc spectral scan support"
-+ depends on ATH9K_DEBUGFS || ATH9K_HTC_DEBUGFS
-+ depends on RELAY
-+ default n
-+ ---help---
-+ Say Y to enable access to the FFT/spectral data via debugfs.
---- a/drivers/net/wireless/ath/ath9k/Makefile
-+++ b/drivers/net/wireless/ath/ath9k/Makefile
-@@ -61,8 +61,8 @@ ath9k_common-y:= common.o \
- common-init.o \
- common-beacon.o \
-
--ath9k_common-$(CPTCFG_ATH9K_COMMON_DEBUG) += common-debug.o \
-- common-spectral.o
-+ath9k_common-$(CPTCFG_ATH9K_COMMON_DEBUG) += common-debug.o
-+ath9k_common-$(CPTCFG_ATH9K_COMMON_SPECTRAL) += common-spectral.o
-
- ath9k_htc-y += htc_hst.o \
- hif_usb.o \
---- a/drivers/net/wireless/ath/ath9k/common-spectral.h
-+++ b/drivers/net/wireless/ath/ath9k/common-spectral.h
-@@ -151,7 +151,7 @@ static inline u8 spectral_bitmap_weight(
- return bins[0] & 0x3f;
- }
-
--#ifdef CPTCFG_ATH9K_COMMON_DEBUG
-+#ifdef CPTCFG_ATH9K_COMMON_SPECTRAL
- void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy);
- void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv);
-
-@@ -183,6 +183,6 @@ static inline int ath_cmn_process_fft(st
- {
- return 0;
- }
--#endif /* CPTCFG_ATH9K_COMMON_DEBUG */
-+#endif /* CPTCFG_ATH9K_COMMON_SPECTRAL */
-
- #endif /* SPECTRAL_H */
---- a/local-symbols
-+++ b/local-symbols
-@@ -116,6 +116,7 @@ ATH9K_PCOEM=
- ATH9K_HTC=
- ATH9K_HTC_DEBUGFS=
- ATH9K_HWRNG=
-+ATH9K_COMMON_SPECTRAL=
- CARL9170=
- CARL9170_LEDS=
- CARL9170_DEBUGFS=
+++ /dev/null
-From 42e01cb9cb109fb0bb4743f6c54d6aa67ac39b61 Mon Sep 17 00:00:00 2001
-Message-Id: <42e01cb9cb109fb0bb4743f6c54d6aa67ac39b61.1515610034.git.mschiffer@universe-factory.net>
-In-Reply-To: <9df7ddc3ed25b7d3473f117a0680b9418adb5753.1515610034.git.mschiffer@universe-factory.net>
-References: <9df7ddc3ed25b7d3473f117a0680b9418adb5753.1515610034.git.mschiffer@universe-factory.net>
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Mon, 27 Nov 2017 18:56:23 +0100
-Subject: [PATCH 2/2] ath10k: move spectral scan support under a separate
- config symbol
-
-At the moment, spectral scan support, and with it RELAY, is always enabled
-with ATH10K_DEBUGFS. Spectral scan support is currently the only user of
-RELAY in ath10k, and it unconditionally reserves a relay channel.
-
-Having debugfs support in ath10k is often useful even on very small
-embedded routers, where we'd rather like to avoid the code size and RAM
-usage of the relay support. While ath10k-based devices usually have more
-resources than ath9k-based ones, it makes sense to keep the configuration
-symmetric to ath9k, so the same base kernel without RELAY can be used for
-both ath9k and ath10k hardware.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
-Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
----
- drivers/net/wireless/ath/ath10k/Kconfig | 9 ++++++++-
- drivers/net/wireless/ath/ath10k/Makefile | 2 +-
- drivers/net/wireless/ath/ath10k/spectral.h | 4 ++--
- 3 files changed, 11 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/Kconfig
-+++ b/drivers/net/wireless/ath/ath10k/Kconfig
-@@ -51,12 +51,19 @@ config ATH10K_DEBUG
- config ATH10K_DEBUGFS
- bool "Atheros ath10k debugfs support"
- depends on ATH10K && DEBUG_FS
-- depends on RELAY
- ---help---
- Enabled debugfs support
-
- If unsure, say Y to make it easier to debug problems.
-
-+config ATH10K_SPECTRAL
-+ bool "Atheros ath10k spectral scan support"
-+ depends on ATH10K_DEBUGFS
-+ depends on RELAY
-+ default n
-+ ---help---
-+ Say Y to enable access to the FFT/spectral data via debugfs.
-+
- config ATH10K_TRACING
- depends on !KERNEL_3_4
- bool "Atheros ath10k tracing support"
---- a/drivers/net/wireless/ath/ath10k/Makefile
-+++ b/drivers/net/wireless/ath/ath10k/Makefile
-@@ -14,7 +14,7 @@ ath10k_core-y += mac.o \
- p2p.o \
- swap.o
-
--ath10k_core-$(CPTCFG_ATH10K_DEBUGFS) += spectral.o
-+ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += spectral.o
- ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o
- ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
- ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
---- a/drivers/net/wireless/ath/ath10k/spectral.h
-+++ b/drivers/net/wireless/ath/ath10k/spectral.h
-@@ -44,7 +44,7 @@ enum ath10k_spectral_mode {
- SPECTRAL_MANUAL,
- };
-
--#ifdef CPTCFG_ATH10K_DEBUGFS
-+#ifdef CPTCFG_ATH10K_SPECTRAL
-
- int ath10k_spectral_process_fft(struct ath10k *ar,
- struct wmi_phyerr_ev_arg *phyerr,
-@@ -85,6 +85,6 @@ static inline void ath10k_spectral_destr
- {
- }
-
--#endif /* CPTCFG_ATH10K_DEBUGFS */
-+#endif /* CPTCFG_ATH10K_SPECTRAL */
-
- #endif /* SPECTRAL_H */
---- a/local-symbols
-+++ b/local-symbols
-@@ -140,6 +140,7 @@ ATH10K_SDIO=
- ATH10K_USB=
- ATH10K_DEBUG=
- ATH10K_DEBUGFS=
-+ATH10K_SPECTRAL=
- ATH10K_THERMAL=
- ATH10K_TRACING=
- ATH10K_DFS_CERTIFIED=
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 17 Jan 2018 11:11:17 +0100
-Subject: [PATCH] ath9k: discard undersized packets
-
-Sometimes the hardware will push small packets that trigger a WARN_ON
-in mac80211. Discard them early to avoid this issue.
-
-Reported-by: Stijn Tintel <stijn@linux-ipv6.be>
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/recv.c
-+++ b/drivers/net/wireless/ath/ath9k/recv.c
-@@ -826,9 +826,9 @@ static int ath9k_rx_skb_preprocess(struc
- sc->rx.discard_next = false;
-
- /*
-- * Discard zero-length packets.
-+ * Discard zero-length packets and packets smaller than an ACK
- */
-- if (!rx_stats->rs_datalen) {
-+ if (rx_stats->rs_datalen < 10) {
- RX_STAT_INC(rx_len_err);
- goto corrupt;
- }
+++ /dev/null
-From 1fd3ae124d5e675f57cf7e3c601fb8f7712e0329 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:38 +0100
-Subject: [PATCH] brcmfmac: Fix parameter order in brcmf_sdiod_f0_writeb()
-
-All the other IO functions are the other way round in this
-driver. Make this one match.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -230,8 +230,8 @@ void brcmf_sdiod_change_state(struct brc
- sdiodev->state = state;
- }
-
--static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func,
-- uint regaddr, u8 byte)
-+static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte,
-+ uint regaddr)
- {
- int err_ret;
-
-@@ -269,8 +269,8 @@ static int brcmf_sdiod_request_data(stru
- if (fn)
- sdio_writeb(func, *(u8 *)data, addr, &ret);
- else
-- ret = brcmf_sdiod_f0_writeb(func, addr,
-- *(u8 *)data);
-+ ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data,
-+ addr);
- } else {
- if (fn)
- *(u8 *)data = sdio_readb(func, addr, &ret);
+++ /dev/null
-From 1e6f676f43aa4270ebc5cff8e32a55f72362e042 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:39 +0100
-Subject: [PATCH] brcmfmac: Register sizes on hardware are not dependent on
- compiler types
-
-The 4 IO functions in this patch are incorrect as they use compiler types
-to determine how many bytes to send to the hardware.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 22 +++++++++++-----------
- 1 file changed, 11 insertions(+), 11 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -264,7 +264,7 @@ static int brcmf_sdiod_request_data(stru
- func = sdiodev->func[fn];
-
- switch (regsz) {
-- case sizeof(u8):
-+ case 1:
- if (write) {
- if (fn)
- sdio_writeb(func, *(u8 *)data, addr, &ret);
-@@ -278,13 +278,13 @@ static int brcmf_sdiod_request_data(stru
- *(u8 *)data = sdio_f0_readb(func, addr, &ret);
- }
- break;
-- case sizeof(u16):
-+ case 2:
- if (write)
- sdio_writew(func, *(u16 *)data, addr, &ret);
- else
- *(u16 *)data = sdio_readw(func, addr, &ret);
- break;
-- case sizeof(u32):
-+ case 4:
- if (write)
- sdio_writel(func, *(u32 *)data, addr, &ret);
- else
-@@ -368,7 +368,7 @@ brcmf_sdiod_set_sbaddr_window(struct brc
- for (i = 0; i < 3; i++) {
- err = brcmf_sdiod_regrw_helper(sdiodev,
- SBSDIO_FUNC1_SBADDRLOW + i,
-- sizeof(u8), &addr[i], true);
-+ 1, &addr[i], true);
- if (err) {
- brcmf_err("failed at addr: 0x%0x\n",
- SBSDIO_FUNC1_SBADDRLOW + i);
-@@ -407,7 +407,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
-- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
-+ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data,
- false);
- brcmf_dbg(SDIO, "data:0x%02x\n", data);
-
-@@ -423,10 +423,10 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
-- retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr);
-+ retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
- if (retval)
- goto done;
-- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
-+ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data,
- false);
- brcmf_dbg(SDIO, "data:0x%08x\n", data);
-
-@@ -443,7 +443,7 @@ void brcmf_sdiod_regwb(struct brcmf_sdio
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
-- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
-+ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data,
- true);
- if (ret)
- *ret = retval;
-@@ -455,10 +455,10 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
-- retval = brcmf_sdiod_addrprep(sdiodev, sizeof(data), &addr);
-+ retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
- if (retval)
- goto done;
-- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, sizeof(data), &data,
-+ retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data,
- true);
-
- done:
-@@ -876,7 +876,7 @@ int brcmf_sdiod_abort(struct brcmf_sdio_
-
- /* issue abort cmd52 command through F0 */
- brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT,
-- sizeof(t_func), &t_func, true);
-+ 1, &t_func, true);
-
- brcmf_dbg(SDIO, "Exit\n");
- return 0;
+++ /dev/null
-From 0fcc9fe0048422d66bb906eaa73cc75e11ff7345 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:40 +0100
-Subject: [PATCH] brcmfmac: Split brcmf_sdiod_regrw_helper() up.
-
-This large function is concealing a LOT of obscure logic about
-how the hardware functions. Time to split it up.
-
-This first patch splits the function into two pieces - read and write,
-doing away with the rw flag in the process.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 94 +++++++++++++++++-----
- 1 file changed, 73 insertions(+), 21 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -302,8 +302,8 @@ static int brcmf_sdiod_request_data(stru
- return ret;
- }
-
--static int brcmf_sdiod_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
-- u8 regsz, void *data, bool write)
-+static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr,
-+ u8 regsz, void *data)
- {
- u8 func;
- s32 retry = 0;
-@@ -324,13 +324,66 @@ static int brcmf_sdiod_regrw_helper(stru
- func = SDIO_FUNC_1;
-
- do {
-- if (!write)
-- memset(data, 0, regsz);
- /* for retry wait for 1 ms till bus get settled down */
- if (retry)
- usleep_range(1000, 2000);
-+
-+ ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
-+ data, true);
-+
-+ } while (ret != 0 && ret != -ENOMEDIUM &&
-+ retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
-+
-+ if (ret == -ENOMEDIUM) {
-+ brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-+ } else if (ret != 0) {
-+ /*
-+ * SleepCSR register access can fail when
-+ * waking up the device so reduce this noise
-+ * in the logs.
-+ */
-+ if (addr != SBSDIO_FUNC1_SLEEPCSR)
-+ brcmf_err("failed to write data F%d@0x%05x, err: %d\n",
-+ func, addr, ret);
-+ else
-+ brcmf_dbg(SDIO, "failed to write data F%d@0x%05x, err: %d\n",
-+ func, addr, ret);
-+ }
-+
-+ return ret;
-+}
-+
-+static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr,
-+ u8 regsz, void *data)
-+{
-+ u8 func;
-+ s32 retry = 0;
-+ int ret;
-+
-+ if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
-+ return -ENOMEDIUM;
-+
-+ /*
-+ * figure out how to read the register based on address range
-+ * 0x00 ~ 0x7FF: function 0 CCCR and FBR
-+ * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
-+ * The rest: function 1 silicon backplane core registers
-+ */
-+ if ((addr & ~REG_F0_REG_MASK) == 0)
-+ func = SDIO_FUNC_0;
-+ else
-+ func = SDIO_FUNC_1;
-+
-+ do {
-+ memset(data, 0, regsz);
-+
-+ /* for retry wait for 1 ms till bus get settled down */
-+ if (retry)
-+ usleep_range(1000, 2000);
-+
- ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
-- data, write);
-+ data, false);
-+
- } while (ret != 0 && ret != -ENOMEDIUM &&
- retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
-
-@@ -343,12 +396,13 @@ static int brcmf_sdiod_regrw_helper(stru
- * in the logs.
- */
- if (addr != SBSDIO_FUNC1_SLEEPCSR)
-- brcmf_err("failed to %s data F%d@0x%05x, err: %d\n",
-- write ? "write" : "read", func, addr, ret);
-+ brcmf_err("failed to read data F%d@0x%05x, err: %d\n",
-+ func, addr, ret);
- else
-- brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
-- write ? "write" : "read", func, addr, ret);
-+ brcmf_dbg(SDIO, "failed to read data F%d@0x%05x, err: %d\n",
-+ func, addr, ret);
- }
-+
- return ret;
- }
-
-@@ -366,13 +420,11 @@ brcmf_sdiod_set_sbaddr_window(struct brc
- addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
-
- for (i = 0; i < 3; i++) {
-- err = brcmf_sdiod_regrw_helper(sdiodev,
-- SBSDIO_FUNC1_SBADDRLOW + i,
-- 1, &addr[i], true);
-+ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, addr[i],
-+ &err);
- if (err) {
- brcmf_err("failed at addr: 0x%0x\n",
- SBSDIO_FUNC1_SBADDRLOW + i);
-- break;
- }
- }
-
-@@ -407,8 +459,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
-- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data,
-- false);
-+ retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data);
- brcmf_dbg(SDIO, "data:0x%02x\n", data);
-
- if (ret)
-@@ -426,8 +477,9 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
- retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
- if (retval)
- goto done;
-- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data,
-- false);
-+
-+ retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
-+
- brcmf_dbg(SDIO, "data:0x%08x\n", data);
-
- done:
-@@ -443,8 +495,8 @@ void brcmf_sdiod_regwb(struct brcmf_sdio
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
-- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 1, &data,
-- true);
-+ retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data);
-+
- if (ret)
- *ret = retval;
- }
-@@ -458,8 +510,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
- retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
- if (retval)
- goto done;
-- retval = brcmf_sdiod_regrw_helper(sdiodev, addr, 4, &data,
-- true);
-+
-+ retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
-
- done:
- if (ret)
+++ /dev/null
-From b9b0d290bc0c90a5a262bc89c9d995988ea98669 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:41 +0100
-Subject: [PATCH] brcmfmac: Clean up brcmf_sdiod_set_sbaddr_window()
-
-This function sets the address of the IO window used for
-SDIO accesses onto the backplane of the chip.
-
-It currently uses 3 separate masks despite the full mask being
-defined in the code already. Remove the separate masks and clean up.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 17 +++++------------
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 3 ---
- 2 files changed, 5 insertions(+), 15 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -410,23 +410,16 @@ static int
- brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
- {
- int err = 0, i;
-- u8 addr[3];
-+ u32 addr;
-
- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
- return -ENOMEDIUM;
-
-- addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK;
-- addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK;
-- addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK;
-+ addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
-
-- for (i = 0; i < 3; i++) {
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i, addr[i],
-- &err);
-- if (err) {
-- brcmf_err("failed at addr: 0x%0x\n",
-- SBSDIO_FUNC1_SBADDRLOW + i);
-- }
-- }
-+ for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
-+ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
-+ addr & 0xff, &err);
-
- return err;
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -133,9 +133,6 @@
-
- /* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
-
--#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */
--#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */
--#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */
- /* Address bits from SBADDR regs */
- #define SBSDIO_SBWINDOW_MASK 0xffff8000
-
+++ /dev/null
-From ea243e9077b3545f20d93884e91c50ac0719685a Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:42 +0100
-Subject: [PATCH] brcmfmac: Remove dead IO code
-
-The value passed to brcmf_sdiod_addrprep() is *always* 4
-remove this parameter and the unused code to handle it.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 18 ++++++++----------
- 1 file changed, 8 insertions(+), 10 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -425,7 +425,7 @@ brcmf_sdiod_set_sbaddr_window(struct brc
- }
-
- static int
--brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr)
-+brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
- {
- uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
- int err = 0;
-@@ -439,9 +439,7 @@ brcmf_sdiod_addrprep(struct brcmf_sdio_d
- }
-
- *addr &= SBSDIO_SB_OFT_ADDR_MASK;
--
-- if (width == 4)
-- *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-+ *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- return 0;
- }
-@@ -467,7 +465,7 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
-- retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
-+ retval = brcmf_sdiod_addrprep(sdiodev, &addr);
- if (retval)
- goto done;
-
-@@ -500,7 +498,7 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
-- retval = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
-+ retval = brcmf_sdiod_addrprep(sdiodev, &addr);
- if (retval)
- goto done;
-
-@@ -736,7 +734,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
-
- brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
-
-- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
-+ err = brcmf_sdiod_addrprep(sdiodev, &addr);
- if (err)
- goto done;
-
-@@ -757,7 +755,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_
- brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n",
- addr, pktq->qlen);
-
-- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
-+ err = brcmf_sdiod_addrprep(sdiodev, &addr);
- if (err)
- goto done;
-
-@@ -801,7 +799,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
-
- memcpy(mypkt->data, buf, nbytes);
-
-- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
-+ err = brcmf_sdiod_addrprep(sdiodev, &addr);
-
- if (!err)
- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, addr,
-@@ -821,7 +819,7 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
-
- brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen);
-
-- err = brcmf_sdiod_addrprep(sdiodev, 4, &addr);
-+ err = brcmf_sdiod_addrprep(sdiodev, &addr);
- if (err)
- return err;
-
+++ /dev/null
-From 4a3338ba2a7421db2260159cca5a27bd2ee36d00 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:43 +0100
-Subject: [PATCH] brcmfmac: Remove bandaid for SleepCSR
-
-Register access code is not the place for band-aid fixes like this.
-If this is a genuine problem, it should be fixed further up in the driver
-stack.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 28 +---------------------
- 1 file changed, 1 insertion(+), 27 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -334,21 +334,8 @@ static int brcmf_sdiod_reg_write(struct
- } while (ret != 0 && ret != -ENOMEDIUM &&
- retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
-
-- if (ret == -ENOMEDIUM) {
-+ if (ret == -ENOMEDIUM)
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-- } else if (ret != 0) {
-- /*
-- * SleepCSR register access can fail when
-- * waking up the device so reduce this noise
-- * in the logs.
-- */
-- if (addr != SBSDIO_FUNC1_SLEEPCSR)
-- brcmf_err("failed to write data F%d@0x%05x, err: %d\n",
-- func, addr, ret);
-- else
-- brcmf_dbg(SDIO, "failed to write data F%d@0x%05x, err: %d\n",
-- func, addr, ret);
-- }
-
- return ret;
- }
-@@ -389,19 +376,6 @@ static int brcmf_sdiod_reg_read(struct b
-
- if (ret == -ENOMEDIUM)
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-- else if (ret != 0) {
-- /*
-- * SleepCSR register access can fail when
-- * waking up the device so reduce this noise
-- * in the logs.
-- */
-- if (addr != SBSDIO_FUNC1_SLEEPCSR)
-- brcmf_err("failed to read data F%d@0x%05x, err: %d\n",
-- func, addr, ret);
-- else
-- brcmf_dbg(SDIO, "failed to read data F%d@0x%05x, err: %d\n",
-- func, addr, ret);
-- }
-
- return ret;
- }
+++ /dev/null
-From 993a98a42e6e790fd0d2bf7d55a031513c7ba7dc Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:44 +0100
-Subject: [PATCH] brcmfmac: Remove brcmf_sdiod_request_data()
-
-This function is obfuscating how IO works on this chip. Remove it
-and push its logic into brcmf_sdiod_reg_{read,write}().
-
-Handling of -ENOMEDIUM is altered, but as that's pretty much broken anyway
-we can ignore that.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 237 ++++++++-------------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 2 +-
- 2 files changed, 87 insertions(+), 152 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -230,6 +230,43 @@ void brcmf_sdiod_change_state(struct brc
- sdiodev->state = state;
- }
-
-+static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
-+ u32 address)
-+{
-+ int err = 0, i;
-+ u32 addr;
-+
-+ if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
-+ return -ENOMEDIUM;
-+
-+ addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
-+
-+ for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
-+ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
-+ addr & 0xff, &err);
-+
-+ return err;
-+}
-+
-+static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
-+{
-+ uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
-+ int err = 0;
-+
-+ if (bar0 != sdiodev->sbwad) {
-+ err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
-+ if (err)
-+ return err;
-+
-+ sdiodev->sbwad = bar0;
-+ }
-+
-+ *addr &= SBSDIO_SB_OFT_ADDR_MASK;
-+ *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-+
-+ return 0;
-+}
-+
- static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte,
- uint regaddr)
- {
-@@ -249,173 +286,84 @@ static inline int brcmf_sdiod_f0_writeb(
- return err_ret;
- }
-
--static int brcmf_sdiod_request_data(struct brcmf_sdio_dev *sdiodev, u8 fn,
-- u32 addr, u8 regsz, void *data, bool write)
--{
-- struct sdio_func *func;
-- int ret = -EINVAL;
--
-- brcmf_dbg(SDIO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
-- write, fn, addr, regsz);
--
-- /* only allow byte access on F0 */
-- if (WARN_ON(regsz > 1 && !fn))
-- return -EINVAL;
-- func = sdiodev->func[fn];
--
-- switch (regsz) {
-- case 1:
-- if (write) {
-- if (fn)
-- sdio_writeb(func, *(u8 *)data, addr, &ret);
-- else
-- ret = brcmf_sdiod_f0_writeb(func, *(u8 *)data,
-- addr);
-- } else {
-- if (fn)
-- *(u8 *)data = sdio_readb(func, addr, &ret);
-- else
-- *(u8 *)data = sdio_f0_readb(func, addr, &ret);
-- }
-- break;
-- case 2:
-- if (write)
-- sdio_writew(func, *(u16 *)data, addr, &ret);
-- else
-- *(u16 *)data = sdio_readw(func, addr, &ret);
-- break;
-- case 4:
-- if (write)
-- sdio_writel(func, *(u32 *)data, addr, &ret);
-- else
-- *(u32 *)data = sdio_readl(func, addr, &ret);
-- break;
-- default:
-- brcmf_err("invalid size: %d\n", regsz);
-- break;
-- }
--
-- if (ret)
-- brcmf_dbg(SDIO, "failed to %s data F%d@0x%05x, err: %d\n",
-- write ? "write" : "read", fn, addr, ret);
--
-- return ret;
--}
--
- static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 regsz, void *data)
- {
-- u8 func;
-- s32 retry = 0;
- int ret;
-
-- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
-- return -ENOMEDIUM;
--
- /*
- * figure out how to read the register based on address range
- * 0x00 ~ 0x7FF: function 0 CCCR and FBR
- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
- * The rest: function 1 silicon backplane core registers
-+ * f0 writes must be bytewise
- */
-- if ((addr & ~REG_F0_REG_MASK) == 0)
-- func = SDIO_FUNC_0;
-- else
-- func = SDIO_FUNC_1;
--
-- do {
-- /* for retry wait for 1 ms till bus get settled down */
-- if (retry)
-- usleep_range(1000, 2000);
-
-- ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
-- data, true);
--
-- } while (ret != 0 && ret != -ENOMEDIUM &&
-- retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
-+ if ((addr & ~REG_F0_REG_MASK) == 0) {
-+ if (WARN_ON(regsz > 1))
-+ return -EINVAL;
-+ ret = brcmf_sdiod_f0_writeb(sdiodev->func[0],
-+ *(u8 *)data, addr);
-+ } else {
-+ switch (regsz) {
-+ case 1:
-+ sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret);
-+ break;
-+ case 4:
-+ ret = brcmf_sdiod_addrprep(sdiodev, &addr);
-+ if (ret)
-+ goto done;
-
-- if (ret == -ENOMEDIUM)
-- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-+ sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret);
-+ break;
-+ default:
-+ WARN(1, "Invalid reg size\n");
-+ ret = -EINVAL;
-+ break;
-+ }
-+ }
-
-+done:
- return ret;
- }
-
- static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr,
- u8 regsz, void *data)
- {
-- u8 func;
-- s32 retry = 0;
- int ret;
-
-- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
-- return -ENOMEDIUM;
--
- /*
- * figure out how to read the register based on address range
- * 0x00 ~ 0x7FF: function 0 CCCR and FBR
- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
- * The rest: function 1 silicon backplane core registers
-+ * f0 reads must be bytewise
- */
-- if ((addr & ~REG_F0_REG_MASK) == 0)
-- func = SDIO_FUNC_0;
-- else
-- func = SDIO_FUNC_1;
--
-- do {
-- memset(data, 0, regsz);
--
-- /* for retry wait for 1 ms till bus get settled down */
-- if (retry)
-- usleep_range(1000, 2000);
--
-- ret = brcmf_sdiod_request_data(sdiodev, func, addr, regsz,
-- data, false);
--
-- } while (ret != 0 && ret != -ENOMEDIUM &&
-- retry++ < SDIOH_API_ACCESS_RETRY_LIMIT);
--
-- if (ret == -ENOMEDIUM)
-- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
--
-- return ret;
--}
--
--static int
--brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
--{
-- int err = 0, i;
-- u32 addr;
--
-- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
-- return -ENOMEDIUM;
--
-- addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
--
-- for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
-- addr & 0xff, &err);
--
-- return err;
--}
--
--static int
--brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
--{
-- uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
-- int err = 0;
--
-- if (bar0 != sdiodev->sbwad) {
-- err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
-- if (err)
-- return err;
-+ if ((addr & ~REG_F0_REG_MASK) == 0) {
-+ if (WARN_ON(regsz > 1))
-+ return -EINVAL;
-+ *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret);
-+ } else {
-+ switch (regsz) {
-+ case 1:
-+ *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret);
-+ break;
-+ case 4:
-+ ret = brcmf_sdiod_addrprep(sdiodev, &addr);
-+ if (ret)
-+ goto done;
-
-- sdiodev->sbwad = bar0;
-+ *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret);
-+ break;
-+ default:
-+ WARN(1, "Invalid reg size\n");
-+ ret = -EINVAL;
-+ break;
-+ }
- }
-
-- *addr &= SBSDIO_SB_OFT_ADDR_MASK;
-- *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
--
-- return 0;
-+done:
-+ return ret;
- }
-
- u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
-@@ -439,15 +387,9 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
-- retval = brcmf_sdiod_addrprep(sdiodev, &addr);
-- if (retval)
-- goto done;
--
- retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
--
- brcmf_dbg(SDIO, "data:0x%08x\n", data);
-
--done:
- if (ret)
- *ret = retval;
-
-@@ -472,13 +414,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
-- retval = brcmf_sdiod_addrprep(sdiodev, &addr);
-- if (retval)
-- goto done;
--
- retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
-
--done:
- if (ret)
- *ret = retval;
- }
-@@ -886,14 +823,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
- return bcmerror;
- }
-
--int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn)
-+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)
- {
-- char t_func = (char)fn;
- brcmf_dbg(SDIO, "Enter\n");
-
- /* issue abort cmd52 command through F0 */
-- brcmf_sdiod_request_data(sdiodev, SDIO_FUNC_0, SDIO_CCCR_ABORT,
-- 1, &t_func, true);
-+ brcmf_sdiod_reg_write(sdiodev, SDIO_CCCR_ABORT, 1, &fn);
-
- brcmf_dbg(SDIO, "Exit\n");
- return 0;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -339,7 +339,7 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
- u8 *data, uint size);
-
- /* Issue an abort to the specified function */
--int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
-+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn);
- void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
- void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
- enum brcmf_sdiod_state state);
+++ /dev/null
-From 3508a056a1f45d95c874fc9af8748bf4229432b6 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:45 +0100
-Subject: [PATCH] brcmfmac: Fix asymmetric IO functions.
-
-Unlikely to be a problem, but brcmf_sdiod_regrl() is
-not symmetric with brcmf_sdiod_regrb() in initializing
-the data value on stack. Fix that.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-[arend: reword the commit message a bit]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -383,7 +383,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d
-
- u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
- {
-- u32 data = 0;
-+ u32 data;
- int retval;
-
- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
+++ /dev/null
-From 12e3e74e2820e11d91ee44fd3a190cd80d109faa Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:46 +0100
-Subject: [PATCH] brcmfmac: Remove noisy debugging.
-
-If you need debugging this low level, you're doing something wrong.
-Remove these noisy debug statements so the code is more readable.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 6 ------
- 1 file changed, 6 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -371,9 +371,7 @@ u8 brcmf_sdiod_regrb(struct brcmf_sdio_d
- u8 data;
- int retval;
-
-- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
- retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data);
-- brcmf_dbg(SDIO, "data:0x%02x\n", data);
-
- if (ret)
- *ret = retval;
-@@ -386,9 +384,7 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
- u32 data;
- int retval;
-
-- brcmf_dbg(SDIO, "addr:0x%08x\n", addr);
- retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
-- brcmf_dbg(SDIO, "data:0x%08x\n", data);
-
- if (ret)
- *ret = retval;
-@@ -401,7 +397,6 @@ void brcmf_sdiod_regwb(struct brcmf_sdio
- {
- int retval;
-
-- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%02x\n", addr, data);
- retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data);
-
- if (ret)
-@@ -413,7 +408,6 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
- {
- int retval;
-
-- brcmf_dbg(SDIO, "addr:0x%08x, data:0x%08x\n", addr, data);
- retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
-
- if (ret)
+++ /dev/null
-From dd8a2d49e4ed321ab8e7b679499c3a98ccc5ca24 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Mon, 13 Nov 2017 21:35:47 +0100
-Subject: [PATCH] brcmfmac: Rename bcmerror to err
-
-Trivial cleanup of nasty variable name
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 14 +++++++-------
- 1 file changed, 7 insertions(+), 7 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -746,7 +746,7 @@ int
- brcmf_sdiod_ramrw(struct brcmf_sdio_dev *sdiodev, bool write, u32 address,
- u8 *data, uint size)
- {
-- int bcmerror = 0;
-+ int err = 0;
- struct sk_buff *pkt;
- u32 sdaddr;
- uint dsize;
-@@ -771,8 +771,8 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
- /* Do the transfer(s) */
- while (size) {
- /* Set the backplane window to include the start address */
-- bcmerror = brcmf_sdiod_set_sbaddr_window(sdiodev, address);
-- if (bcmerror)
-+ err = brcmf_sdiod_set_sbaddr_window(sdiodev, address);
-+ if (err)
- break;
-
- brcmf_dbg(SDIO, "%s %d bytes at offset 0x%08x in window 0x%08x\n",
-@@ -785,9 +785,9 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
- skb_put(pkt, dsize);
- if (write)
- memcpy(pkt->data, data, dsize);
-- bcmerror = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write,
-- sdaddr, pkt);
-- if (bcmerror) {
-+ err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write, sdaddr,
-+ pkt);
-+ if (err) {
- brcmf_err("membytes transfer failed\n");
- break;
- }
-@@ -814,7 +814,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
-
- sdio_release_host(sdiodev->func[1]);
-
-- return bcmerror;
-+ return err;
- }
-
- int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)
+++ /dev/null
-From 8f13c87ccc495e30de5f58bbda967f6edd5bec53 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:26 +0100
-Subject: [PATCH] brcmfmac: Split brcmf_sdiod_buffrw function up.
-
-This function needs to be split up into separate read / write variants
-for clarity.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 67 +++++++++++++++-------
- 1 file changed, 45 insertions(+), 22 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -414,8 +414,8 @@ void brcmf_sdiod_regwl(struct brcmf_sdio
- *ret = retval;
- }
-
--static int brcmf_sdiod_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
-- bool write, u32 addr, struct sk_buff *pkt)
-+static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev, uint fn,
-+ u32 addr, struct sk_buff *pkt)
- {
- unsigned int req_sz;
- int err;
-@@ -424,18 +424,36 @@ static int brcmf_sdiod_buffrw(struct brc
- req_sz = pkt->len + 3;
- req_sz &= (uint)~3;
-
-- if (write)
-- err = sdio_memcpy_toio(sdiodev->func[fn], addr,
-- ((u8 *)(pkt->data)), req_sz);
-- else if (fn == 1)
-- err = sdio_memcpy_fromio(sdiodev->func[fn], ((u8 *)(pkt->data)),
-- addr, req_sz);
-+ if (fn == 1)
-+ err = sdio_memcpy_fromio(sdiodev->func[fn],
-+ ((u8 *)(pkt->data)), addr, req_sz);
- else
- /* function 2 read is FIFO operation */
-- err = sdio_readsb(sdiodev->func[fn], ((u8 *)(pkt->data)), addr,
-- req_sz);
-+ err = sdio_readsb(sdiodev->func[fn],
-+ ((u8 *)(pkt->data)), addr, req_sz);
-+
-+ if (err == -ENOMEDIUM)
-+ brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-+
-+ return err;
-+}
-+
-+static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev, uint fn,
-+ u32 addr, struct sk_buff *pkt)
-+{
-+ unsigned int req_sz;
-+ int err;
-+
-+ /* Single skb use the standard mmc interface */
-+ req_sz = pkt->len + 3;
-+ req_sz &= (uint)~3;
-+
-+ err = sdio_memcpy_toio(sdiodev->func[fn], addr,
-+ ((u8 *)(pkt->data)), req_sz);
-+
- if (err == -ENOMEDIUM)
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-+
- return err;
- }
-
-@@ -643,7 +661,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
- if (err)
- goto done;
-
-- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, pkt);
-+ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt);
-
- done:
- return err;
-@@ -665,14 +683,14 @@ int brcmf_sdiod_recv_chain(struct brcmf_
- goto done;
-
- if (pktq->qlen == 1)
-- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
-- pktq->next);
-+ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
-+ pktq->next);
- else if (!sdiodev->sg_support) {
- glom_skb = brcmu_pkt_buf_get_skb(totlen);
- if (!glom_skb)
- return -ENOMEM;
-- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr,
-- glom_skb);
-+ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
-+ glom_skb);
- if (err)
- goto done;
-
-@@ -707,8 +725,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
- err = brcmf_sdiod_addrprep(sdiodev, &addr);
-
- if (!err)
-- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true, addr,
-- mypkt);
-+ err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt);
-
- brcmu_pkt_buf_free_skb(mypkt);
- return err;
-@@ -730,8 +747,8 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
-
- if (pktq->qlen == 1 || !sdiodev->sg_support)
- skb_queue_walk(pktq, skb) {
-- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, true,
-- addr, skb);
-+ err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2,
-+ addr, skb);
- if (err)
- break;
- }
-@@ -783,10 +800,16 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
- sdaddr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- skb_put(pkt, dsize);
-- if (write)
-+
-+ if (write) {
- memcpy(pkt->data, data, dsize);
-- err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_1, write, sdaddr,
-- pkt);
-+ err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_1,
-+ sdaddr, pkt);
-+ } else {
-+ err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_1,
-+ sdaddr, pkt);
-+ }
-+
- if (err) {
- brcmf_err("membytes transfer failed\n");
- break;
+++ /dev/null
-From 6e24dd012bfda479d0046f7995058f167e1923bc Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:27 +0100
-Subject: [PATCH] brcmfmac: whitespace fixes in brcmf_sdiod_send_buf()
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-[arend: mention function in patch subject]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -714,6 +714,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
- int err;
-
- mypkt = brcmu_pkt_buf_get_skb(nbytes);
-+
- if (!mypkt) {
- brcmf_err("brcmu_pkt_buf_get_skb failed: len %d\n",
- nbytes);
-@@ -728,8 +729,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt);
-
- brcmu_pkt_buf_free_skb(mypkt);
-- return err;
-
-+ return err;
- }
-
- int brcmf_sdiod_send_pkt(struct brcmf_sdio_dev *sdiodev,
+++ /dev/null
-From a7323378dcf1f10a98f47b744e6f65e6fd671d84 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:28 +0100
-Subject: [PATCH] brcmfmac: Clarify if using braces.
-
-Whilst this if () statement is technically correct, it lacks clarity.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -746,16 +746,17 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
- if (err)
- return err;
-
-- if (pktq->qlen == 1 || !sdiodev->sg_support)
-+ if (pktq->qlen == 1 || !sdiodev->sg_support) {
- skb_queue_walk(pktq, skb) {
- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2,
- addr, skb);
- if (err)
- break;
- }
-- else
-+ } else {
- err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr,
- pktq);
-+ }
-
- return err;
- }
+++ /dev/null
-From 71bd508d7ded8c504ef05d1b4befecfe25e54cb1 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:29 +0100
-Subject: [PATCH] brcmfmac: Rename / replace old IO functions with simpler
- ones.
-
-Primarily this patch removes:
-
-brcmf_sdiod_f0_writeb()
-brcmf_sdiod_reg_write()
-brcmf_sdiod_reg_read()
-
-Since we no longer use the quirky method of deciding which function to
-address via the address being accessed, take the opportunity to rename
-some IO functions more in line with common kernel code. We also convert
-those that map directly to sdio_{read,write}*() to macros.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 169 +++----------------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 186 ++++++++++-----------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 28 +++-
- 3 files changed, 138 insertions(+), 245 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -137,27 +137,27 @@ int brcmf_sdiod_intr_register(struct brc
- if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) {
- /* assign GPIO to SDIO core */
- addr = CORE_CC_REG(SI_ENUM_BASE, gpiocontrol);
-- gpiocontrol = brcmf_sdiod_regrl(sdiodev, addr, &ret);
-+ gpiocontrol = brcmf_sdiod_readl(sdiodev, addr, &ret);
- gpiocontrol |= 0x2;
-- brcmf_sdiod_regwl(sdiodev, addr, gpiocontrol, &ret);
-+ brcmf_sdiod_writel(sdiodev, addr, gpiocontrol, &ret);
-
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_SELECT, 0xf,
-- &ret);
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret);
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_SELECT,
-+ 0xf, &ret);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_OUT, 0, &ret);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_GPIO_EN, 0x2, &ret);
- }
-
- /* must configure SDIO_CCCR_IENx to enable irq */
-- data = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_IENx, &ret);
-+ data = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_IENx, &ret);
- data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
-- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret);
-+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret);
-
- /* redirect, configure and enable io for interrupt signal */
- data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
- if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
- data |= SDIO_SEPINT_ACT_HI;
-- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret);
--
-+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT,
-+ data, &ret);
- sdio_release_host(sdiodev->func[1]);
- } else {
- brcmf_dbg(SDIO, "Entering\n");
-@@ -183,8 +183,8 @@ void brcmf_sdiod_intr_unregister(struct
-
- pdata = &sdiodev->settings->bus.sdio;
- sdio_claim_host(sdiodev->func[1]);
-- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
-- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
-+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
-+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
- sdio_release_host(sdiodev->func[1]);
-
- sdiodev->oob_irq_requested = false;
-@@ -242,8 +242,8 @@ static int brcmf_sdiod_set_sbaddr_window
- addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
-
- for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
-- addr & 0xff, &err);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
-+ addr & 0xff, &err);
-
- return err;
- }
-@@ -267,124 +267,15 @@ static int brcmf_sdiod_addrprep(struct b
- return 0;
- }
-
--static inline int brcmf_sdiod_f0_writeb(struct sdio_func *func, u8 byte,
-- uint regaddr)
--{
-- int err_ret;
--
-- /*
-- * Can only directly write to some F0 registers.
-- * Handle CCCR_IENx and CCCR_ABORT command
-- * as a special case.
-- */
-- if ((regaddr == SDIO_CCCR_ABORT) ||
-- (regaddr == SDIO_CCCR_IENx))
-- sdio_writeb(func, byte, regaddr, &err_ret);
-- else
-- sdio_f0_writeb(func, byte, regaddr, &err_ret);
--
-- return err_ret;
--}
--
--static int brcmf_sdiod_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr,
-- u8 regsz, void *data)
--{
-- int ret;
--
-- /*
-- * figure out how to read the register based on address range
-- * 0x00 ~ 0x7FF: function 0 CCCR and FBR
-- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
-- * The rest: function 1 silicon backplane core registers
-- * f0 writes must be bytewise
-- */
--
-- if ((addr & ~REG_F0_REG_MASK) == 0) {
-- if (WARN_ON(regsz > 1))
-- return -EINVAL;
-- ret = brcmf_sdiod_f0_writeb(sdiodev->func[0],
-- *(u8 *)data, addr);
-- } else {
-- switch (regsz) {
-- case 1:
-- sdio_writeb(sdiodev->func[1], *(u8 *)data, addr, &ret);
-- break;
-- case 4:
-- ret = brcmf_sdiod_addrprep(sdiodev, &addr);
-- if (ret)
-- goto done;
--
-- sdio_writel(sdiodev->func[1], *(u32 *)data, addr, &ret);
-- break;
-- default:
-- WARN(1, "Invalid reg size\n");
-- ret = -EINVAL;
-- break;
-- }
-- }
--
--done:
-- return ret;
--}
--
--static int brcmf_sdiod_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr,
-- u8 regsz, void *data)
--{
-- int ret;
--
-- /*
-- * figure out how to read the register based on address range
-- * 0x00 ~ 0x7FF: function 0 CCCR and FBR
-- * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers
-- * The rest: function 1 silicon backplane core registers
-- * f0 reads must be bytewise
-- */
-- if ((addr & ~REG_F0_REG_MASK) == 0) {
-- if (WARN_ON(regsz > 1))
-- return -EINVAL;
-- *(u8 *)data = sdio_f0_readb(sdiodev->func[0], addr, &ret);
-- } else {
-- switch (regsz) {
-- case 1:
-- *(u8 *)data = sdio_readb(sdiodev->func[1], addr, &ret);
-- break;
-- case 4:
-- ret = brcmf_sdiod_addrprep(sdiodev, &addr);
-- if (ret)
-- goto done;
--
-- *(u32 *)data = sdio_readl(sdiodev->func[1], addr, &ret);
-- break;
-- default:
-- WARN(1, "Invalid reg size\n");
-- ret = -EINVAL;
-- break;
-- }
-- }
--
--done:
-- return ret;
--}
--
--u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
-+u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
- {
-- u8 data;
-+ u32 data = 0;
- int retval;
-
-- retval = brcmf_sdiod_reg_read(sdiodev, addr, 1, &data);
--
-- if (ret)
-- *ret = retval;
--
-- return data;
--}
-+ retval = brcmf_sdiod_addrprep(sdiodev, &addr);
-
--u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
--{
-- u32 data;
-- int retval;
--
-- retval = brcmf_sdiod_reg_read(sdiodev, addr, 4, &data);
-+ if (!retval)
-+ data = sdio_readl(sdiodev->func[1], addr, &retval);
-
- if (ret)
- *ret = retval;
-@@ -392,23 +283,15 @@ u32 brcmf_sdiod_regrl(struct brcmf_sdio_
- return data;
- }
-
--void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr,
-- u8 data, int *ret)
-+void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr,
-+ u32 data, int *ret)
- {
- int retval;
-
-- retval = brcmf_sdiod_reg_write(sdiodev, addr, 1, &data);
--
-- if (ret)
-- *ret = retval;
--}
--
--void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr,
-- u32 data, int *ret)
--{
-- int retval;
-+ retval = brcmf_sdiod_addrprep(sdiodev, &addr);
-
-- retval = brcmf_sdiod_reg_write(sdiodev, addr, 4, &data);
-+ if (!retval)
-+ sdio_writel(sdiodev->func[1], data, addr, &retval);
-
- if (ret)
- *ret = retval;
-@@ -846,8 +729,8 @@ int brcmf_sdiod_abort(struct brcmf_sdio_
- {
- brcmf_dbg(SDIO, "Enter\n");
-
-- /* issue abort cmd52 command through F0 */
-- brcmf_sdiod_reg_write(sdiodev, SDIO_CCCR_ABORT, 1, &fn);
-+ /* Issue abort cmd52 command through F0 */
-+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, fn, NULL);
-
- brcmf_dbg(SDIO, "Exit\n");
- return 0;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -669,7 +669,7 @@ static int r_sdreg32(struct brcmf_sdio *
- int ret;
-
- core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
-- *regvar = brcmf_sdiod_regrl(bus->sdiodev, core->base + offset, &ret);
-+ *regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret);
-
- return ret;
- }
-@@ -680,7 +680,7 @@ static int w_sdreg32(struct brcmf_sdio *
- int ret;
-
- core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
-- brcmf_sdiod_regwl(bus->sdiodev, core->base + reg_offset, regval, &ret);
-+ brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret);
-
- return ret;
- }
-@@ -697,8 +697,7 @@ brcmf_sdio_kso_control(struct brcmf_sdio
-
- wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
- /* 1st KSO write goes to AOS wake up core if device is asleep */
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-- wr_val, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
-
- if (on) {
- /* device WAKEUP through KSO:
-@@ -724,7 +723,7 @@ brcmf_sdio_kso_control(struct brcmf_sdio
- * just one write attempt may fail,
- * read it back until it matches written value
- */
-- rd_val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-+ rd_val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
- &err);
- if (!err) {
- if ((rd_val & bmask) == cmp_val)
-@@ -734,9 +733,11 @@ brcmf_sdio_kso_control(struct brcmf_sdio
- /* bail out upon subsequent access errors */
- if (err && (err_cnt++ > BRCMF_SDIO_MAX_ACCESS_ERRORS))
- break;
-+
- udelay(KSO_WAIT_US);
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-- wr_val, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val,
-+ &err);
-+
- } while (try_cnt++ < MAX_KSO_ATTEMPTS);
-
- if (try_cnt > 2)
-@@ -772,15 +773,15 @@ static int brcmf_sdio_htclk(struct brcmf
- clkreq =
- bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
-
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-- clkreq, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ clkreq, &err);
- if (err) {
- brcmf_err("HT Avail request error: %d\n", err);
- return -EBADE;
- }
-
- /* Check current status */
-- clkctl = brcmf_sdiod_regrb(bus->sdiodev,
-+ clkctl = brcmf_sdiod_readb(bus->sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (err) {
- brcmf_err("HT Avail read error: %d\n", err);
-@@ -790,35 +791,34 @@ static int brcmf_sdio_htclk(struct brcmf
- /* Go to pending and await interrupt if appropriate */
- if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
- /* Allow only clock-available interrupt */
-- devctl = brcmf_sdiod_regrb(bus->sdiodev,
-+ devctl = brcmf_sdiod_readb(bus->sdiodev,
- SBSDIO_DEVICE_CTL, &err);
- if (err) {
-- brcmf_err("Devctl error setting CA: %d\n",
-- err);
-+ brcmf_err("Devctl error setting CA: %d\n", err);
- return -EBADE;
- }
-
- devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-- devctl, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-+ devctl, &err);
- brcmf_dbg(SDIO, "CLKCTL: set PENDING\n");
- bus->clkstate = CLK_PENDING;
-
- return 0;
- } else if (bus->clkstate == CLK_PENDING) {
- /* Cancel CA-only interrupt filter */
-- devctl = brcmf_sdiod_regrb(bus->sdiodev,
-+ devctl = brcmf_sdiod_readb(bus->sdiodev,
- SBSDIO_DEVICE_CTL, &err);
- devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-- devctl, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-+ devctl, &err);
- }
-
- /* Otherwise, wait here (polling) for HT Avail */
- timeout = jiffies +
- msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000);
- while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
-- clkctl = brcmf_sdiod_regrb(bus->sdiodev,
-+ clkctl = brcmf_sdiod_readb(bus->sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR,
- &err);
- if (time_after(jiffies, timeout))
-@@ -852,16 +852,16 @@ static int brcmf_sdio_htclk(struct brcmf
-
- if (bus->clkstate == CLK_PENDING) {
- /* Cancel CA-only interrupt filter */
-- devctl = brcmf_sdiod_regrb(bus->sdiodev,
-+ devctl = brcmf_sdiod_readb(bus->sdiodev,
- SBSDIO_DEVICE_CTL, &err);
- devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-- devctl, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-+ devctl, &err);
- }
-
- bus->clkstate = CLK_SDONLY;
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-- clkreq, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ clkreq, &err);
- brcmf_dbg(SDIO, "CLKCTL: turned OFF\n");
- if (err) {
- brcmf_err("Failed access turning clock off: %d\n",
-@@ -951,14 +951,14 @@ brcmf_sdio_bus_sleep(struct brcmf_sdio *
-
- /* Going to sleep */
- if (sleep) {
-- clkcsr = brcmf_sdiod_regrb(bus->sdiodev,
-+ clkcsr = brcmf_sdiod_readb(bus->sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR,
- &err);
- if ((clkcsr & SBSDIO_CSR_MASK) == 0) {
- brcmf_dbg(SDIO, "no clock, set ALP\n");
-- brcmf_sdiod_regwb(bus->sdiodev,
-- SBSDIO_FUNC1_CHIPCLKCSR,
-- SBSDIO_ALP_AVAIL_REQ, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev,
-+ SBSDIO_FUNC1_CHIPCLKCSR,
-+ SBSDIO_ALP_AVAIL_REQ, &err);
- }
- err = brcmf_sdio_kso_control(bus, false);
- } else {
-@@ -1178,16 +1178,16 @@ static void brcmf_sdio_rxfail(struct brc
- if (abort)
- brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
-
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL,
-- SFC_RF_TERM, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
-+ &err);
- bus->sdcnt.f1regdata++;
-
- /* Wait until the packet has been flushed (device/FIFO stable) */
- for (lastrbc = retries = 0xffff; retries > 0; retries--) {
-- hi = brcmf_sdiod_regrb(bus->sdiodev,
-- SBSDIO_FUNC1_RFRAMEBCHI, &err);
-- lo = brcmf_sdiod_regrb(bus->sdiodev,
-- SBSDIO_FUNC1_RFRAMEBCLO, &err);
-+ hi = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_RFRAMEBCHI,
-+ &err);
-+ lo = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_RFRAMEBCLO,
-+ &err);
- bus->sdcnt.f1regdata += 2;
-
- if ((hi == 0) && (lo == 0))
-@@ -1229,12 +1229,12 @@ static void brcmf_sdio_txfail(struct brc
- bus->sdcnt.tx_sderrs++;
-
- brcmf_sdiod_abort(sdiodev, SDIO_FUNC_2);
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
- bus->sdcnt.f1regdata++;
-
- for (i = 0; i < 3; i++) {
-- hi = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_WFRAMEBCHI, NULL);
-- lo = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL);
-+ hi = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_WFRAMEBCHI, NULL);
-+ lo = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_WFRAMEBCLO, NULL);
- bus->sdcnt.f1regdata += 2;
- if ((hi == 0) && (lo == 0))
- break;
-@@ -2446,11 +2446,11 @@ static void brcmf_sdio_bus_stop(struct d
- bus->hostintmask = 0;
-
- /* Force backplane clocks to assure F2 interrupt propagates */
-- saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- &err);
- if (!err)
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-- (saveclk | SBSDIO_FORCE_HT), &err);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ (saveclk | SBSDIO_FORCE_HT), &err);
- if (err)
- brcmf_err("Failed to force clock for F2: err %d\n",
- err);
-@@ -2509,7 +2509,7 @@ static int brcmf_sdio_intr_rstatus(struc
- buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- addr = buscore->base + offsetof(struct sdpcmd_regs, intstatus);
-
-- val = brcmf_sdiod_regrl(bus->sdiodev, addr, &ret);
-+ val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
- bus->sdcnt.f1regdata++;
- if (ret != 0)
- return ret;
-@@ -2519,7 +2519,7 @@ static int brcmf_sdio_intr_rstatus(struc
-
- /* Clear interrupts */
- if (val) {
-- brcmf_sdiod_regwl(bus->sdiodev, addr, val, &ret);
-+ brcmf_sdiod_writel(bus->sdiodev, addr, val, &ret);
- bus->sdcnt.f1regdata++;
- atomic_or(val, &bus->intstatus);
- }
-@@ -2545,23 +2545,23 @@ static void brcmf_sdio_dpc(struct brcmf_
-
- #ifdef DEBUG
- /* Check for inconsistent device control */
-- devctl = brcmf_sdiod_regrb(bus->sdiodev,
-- SBSDIO_DEVICE_CTL, &err);
-+ devctl = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-+ &err);
- #endif /* DEBUG */
-
- /* Read CSR, if clock on switch to AVAIL, else ignore */
-- clkctl = brcmf_sdiod_regrb(bus->sdiodev,
-+ clkctl = brcmf_sdiod_readb(bus->sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
-
- brcmf_dbg(SDIO, "DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n",
- devctl, clkctl);
-
- if (SBSDIO_HTAV(clkctl)) {
-- devctl = brcmf_sdiod_regrb(bus->sdiodev,
-+ devctl = brcmf_sdiod_readb(bus->sdiodev,
- SBSDIO_DEVICE_CTL, &err);
- devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL,
-- devctl, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev,
-+ SBSDIO_DEVICE_CTL, devctl, &err);
- bus->clkstate = CLK_AVAIL;
- }
- }
-@@ -3347,31 +3347,31 @@ static void brcmf_sdio_sr_init(struct br
-
- brcmf_dbg(TRACE, "Enter\n");
-
-- val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err);
-+ val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, &err);
- if (err) {
- brcmf_err("error reading SBSDIO_FUNC1_WAKEUPCTRL\n");
- return;
- }
-
- val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_WAKEUPCTRL, val, &err);
- if (err) {
- brcmf_err("error writing SBSDIO_FUNC1_WAKEUPCTRL\n");
- return;
- }
-
- /* Add CMD14 Support */
-- brcmf_sdiod_regwb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
-- (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
-- SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
-- &err);
-+ brcmf_sdiod_func0_wb(bus->sdiodev, SDIO_CCCR_BRCM_CARDCAP,
-+ (SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT |
-+ SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT),
-+ &err);
- if (err) {
- brcmf_err("error writing SDIO_CCCR_BRCM_CARDCAP\n");
- return;
- }
-
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-- SBSDIO_FORCE_HT, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ SBSDIO_FORCE_HT, &err);
- if (err) {
- brcmf_err("error writing SBSDIO_FUNC1_CHIPCLKCSR\n");
- return;
-@@ -3394,7 +3394,7 @@ static int brcmf_sdio_kso_init(struct br
- if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12)
- return 0;
-
-- val = brcmf_sdiod_regrb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
-+ val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
- if (err) {
- brcmf_err("error reading SBSDIO_FUNC1_SLEEPCSR\n");
- return err;
-@@ -3403,8 +3403,8 @@ static int brcmf_sdio_kso_init(struct br
- if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
- val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN <<
- SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-- val, &err);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR,
-+ val, &err);
- if (err) {
- brcmf_err("error writing SBSDIO_FUNC1_SLEEPCSR\n");
- return err;
-@@ -3565,9 +3565,9 @@ static void brcmf_sdio_bus_watchdog(stru
- u8 devpend;
-
- sdio_claim_host(bus->sdiodev->func[1]);
-- devpend = brcmf_sdiod_regrb(bus->sdiodev,
-- SDIO_CCCR_INTx,
-- NULL);
-+ devpend = brcmf_sdiod_func0_rb(bus->sdiodev,
-+ SDIO_CCCR_INTx,
-+ NULL);
- sdio_release_host(bus->sdiodev->func[1]);
- intstatus = devpend & (INTR_STATUS_FUNC1 |
- INTR_STATUS_FUNC2);
-@@ -3705,12 +3705,12 @@ brcmf_sdio_drivestrengthinit(struct brcm
- }
- }
- addr = CORE_CC_REG(pmu->base, chipcontrol_addr);
-- brcmf_sdiod_regwl(sdiodev, addr, 1, NULL);
-- cc_data_temp = brcmf_sdiod_regrl(sdiodev, addr, NULL);
-+ brcmf_sdiod_writel(sdiodev, addr, 1, NULL);
-+ cc_data_temp = brcmf_sdiod_readl(sdiodev, addr, NULL);
- cc_data_temp &= ~str_mask;
- drivestrength_sel <<= str_shift;
- cc_data_temp |= drivestrength_sel;
-- brcmf_sdiod_regwl(sdiodev, addr, cc_data_temp, NULL);
-+ brcmf_sdiod_writel(sdiodev, addr, cc_data_temp, NULL);
-
- brcmf_dbg(INFO, "SDIO: %d mA (req=%d mA) drive strength selected, set to 0x%08x\n",
- str_tab[i].strength, drivestrength, cc_data_temp);
-@@ -3725,7 +3725,7 @@ static int brcmf_sdio_buscoreprep(void *
-
- /* Try forcing SDIO core to do ALPAvail request only */
- clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ;
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
- if (err) {
- brcmf_err("error writing for HT off\n");
- return err;
-@@ -3733,8 +3733,7 @@ static int brcmf_sdio_buscoreprep(void *
-
- /* If register supported, wait for ALPAvail and then force ALP */
- /* This may take up to 15 milliseconds */
-- clkval = brcmf_sdiod_regrb(sdiodev,
-- SBSDIO_FUNC1_CHIPCLKCSR, NULL);
-+ clkval = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, NULL);
-
- if ((clkval & ~SBSDIO_AVBITS) != clkset) {
- brcmf_err("ChipClkCSR access: wrote 0x%02x read 0x%02x\n",
-@@ -3742,10 +3741,11 @@ static int brcmf_sdio_buscoreprep(void *
- return -EACCES;
- }
-
-- SPINWAIT(((clkval = brcmf_sdiod_regrb(sdiodev,
-- SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
-- !SBSDIO_ALPAV(clkval)),
-- PMU_MAX_TRANSITION_DLY);
-+ SPINWAIT(((clkval = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ NULL)),
-+ !SBSDIO_ALPAV(clkval)),
-+ PMU_MAX_TRANSITION_DLY);
-+
- if (!SBSDIO_ALPAV(clkval)) {
- brcmf_err("timeout on ALPAV wait, clkval 0x%02x\n",
- clkval);
-@@ -3753,11 +3753,11 @@ static int brcmf_sdio_buscoreprep(void *
- }
-
- clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP;
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err);
- udelay(65);
-
- /* Also, disable the extra SDIO pull-ups */
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL);
-
- return 0;
- }
-@@ -3772,7 +3772,7 @@ static void brcmf_sdio_buscore_activate(
- /* clear all interrupts */
- core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV);
- reg_addr = core->base + offsetof(struct sdpcmd_regs, intstatus);
-- brcmf_sdiod_regwl(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
-+ brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
-
- if (rstvec)
- /* Write reset vector to address 0 */
-@@ -3785,7 +3785,7 @@ static u32 brcmf_sdio_buscore_read32(voi
- struct brcmf_sdio_dev *sdiodev = ctx;
- u32 val, rev;
-
-- val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
-+ val = brcmf_sdiod_readl(sdiodev, addr, NULL);
- if ((sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
- sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
- addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
-@@ -3802,7 +3802,7 @@ static void brcmf_sdio_buscore_write32(v
- {
- struct brcmf_sdio_dev *sdiodev = ctx;
-
-- brcmf_sdiod_regwl(sdiodev, addr, val, NULL);
-+ brcmf_sdiod_writel(sdiodev, addr, val, NULL);
- }
-
- static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = {
-@@ -3826,18 +3826,18 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
- sdio_claim_host(sdiodev->func[1]);
-
- pr_debug("F1 signature read @0x18000000=0x%4x\n",
-- brcmf_sdiod_regrl(sdiodev, SI_ENUM_BASE, NULL));
-+ brcmf_sdiod_readl(sdiodev, SI_ENUM_BASE, NULL));
-
- /*
- * Force PLL off until brcmf_chip_attach()
- * programs PLL control regs
- */
-
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-- BRCMF_INIT_CLKCTL1, &err);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, BRCMF_INIT_CLKCTL1,
-+ &err);
- if (!err)
-- clkctl = brcmf_sdiod_regrb(sdiodev,
-- SBSDIO_FUNC1_CHIPCLKCSR, &err);
-+ clkctl = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ &err);
-
- if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) {
- brcmf_err("ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
-@@ -3897,25 +3897,25 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
- brcmf_sdio_drivestrengthinit(sdiodev, bus->ci, drivestrength);
-
- /* Set card control so an SDIO card reset does a WLAN backplane reset */
-- reg_val = brcmf_sdiod_regrb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err);
-+ reg_val = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, &err);
- if (err)
- goto fail;
-
- reg_val |= SDIO_CCCR_BRCM_CARDCTRL_WLANRESET;
-
-- brcmf_sdiod_regwb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
-+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_CARDCTRL, reg_val, &err);
- if (err)
- goto fail;
-
- /* set PMUControl so a backplane reset does PMU state reload */
- reg_addr = CORE_CC_REG(brcmf_chip_get_pmu(bus->ci)->base, pmucontrol);
-- reg_val = brcmf_sdiod_regrl(sdiodev, reg_addr, &err);
-+ reg_val = brcmf_sdiod_readl(sdiodev, reg_addr, &err);
- if (err)
- goto fail;
-
- reg_val |= (BCMA_CC_PMU_CTL_RES_RELOAD << BCMA_CC_PMU_CTL_RES_SHIFT);
-
-- brcmf_sdiod_regwl(sdiodev, reg_addr, reg_val, &err);
-+ brcmf_sdiod_writel(sdiodev, reg_addr, reg_val, &err);
- if (err)
- goto fail;
-
-@@ -4055,10 +4055,10 @@ static void brcmf_sdio_firmware_callback
- goto release;
-
- /* Force clocks on backplane to be sure F2 interrupt propagates */
-- saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, &err);
-+ saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (!err) {
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-- (saveclk | SBSDIO_FORCE_HT), &err);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ (saveclk | SBSDIO_FORCE_HT), &err);
- }
- if (err) {
- brcmf_err("Failed to force clock for F2: err %d\n", err);
-@@ -4080,7 +4080,7 @@ static void brcmf_sdio_firmware_callback
- w_sdreg32(bus, bus->hostintmask,
- offsetof(struct sdpcmd_regs, hostintmask));
-
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_WATERMARK, 8, &err);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
- } else {
- /* Disable F2 again */
- sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
-@@ -4091,8 +4091,8 @@ static void brcmf_sdio_firmware_callback
- brcmf_sdio_sr_init(bus);
- } else {
- /* Restore previous clock setting */
-- brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-- saveclk, &err);
-+ brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ saveclk, &err);
- }
-
- if (err == 0) {
-@@ -4225,7 +4225,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- bus->rxflow = false;
-
- /* Done with backplane-dependent accesses, can drop clock... */
-- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
-+ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
-
- sdio_release_host(bus->sdiodev->func[1]);
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -50,6 +50,7 @@
- #define SBSDIO_NUM_FUNCTION 3
-
- /* function 0 vendor specific CCCR registers */
-+
- #define SDIO_CCCR_BRCM_CARDCAP 0xf0
- #define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
- #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
-@@ -131,8 +132,6 @@
- /* with b15, maps to 32-bit SB access */
- #define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000
-
--/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
--
- /* Address bits from SBADDR regs */
- #define SBSDIO_SBWINDOW_MASK 0xffff8000
-
-@@ -293,13 +292,24 @@ struct sdpcmd_regs {
- int brcmf_sdiod_intr_register(struct brcmf_sdio_dev *sdiodev);
- void brcmf_sdiod_intr_unregister(struct brcmf_sdio_dev *sdiodev);
-
--/* sdio device register access interface */
--u8 brcmf_sdiod_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
--u32 brcmf_sdiod_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
--void brcmf_sdiod_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, u8 data,
-- int *ret);
--void brcmf_sdiod_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
-- int *ret);
-+/* SDIO device register access interface */
-+/* Accessors for SDIO Function 0 */
-+#define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
-+ sdio_readb((sdiodev)->func[0], (addr), (r))
-+
-+#define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
-+ sdio_writeb((sdiodev)->func[0], (v), (addr), (ret))
-+
-+/* Accessors for SDIO Function 1 */
-+#define brcmf_sdiod_readb(sdiodev, addr, r) \
-+ sdio_readb((sdiodev)->func[1], (addr), (r))
-+
-+#define brcmf_sdiod_writeb(sdiodev, addr, v, ret) \
-+ sdio_writeb((sdiodev)->func[1], (v), (addr), (ret))
-+
-+u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
-+void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
-+ int *ret);
-
- /* Buffer transfer to/from device (client) core via cmd53.
- * fn: function number
+++ /dev/null
-From eeef8a5da781e11746347b3cd9f1942be48ebaf0 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:30 +0100
-Subject: [PATCH] brcmfmac: Tidy register definitions a little
-
-Trivial tidy of register definitions.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 4 ++--
- .../net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 19 ++++++++++---------
- 2 files changed, 12 insertions(+), 11 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -153,9 +153,9 @@ int brcmf_sdiod_intr_register(struct brc
- brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret);
-
- /* redirect, configure and enable io for interrupt signal */
-- data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE;
-+ data = SDIO_CCCR_BRCM_SEPINT_MASK | SDIO_CCCR_BRCM_SEPINT_OE;
- if (pdata->oob_irq_flags & IRQF_TRIGGER_HIGH)
-- data |= SDIO_SEPINT_ACT_HI;
-+ data |= SDIO_CCCR_BRCM_SEPINT_ACT_HI;
- brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT,
- data, &ret);
- sdio_release_host(sdiodev->func[1]);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -52,16 +52,17 @@
- /* function 0 vendor specific CCCR registers */
-
- #define SDIO_CCCR_BRCM_CARDCAP 0xf0
--#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT 0x02
--#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT 0x04
--#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC 0x08
--#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
--#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET 0x02
--#define SDIO_CCCR_BRCM_SEPINT 0xf2
-+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_SUPPORT BIT(1)
-+#define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT BIT(2)
-+#define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC BIT(3)
-+
-+#define SDIO_CCCR_BRCM_CARDCTRL 0xf1
-+#define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET BIT(1)
-
--#define SDIO_SEPINT_MASK 0x01
--#define SDIO_SEPINT_OE 0x02
--#define SDIO_SEPINT_ACT_HI 0x04
-+#define SDIO_CCCR_BRCM_SEPINT 0xf2
-+#define SDIO_CCCR_BRCM_SEPINT_MASK BIT(0)
-+#define SDIO_CCCR_BRCM_SEPINT_OE BIT(1)
-+#define SDIO_CCCR_BRCM_SEPINT_ACT_HI BIT(2)
-
- /* function 1 miscellaneous registers */
-
+++ /dev/null
-From a7c3aa1509e243a09c5b1660c8702d792ca76aed Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:31 +0100
-Subject: [PATCH] brcmfmac: Remove brcmf_sdiod_addrprep()
-
-This function has become trivial enough that it may as well be pushed into
-its callers, which has the side-benefit of clarifying what's going on.
-
-Remove it, and rename brcmf_sdiod_set_sbaddr_window() to
-brcmf_sdiod_set_backplane_window() as it's easier to understand.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 84 ++++++++++++----------
- 1 file changed, 46 insertions(+), 38 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -230,41 +230,25 @@ void brcmf_sdiod_change_state(struct brc
- sdiodev->state = state;
- }
-
--static int brcmf_sdiod_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
-- u32 address)
-+static int brcmf_sdiod_set_backplane_window(struct brcmf_sdio_dev *sdiodev,
-+ u32 addr)
- {
-+ u32 v, bar0 = addr & SBSDIO_SBWINDOW_MASK;
- int err = 0, i;
-- u32 addr;
-
-- if (sdiodev->state == BRCMF_SDIOD_NOMEDIUM)
-- return -ENOMEDIUM;
-+ if (bar0 == sdiodev->sbwad)
-+ return 0;
-
-- addr = (address & SBSDIO_SBWINDOW_MASK) >> 8;
-+ v = bar0 >> 8;
-
-- for (i = 0 ; i < 3 && !err ; i++, addr >>= 8)
-+ for (i = 0 ; i < 3 && !err ; i++, v >>= 8)
- brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_SBADDRLOW + i,
-- addr & 0xff, &err);
--
-- return err;
--}
--
--static int brcmf_sdiod_addrprep(struct brcmf_sdio_dev *sdiodev, u32 *addr)
--{
-- uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
-- int err = 0;
--
-- if (bar0 != sdiodev->sbwad) {
-- err = brcmf_sdiod_set_sbaddr_window(sdiodev, bar0);
-- if (err)
-- return err;
-+ v & 0xff, &err);
-
-+ if (!err)
- sdiodev->sbwad = bar0;
-- }
-
-- *addr &= SBSDIO_SB_OFT_ADDR_MASK;
-- *addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
--
-- return 0;
-+ return err;
- }
-
- u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret)
-@@ -272,11 +256,16 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_
- u32 data = 0;
- int retval;
-
-- retval = brcmf_sdiod_addrprep(sdiodev, &addr);
-+ retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
-+ if (retval)
-+ goto out;
-+
-+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
-+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-- if (!retval)
-- data = sdio_readl(sdiodev->func[1], addr, &retval);
-+ data = sdio_readl(sdiodev->func[1], addr, &retval);
-
-+out:
- if (ret)
- *ret = retval;
-
-@@ -288,11 +277,16 @@ void brcmf_sdiod_writel(struct brcmf_sdi
- {
- int retval;
-
-- retval = brcmf_sdiod_addrprep(sdiodev, &addr);
-+ retval = brcmf_sdiod_set_backplane_window(sdiodev, addr);
-+ if (retval)
-+ goto out;
-
-- if (!retval)
-- sdio_writel(sdiodev->func[1], data, addr, &retval);
-+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
-+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-+ sdio_writel(sdiodev->func[1], data, addr, &retval);
-+
-+out:
- if (ret)
- *ret = retval;
- }
-@@ -540,10 +534,13 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
-
- brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
-
-- err = brcmf_sdiod_addrprep(sdiodev, &addr);
-+ err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
- if (err)
- goto done;
-
-+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
-+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-+
- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt);
-
- done:
-@@ -561,10 +558,13 @@ int brcmf_sdiod_recv_chain(struct brcmf_
- brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n",
- addr, pktq->qlen);
-
-- err = brcmf_sdiod_addrprep(sdiodev, &addr);
-+ err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
- if (err)
- goto done;
-
-+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
-+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-+
- if (pktq->qlen == 1)
- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
- pktq->next);
-@@ -606,7 +606,12 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
-
- memcpy(mypkt->data, buf, nbytes);
-
-- err = brcmf_sdiod_addrprep(sdiodev, &addr);
-+ err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
-+ if (err)
-+ return err;
-+
-+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
-+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- if (!err)
- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt);
-@@ -625,10 +630,13 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
-
- brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen);
-
-- err = brcmf_sdiod_addrprep(sdiodev, &addr);
-+ err = brcmf_sdiod_set_backplane_window(sdiodev, addr);
- if (err)
- return err;
-
-+ addr &= SBSDIO_SB_OFT_ADDR_MASK;
-+ addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-+
- if (pktq->qlen == 1 || !sdiodev->sg_support) {
- skb_queue_walk(pktq, skb) {
- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2,
-@@ -673,7 +681,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
- /* Do the transfer(s) */
- while (size) {
- /* Set the backplane window to include the start address */
-- err = brcmf_sdiod_set_sbaddr_window(sdiodev, address);
-+ err = brcmf_sdiod_set_backplane_window(sdiodev, address);
- if (err)
- break;
-
-@@ -716,7 +724,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
- dev_kfree_skb(pkt);
-
- /* Return the window to backplane enumeration space for core access */
-- if (brcmf_sdiod_set_sbaddr_window(sdiodev, sdiodev->sbwad))
-+ if (brcmf_sdiod_set_backplane_window(sdiodev, sdiodev->sbwad))
- brcmf_err("FAILED to set window back to 0x%x\n",
- sdiodev->sbwad);
-
+++ /dev/null
-From c900072bd6faff089aa4fb7b19136a2a0fe3baf0 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:32 +0100
-Subject: [PATCH] brcmfmac: remove unnecessary call to
- brcmf_sdiod_set_backplane_window()
-
-All functions that might require the window address changing call
-brcmf_sdiod_set_backplane_window() prior to access. Thus resetting
-the window is not required.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-[arend: corrected the driver prefix in the subject]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 -----
- 1 file changed, 5 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -723,11 +723,6 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
-
- dev_kfree_skb(pkt);
-
-- /* Return the window to backplane enumeration space for core access */
-- if (brcmf_sdiod_set_backplane_window(sdiodev, sdiodev->sbwad))
-- brcmf_err("FAILED to set window back to 0x%x\n",
-- sdiodev->sbwad);
--
- sdio_release_host(sdiodev->func[1]);
-
- return err;
+++ /dev/null
-From e4c05fc3c0a6c79376f72f17d08014477e962ada Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:33 +0100
-Subject: [PATCH] brcmfmac: Cleanup offsetof()
-
-Create a macro to make the code a bit more readable, whilst we're stuck
-with using struct element offsets as register offsets.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-[arend: rename macro to SD_REG]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 35 +++++++++-------------
- 1 file changed, 14 insertions(+), 21 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -161,6 +161,8 @@ struct rte_console {
-
- #define CORE_BUS_REG(base, field) \
- (base + offsetof(struct sdpcmd_regs, field))
-+#define SD_REG(field) \
-+ (offsetof(struct sdpcmd_regs, field))
-
- /* SDIO function 1 register CHIPCLKCSR */
- /* Force ALP request to backplane */
-@@ -1087,12 +1089,10 @@ static u32 brcmf_sdio_hostmail(struct br
- brcmf_dbg(SDIO, "Enter\n");
-
- /* Read mailbox data and ack that we did so */
-- ret = r_sdreg32(bus, &hmb_data,
-- offsetof(struct sdpcmd_regs, tohostmailboxdata));
-+ ret = r_sdreg32(bus, &hmb_data, SD_REG(tohostmailboxdata));
-
- if (ret == 0)
-- w_sdreg32(bus, SMB_INT_ACK,
-- offsetof(struct sdpcmd_regs, tosbmailbox));
-+ w_sdreg32(bus, SMB_INT_ACK, SD_REG(tosbmailbox));
- bus->sdcnt.f1regdata += 2;
-
- /* dongle indicates the firmware has halted/crashed */
-@@ -1207,8 +1207,7 @@ static void brcmf_sdio_rxfail(struct brc
-
- if (rtx) {
- bus->sdcnt.rxrtx++;
-- err = w_sdreg32(bus, SMB_NAK,
-- offsetof(struct sdpcmd_regs, tosbmailbox));
-+ err = w_sdreg32(bus, SMB_NAK, SD_REG(tosbmailbox));
-
- bus->sdcnt.f1regdata++;
- if (err == 0)
-@@ -2333,9 +2332,7 @@ static uint brcmf_sdio_sendfromq(struct
- if (!bus->intr) {
- /* Check device status, signal pending interrupt */
- sdio_claim_host(bus->sdiodev->func[1]);
-- ret = r_sdreg32(bus, &intstatus,
-- offsetof(struct sdpcmd_regs,
-- intstatus));
-+ ret = r_sdreg32(bus, &intstatus, SD_REG(intstatus));
- sdio_release_host(bus->sdiodev->func[1]);
- bus->sdcnt.f2txdata++;
- if (ret != 0)
-@@ -2441,7 +2438,7 @@ static void brcmf_sdio_bus_stop(struct d
- brcmf_sdio_bus_sleep(bus, false, false);
-
- /* Disable and clear interrupts at the chip level also */
-- w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask));
-+ w_sdreg32(bus, 0, SD_REG(hostintmask));
- local_hostintmask = bus->hostintmask;
- bus->hostintmask = 0;
-
-@@ -2460,8 +2457,7 @@ static void brcmf_sdio_bus_stop(struct d
- sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
-
- /* Clear any pending interrupts now that F2 is disabled */
-- w_sdreg32(bus, local_hostintmask,
-- offsetof(struct sdpcmd_regs, intstatus));
-+ w_sdreg32(bus, local_hostintmask, SD_REG(intstatus));
-
- sdio_release_host(sdiodev->func[1]);
- }
-@@ -2507,7 +2503,7 @@ static int brcmf_sdio_intr_rstatus(struc
- int ret;
-
- buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
-- addr = buscore->base + offsetof(struct sdpcmd_regs, intstatus);
-+ addr = buscore->base + SD_REG(intstatus);
-
- val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
- bus->sdcnt.f1regdata++;
-@@ -2584,11 +2580,9 @@ static void brcmf_sdio_dpc(struct brcmf_
- */
- if (intstatus & I_HMB_FC_CHANGE) {
- intstatus &= ~I_HMB_FC_CHANGE;
-- err = w_sdreg32(bus, I_HMB_FC_CHANGE,
-- offsetof(struct sdpcmd_regs, intstatus));
-+ err = w_sdreg32(bus, I_HMB_FC_CHANGE, SD_REG(intstatus));
-
-- err = r_sdreg32(bus, &newstatus,
-- offsetof(struct sdpcmd_regs, intstatus));
-+ err = r_sdreg32(bus, &newstatus, SD_REG(intstatus));
- bus->sdcnt.f1regdata += 2;
- atomic_set(&bus->fcstate,
- !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)));
-@@ -3771,7 +3765,7 @@ static void brcmf_sdio_buscore_activate(
-
- /* clear all interrupts */
- core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV);
-- reg_addr = core->base + offsetof(struct sdpcmd_regs, intstatus);
-+ reg_addr = core->base + SD_REG(intstatus);
- brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
-
- if (rstvec)
-@@ -4067,7 +4061,7 @@ static void brcmf_sdio_firmware_callback
-
- /* Enable function 2 (frame transfers) */
- w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
-- offsetof(struct sdpcmd_regs, tosbmailboxdata));
-+ SD_REG(tosbmailboxdata));
- err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
-
-
-@@ -4077,8 +4071,7 @@ static void brcmf_sdio_firmware_callback
- if (!err) {
- /* Set up the interrupt mask and enable interrupts */
- bus->hostintmask = HOSTINTMASK;
-- w_sdreg32(bus, bus->hostintmask,
-- offsetof(struct sdpcmd_regs, hostintmask));
-+ w_sdreg32(bus, bus->hostintmask, SD_REG(hostintmask));
-
- brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
- } else {
+++ /dev/null
-From 5cfe38f1f8d3c6b98e15b8cfde05028a3c79930b Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:34 +0100
-Subject: [PATCH] brcmfmac: Remove unused macro.
-
-This macro is used exactly nowhere in the code. Delete it.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 --
- 1 file changed, 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -159,8 +159,6 @@ struct rte_console {
- /* manfid tuple length, include tuple, link bytes */
- #define SBSDIO_CIS_MANFID_TUPLE_LEN 6
-
--#define CORE_BUS_REG(base, field) \
-- (base + offsetof(struct sdpcmd_regs, field))
- #define SD_REG(field) \
- (offsetof(struct sdpcmd_regs, field))
-
+++ /dev/null
-From 21a10846d09db3c5e3bdfb0be0fc7aa9fdc7000a Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Fri, 8 Dec 2017 13:10:35 +0100
-Subject: [PATCH] brcmfmac: Remove repeated calls to brcmf_chip_get_core()
-
-There is no need to repeatdly call brcmf_chip_get_core(), which
-traverses a list of cores every time its called (including during
-register access code!).
-
-Call it once, and store a pointer to the core structure. The existing
-code does nto keep track of users of the cores anyway, and even so, this
-will allow for easier refcounting in future.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 25 +++++++++++++---------
- 1 file changed, 15 insertions(+), 10 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -436,6 +436,7 @@ struct brcmf_sdio_count {
- struct brcmf_sdio {
- struct brcmf_sdio_dev *sdiodev; /* sdio device handler */
- struct brcmf_chip *ci; /* Chip info struct */
-+ struct brcmf_core *sdio_core; /* sdio core info struct */
-
- u32 hostintmask; /* Copy of Host Interrupt Mask */
- atomic_t intstatus; /* Intstatus bits (events) pending */
-@@ -665,10 +666,9 @@ static bool data_ok(struct brcmf_sdio *b
- */
- static int r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
- {
-- struct brcmf_core *core;
-+ struct brcmf_core *core = bus->sdio_core;
- int ret;
-
-- core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- *regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret);
-
- return ret;
-@@ -676,10 +676,9 @@ static int r_sdreg32(struct brcmf_sdio *
-
- static int w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
- {
-- struct brcmf_core *core;
-+ struct brcmf_core *core = bus->sdio_core;
- int ret;
-
-- core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret);
-
- return ret;
-@@ -2495,12 +2494,11 @@ static inline void brcmf_sdio_clrintr(st
-
- static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
- {
-- struct brcmf_core *buscore;
-+ struct brcmf_core *buscore = bus->sdio_core;
- u32 addr;
- unsigned long val;
- int ret;
-
-- buscore = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
- addr = buscore->base + SD_REG(intstatus);
-
- val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
-@@ -3377,13 +3375,14 @@ static void brcmf_sdio_sr_init(struct br
- /* enable KSO bit */
- static int brcmf_sdio_kso_init(struct brcmf_sdio *bus)
- {
-+ struct brcmf_core *core = bus->sdio_core;
- u8 val;
- int err = 0;
-
- brcmf_dbg(TRACE, "Enter\n");
-
- /* KSO bit added in SDIO core rev 12 */
-- if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12)
-+ if (core->rev < 12)
- return 0;
-
- val = brcmf_sdiod_readb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, &err);
-@@ -3412,6 +3411,7 @@ static int brcmf_sdio_bus_preinit(struct
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- struct brcmf_sdio *bus = sdiodev->bus;
-+ struct brcmf_core *core = bus->sdio_core;
- uint pad_size;
- u32 value;
- int err;
-@@ -3420,7 +3420,7 @@ static int brcmf_sdio_bus_preinit(struct
- * a device perspective, ie. bus:txglom affects the
- * bus transfers from device to host.
- */
-- if (brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV)->rev < 12) {
-+ if (core->rev < 12) {
- /* for sdio core rev < 12, disable txgloming */
- value = 0;
- err = brcmf_iovar_data_set(dev, "bus:txglom", &value,
-@@ -3758,11 +3758,10 @@ static void brcmf_sdio_buscore_activate(
- u32 rstvec)
- {
- struct brcmf_sdio_dev *sdiodev = ctx;
-- struct brcmf_core *core;
-+ struct brcmf_core *core = sdiodev->bus->sdio_core;
- u32 reg_addr;
-
- /* clear all interrupts */
-- core = brcmf_chip_get_core(chip, BCMA_CORE_SDIO_DEV);
- reg_addr = core->base + SD_REG(intstatus);
- brcmf_sdiod_writel(sdiodev, reg_addr, 0xFFFFFFFF, NULL);
-
-@@ -3843,6 +3842,12 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
- bus->ci = NULL;
- goto fail;
- }
-+
-+ /* Pick up the SDIO core info struct from chip.c */
-+ bus->sdio_core = brcmf_chip_get_core(bus->ci, BCMA_CORE_SDIO_DEV);
-+ if (!bus->sdio_core)
-+ goto fail;
-+
- sdiodev->settings = brcmf_get_module_param(sdiodev->dev,
- BRCMF_BUSTYPE_SDIO,
- bus->ci->chip,
+++ /dev/null
-From 7762bb134e3b40e8ee2611365775b7432190a9c7 Mon Sep 17 00:00:00 2001
-From: Wright Feng <wright.feng@cypress.com>
-Date: Mon, 11 Dec 2017 15:38:21 +0800
-Subject: [PATCH] brcmfmac: enlarge buffer size of caps to 512 bytes
-
-The buffer size of return of cap iovar is greater than 256 bytes in some
-firmwares. For instance, the return size of cap iovar is 271 bytes in 4373
-13.10.246.79 firmare. It makes feature capability parsing failed because
-caps buffer is default value.
-So we enlarge caps buffer size to 512 bytes and add the error print for
-cap iovar error.
-
-Signed-off-by: Wright Feng <wright.feng@cypress.com>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 12 +++++++++---
- 1 file changed, 9 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-@@ -130,13 +130,19 @@ static void brcmf_feat_iovar_data_set(st
- }
- }
-
-+#define MAX_CAPS_BUFFER_SIZE 512
- static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
- {
-- char caps[256];
-+ char caps[MAX_CAPS_BUFFER_SIZE];
- enum brcmf_feat_id id;
-- int i;
-+ int i, err;
-+
-+ err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
-+ if (err) {
-+ brcmf_err("could not get firmware cap (%d)\n", err);
-+ return;
-+ }
-
-- brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
- brcmf_dbg(INFO, "[ %s]\n", caps);
-
- for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) {
+++ /dev/null
-From 3d110df8f74781354051e4bb1e3e97fa368b2f80 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Tue, 19 Dec 2017 13:47:07 +0100
-Subject: [PATCH] brcmfmac: Remove {r,w}_sdreg32
-
-Remove yet another IO function from the code and replace with one
-that already exists.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-[arend: keep address calculation, ie. (base + offset) in one line]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 88 +++++++++++-----------
- 1 file changed, 42 insertions(+), 46 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -660,30 +660,6 @@ static bool data_ok(struct brcmf_sdio *b
- ((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0;
- }
-
--/*
-- * Reads a register in the SDIO hardware block. This block occupies a series of
-- * adresses on the 32 bit backplane bus.
-- */
--static int r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset)
--{
-- struct brcmf_core *core = bus->sdio_core;
-- int ret;
--
-- *regvar = brcmf_sdiod_readl(bus->sdiodev, core->base + offset, &ret);
--
-- return ret;
--}
--
--static int w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset)
--{
-- struct brcmf_core *core = bus->sdio_core;
-- int ret;
--
-- brcmf_sdiod_writel(bus->sdiodev, core->base + reg_offset, regval, &ret);
--
-- return ret;
--}
--
- static int
- brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on)
- {
-@@ -1078,6 +1054,8 @@ static void brcmf_sdio_get_console_addr(
-
- static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus)
- {
-+ struct brcmf_sdio_dev *sdiod = bus->sdiodev;
-+ struct brcmf_core *core = bus->sdio_core;
- u32 intstatus = 0;
- u32 hmb_data;
- u8 fcbits;
-@@ -1086,10 +1064,14 @@ static u32 brcmf_sdio_hostmail(struct br
- brcmf_dbg(SDIO, "Enter\n");
-
- /* Read mailbox data and ack that we did so */
-- ret = r_sdreg32(bus, &hmb_data, SD_REG(tohostmailboxdata));
-+ hmb_data = brcmf_sdiod_readl(sdiod,
-+ core->base + SD_REG(tohostmailboxdata),
-+ &ret);
-+
-+ if (!ret)
-+ brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox),
-+ SMB_INT_ACK, &ret);
-
-- if (ret == 0)
-- w_sdreg32(bus, SMB_INT_ACK, SD_REG(tosbmailbox));
- bus->sdcnt.f1regdata += 2;
-
- /* dongle indicates the firmware has halted/crashed */
-@@ -1163,6 +1145,8 @@ static u32 brcmf_sdio_hostmail(struct br
-
- static void brcmf_sdio_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx)
- {
-+ struct brcmf_sdio_dev *sdiod = bus->sdiodev;
-+ struct brcmf_core *core = bus->sdio_core;
- uint retries = 0;
- u16 lastrbc;
- u8 hi, lo;
-@@ -1204,7 +1188,8 @@ static void brcmf_sdio_rxfail(struct brc
-
- if (rtx) {
- bus->sdcnt.rxrtx++;
-- err = w_sdreg32(bus, SMB_NAK, SD_REG(tosbmailbox));
-+ brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox),
-+ SMB_NAK, &err);
-
- bus->sdcnt.f1regdata++;
- if (err == 0)
-@@ -2291,6 +2276,7 @@ static uint brcmf_sdio_sendfromq(struct
- {
- struct sk_buff *pkt;
- struct sk_buff_head pktq;
-+ u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus);
- u32 intstatus = 0;
- int ret = 0, prec_out, i;
- uint cnt = 0;
-@@ -2329,7 +2315,8 @@ static uint brcmf_sdio_sendfromq(struct
- if (!bus->intr) {
- /* Check device status, signal pending interrupt */
- sdio_claim_host(bus->sdiodev->func[1]);
-- ret = r_sdreg32(bus, &intstatus, SD_REG(intstatus));
-+ intstatus = brcmf_sdiod_readl(bus->sdiodev,
-+ intstat_addr, &ret);
- sdio_release_host(bus->sdiodev->func[1]);
- bus->sdcnt.f2txdata++;
- if (ret != 0)
-@@ -2413,12 +2400,13 @@ static int brcmf_sdio_tx_ctrlframe(struc
-
- static void brcmf_sdio_bus_stop(struct device *dev)
- {
-- u32 local_hostintmask;
-- u8 saveclk;
-- int err;
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- struct brcmf_sdio *bus = sdiodev->bus;
-+ struct brcmf_core *core = bus->sdio_core;
-+ u32 local_hostintmask;
-+ u8 saveclk;
-+ int err;
-
- brcmf_dbg(TRACE, "Enter\n");
-
-@@ -2435,7 +2423,9 @@ static void brcmf_sdio_bus_stop(struct d
- brcmf_sdio_bus_sleep(bus, false, false);
-
- /* Disable and clear interrupts at the chip level also */
-- w_sdreg32(bus, 0, SD_REG(hostintmask));
-+ brcmf_sdiod_writel(sdiodev, core->base + SD_REG(hostintmask),
-+ 0, NULL);
-+
- local_hostintmask = bus->hostintmask;
- bus->hostintmask = 0;
-
-@@ -2454,7 +2444,8 @@ static void brcmf_sdio_bus_stop(struct d
- sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
-
- /* Clear any pending interrupts now that F2 is disabled */
-- w_sdreg32(bus, local_hostintmask, SD_REG(intstatus));
-+ brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus),
-+ local_hostintmask, NULL);
-
- sdio_release_host(sdiodev->func[1]);
- }
-@@ -2521,7 +2512,9 @@ static int brcmf_sdio_intr_rstatus(struc
-
- static void brcmf_sdio_dpc(struct brcmf_sdio *bus)
- {
-+ struct brcmf_sdio_dev *sdiod = bus->sdiodev;
- u32 newstatus = 0;
-+ u32 intstat_addr = bus->sdio_core->base + SD_REG(intstatus);
- unsigned long intstatus;
- uint txlimit = bus->txbound; /* Tx frames to send before resched */
- uint framecnt; /* Temporary counter of tx/rx frames */
-@@ -2576,9 +2569,10 @@ static void brcmf_sdio_dpc(struct brcmf_
- */
- if (intstatus & I_HMB_FC_CHANGE) {
- intstatus &= ~I_HMB_FC_CHANGE;
-- err = w_sdreg32(bus, I_HMB_FC_CHANGE, SD_REG(intstatus));
-+ brcmf_sdiod_writel(sdiod, intstat_addr, I_HMB_FC_CHANGE, &err);
-+
-+ newstatus = brcmf_sdiod_readl(sdiod, intstat_addr, &err);
-
-- err = r_sdreg32(bus, &newstatus, SD_REG(intstatus));
- bus->sdcnt.f1regdata += 2;
- atomic_set(&bus->fcstate,
- !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)));
-@@ -4017,22 +4011,21 @@ static void brcmf_sdio_firmware_callback
- const struct firmware *code,
- void *nvram, u32 nvram_len)
- {
-- struct brcmf_bus *bus_if;
-- struct brcmf_sdio_dev *sdiodev;
-- struct brcmf_sdio *bus;
-+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-+ struct brcmf_sdio *bus = sdiodev->bus;
-+ struct brcmf_sdio_dev *sdiod = bus->sdiodev;
-+ struct brcmf_core *core = bus->sdio_core;
- u8 saveclk;
-
- brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
-- bus_if = dev_get_drvdata(dev);
-- sdiodev = bus_if->bus_priv.sdio;
-+
- if (err)
- goto fail;
-
- if (!bus_if->drvr)
- return;
-
-- bus = sdiodev->bus;
--
- /* try to download image and nvram to the dongle */
- bus->alp_only = true;
- err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
-@@ -4063,8 +4056,9 @@ static void brcmf_sdio_firmware_callback
- }
-
- /* Enable function 2 (frame transfers) */
-- w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
-- SD_REG(tosbmailboxdata));
-+ brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata),
-+ SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL);
-+
- err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
-
-
-@@ -4074,7 +4068,9 @@ static void brcmf_sdio_firmware_callback
- if (!err) {
- /* Set up the interrupt mask and enable interrupts */
- bus->hostintmask = HOSTINTMASK;
-- w_sdreg32(bus, bus->hostintmask, SD_REG(hostintmask));
-+ brcmf_sdiod_writel(sdiod, core->base + SD_REG(hostintmask),
-+ bus->hostintmask, NULL);
-+
-
- brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
- } else {
+++ /dev/null
-From dbda7dacb79a377e8ed9d38ce0e4a58b70aa9060 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 19 Dec 2017 13:47:08 +0100
-Subject: [PATCH] brcmfmac: Rename buscore to core for consistency
-
-Avoid confusion with unrelated _buscore labels.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-[arend: only do the rename]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -2485,12 +2485,12 @@ static inline void brcmf_sdio_clrintr(st
-
- static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)
- {
-- struct brcmf_core *buscore = bus->sdio_core;
-+ struct brcmf_core *core = bus->sdio_core;
- u32 addr;
- unsigned long val;
- int ret;
-
-- addr = buscore->base + SD_REG(intstatus);
-+ addr = core->base + SD_REG(intstatus);
-
- val = brcmf_sdiod_readl(bus->sdiodev, addr, &ret);
- bus->sdcnt.f1regdata++;
+++ /dev/null
-From 874bb8e49b7c6368f8ff9f2566c7bd06a2249be0 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Tue, 19 Dec 2017 13:47:09 +0100
-Subject: [PATCH] brcmfmac: stabilise the value of ->sbwad in use for some xfer
- routines.
-
-The IO functions operate within the Chipcommon IO window. Explicitly
-set this, rather than relying on the last initialisation IO access to
-leave it set to the right value by chance.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 8 ++++----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 5 +++++
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 +
- 3 files changed, 10 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -529,7 +529,7 @@ int brcmf_sdiod_recv_buf(struct brcmf_sd
-
- int brcmf_sdiod_recv_pkt(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt)
- {
-- u32 addr = sdiodev->sbwad;
-+ u32 addr = sdiodev->cc_core->base;
- int err = 0;
-
- brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pkt->len);
-@@ -552,7 +552,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_
- {
- struct sk_buff *glom_skb = NULL;
- struct sk_buff *skb;
-- u32 addr = sdiodev->sbwad;
-+ u32 addr = sdiodev->cc_core->base;
- int err = 0;
-
- brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n",
-@@ -593,7 +593,7 @@ done:
- int brcmf_sdiod_send_buf(struct brcmf_sdio_dev *sdiodev, u8 *buf, uint nbytes)
- {
- struct sk_buff *mypkt;
-- u32 addr = sdiodev->sbwad;
-+ u32 addr = sdiodev->cc_core->base;
- int err;
-
- mypkt = brcmu_pkt_buf_get_skb(nbytes);
-@@ -625,7 +625,7 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
- struct sk_buff_head *pktq)
- {
- struct sk_buff *skb;
-- u32 addr = sdiodev->sbwad;
-+ u32 addr = sdiodev->cc_core->base;
- int err;
-
- brcmf_dbg(SDIO, "addr = 0x%x, size = %d\n", addr, pktq->qlen);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -3842,6 +3842,11 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
- if (!bus->sdio_core)
- goto fail;
-
-+ /* Pick up the CHIPCOMMON core info struct, for bulk IO in bcmsdh.c */
-+ sdiodev->cc_core = brcmf_chip_get_core(bus->ci, BCMA_CORE_CHIPCOMMON);
-+ if (!sdiodev->cc_core)
-+ goto fail;
-+
- sdiodev->settings = brcmf_get_module_param(sdiodev->dev,
- BRCMF_BUSTYPE_SDIO,
- bus->ci->chip,
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -178,6 +178,7 @@ struct brcmf_sdio_dev {
- struct sdio_func *func[SDIO_MAX_FUNCS];
- u8 num_funcs; /* Supported funcs on client */
- u32 sbwad; /* Save backplane window address */
-+ struct brcmf_core *cc_core; /* chipcommon core info struct */
- struct brcmf_sdio *bus;
- struct device *dev;
- struct brcmf_bus *bus_if;
+++ /dev/null
-From 508422f3695bf66f7b85fb4723c22f5166003ec6 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Tue, 19 Dec 2017 13:47:10 +0100
-Subject: [PATCH] brcmfmac: Correctly handle accesses to SDIO func0
-
-Rather than workaround the restrictions on func0 addressing in the
-driver, set MMC_QUIRK_LENIENT_FN0
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 4 ++++
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 4 ++--
- 2 files changed, 6 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -995,6 +995,10 @@ static int brcmf_ops_sdio_probe(struct s
- brcmf_dbg(SDIO, "Function#: %d\n", func->num);
-
- dev = &func->dev;
-+
-+ /* Set MMC_QUIRK_LENIENT_FN0 for this card */
-+ func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
-+
- /* prohibit ACPI power management for this device */
- brcmf_sdiod_acpi_set_power_manageable(dev, 0);
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -297,10 +297,10 @@ void brcmf_sdiod_intr_unregister(struct
- /* SDIO device register access interface */
- /* Accessors for SDIO Function 0 */
- #define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
-- sdio_readb((sdiodev)->func[0], (addr), (r))
-+ sdio_f0_readb((sdiodev)->func[0], (addr), (r))
-
- #define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
-- sdio_writeb((sdiodev)->func[0], (v), (addr), (ret))
-+ sdio_f0_writeb((sdiodev)->func[0], (v), (addr), (ret))
-
- /* Accessors for SDIO Function 1 */
- #define brcmf_sdiod_readb(sdiodev, addr, r) \
+++ /dev/null
-From 99d7b6fdfc8c24052c92c720330d31ca1332f996 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Tue, 19 Dec 2017 13:47:11 +0100
-Subject: [PATCH] brcmfmac: Remove func0 from function array
-
-func0 is not provided by the mmc stack as a function when probing.
-Instead providing specific access functions to read/write it.
-
-This prepares for a patch to remove the actual array entry itself.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-[arend: rephrased the commit message]
-[arend: removed unrelated comment for which separate patch is warranted]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 5 +----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 ++++---
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 13 ++++++-------
- 3 files changed, 11 insertions(+), 14 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -1022,8 +1022,7 @@ static int brcmf_ops_sdio_probe(struct s
- /* store refs to functions used. mmc_card does
- * not hold the F0 function pointer.
- */
-- sdiodev->func[0] = kmemdup(func, sizeof(*func), GFP_KERNEL);
-- sdiodev->func[0]->num = 0;
-+ sdiodev->func[0] = NULL;
- sdiodev->func[1] = func->card->sdio_func[0];
- sdiodev->func[2] = func;
-
-@@ -1049,7 +1048,6 @@ static int brcmf_ops_sdio_probe(struct s
- fail:
- dev_set_drvdata(&func->dev, NULL);
- dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
-- kfree(sdiodev->func[0]);
- kfree(sdiodev);
- kfree(bus_if);
- return err;
-@@ -1082,7 +1080,6 @@ static void brcmf_ops_sdio_remove(struct
- dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
-
- kfree(bus_if);
-- kfree(sdiodev->func[0]);
- kfree(sdiodev);
- }
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -3771,9 +3771,10 @@ static u32 brcmf_sdio_buscore_read32(voi
- u32 val, rev;
-
- val = brcmf_sdiod_readl(sdiodev, addr, NULL);
-- if ((sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
-- sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
-- addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
-+
-+ if ((sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
-+ sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
-+ addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
- rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
- if (rev >= 2) {
- val &= ~CID_ID_MASK;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -21,7 +21,9 @@
- #include <linux/firmware.h>
- #include "firmware.h"
-
--#define SDIO_FUNC_0 0
-+/* Maximum number of I/O funcs */
-+#define NUM_SDIO_FUNCS 3
-+
- #define SDIO_FUNC_1 1
- #define SDIO_FUNC_2 2
-
-@@ -39,9 +41,6 @@
- #define INTR_STATUS_FUNC1 0x2
- #define INTR_STATUS_FUNC2 0x4
-
--/* Maximum number of I/O funcs */
--#define SDIOD_MAX_IOFUNCS 7
--
- /* mask of register map */
- #define REG_F0_REG_MASK 0x7FF
- #define REG_F1_MISC_MASK 0x1FFFF
-@@ -175,7 +174,7 @@ struct brcmf_sdio;
- struct brcmf_sdiod_freezer;
-
- struct brcmf_sdio_dev {
-- struct sdio_func *func[SDIO_MAX_FUNCS];
-+ struct sdio_func *func[NUM_SDIO_FUNCS];
- u8 num_funcs; /* Supported funcs on client */
- u32 sbwad; /* Save backplane window address */
- struct brcmf_core *cc_core; /* chipcommon core info struct */
-@@ -297,10 +296,10 @@ void brcmf_sdiod_intr_unregister(struct
- /* SDIO device register access interface */
- /* Accessors for SDIO Function 0 */
- #define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
-- sdio_f0_readb((sdiodev)->func[0], (addr), (r))
-+ sdio_f0_readb((sdiodev)->func[1], (addr), (r))
-
- #define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
-- sdio_f0_writeb((sdiodev)->func[0], (v), (addr), (ret))
-+ sdio_f0_writeb((sdiodev)->func[1], (v), (addr), (ret))
-
- /* Accessors for SDIO Function 1 */
- #define brcmf_sdiod_readb(sdiodev, addr, r) \
+++ /dev/null
-From bcadaaa097c7ec103fe75f9da41f8fe52693b644 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 19 Dec 2017 13:47:12 +0100
-Subject: [PATCH] brcmfmac: More efficient and slightly easier to read fixup
- for 4339 chips
-
-Its more efficient to test the register we're interested in first,
-potentially avoiding two more comparisons, and therefore always avoiding
-one comparison per call on all other chips.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-[arend: fix some checkpatch warnings]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -3772,15 +3772,16 @@ static u32 brcmf_sdio_buscore_read32(voi
-
- val = brcmf_sdiod_readl(sdiodev, addr, NULL);
-
-- if ((sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 ||
-- sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339) &&
-- addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
-+ if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) &&
-+ (sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339 ||
-+ sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) {
- rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
- if (rev >= 2) {
- val &= ~CID_ID_MASK;
- val |= BRCM_CC_4339_CHIP_ID;
- }
- }
-+
- return val;
- }
-
+++ /dev/null
-From 00eb62cfc5f806b003fe5d54c8b5fe9a9665482f Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Tue, 19 Dec 2017 13:47:13 +0100
-Subject: [PATCH] brcmfmac: Replace function index with function pointer
-
-In preparation for removing the function array, remove all code that
-refers to function by index and replace with pointers to the function
-itself.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-[arend: replace BUG() with WARN() macro]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 85 ++++++++++++----------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 15 ++--
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 6 +-
- 3 files changed, 56 insertions(+), 50 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -291,8 +291,9 @@ out:
- *ret = retval;
- }
-
--static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev, uint fn,
-- u32 addr, struct sk_buff *pkt)
-+static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev,
-+ struct sdio_func *func, u32 addr,
-+ struct sk_buff *pkt)
- {
- unsigned int req_sz;
- int err;
-@@ -301,13 +302,19 @@ static int brcmf_sdiod_buff_read(struct
- req_sz = pkt->len + 3;
- req_sz &= (uint)~3;
-
-- if (fn == 1)
-- err = sdio_memcpy_fromio(sdiodev->func[fn],
-- ((u8 *)(pkt->data)), addr, req_sz);
-- else
-- /* function 2 read is FIFO operation */
-- err = sdio_readsb(sdiodev->func[fn],
-- ((u8 *)(pkt->data)), addr, req_sz);
-+ switch (func->num) {
-+ case 1:
-+ err = sdio_memcpy_fromio(func, ((u8 *)(pkt->data)), addr,
-+ req_sz);
-+ break;
-+ case 2:
-+ err = sdio_readsb(func, ((u8 *)(pkt->data)), addr, req_sz);
-+ break;
-+ default:
-+ /* bail out as things are really fishy here */
-+ WARN(1, "invalid sdio function number: %d\n", func->num);
-+ err = -ENOMEDIUM;
-+ };
-
- if (err == -ENOMEDIUM)
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-@@ -315,8 +322,9 @@ static int brcmf_sdiod_buff_read(struct
- return err;
- }
-
--static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev, uint fn,
-- u32 addr, struct sk_buff *pkt)
-+static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev,
-+ struct sdio_func *func, u32 addr,
-+ struct sk_buff *pkt)
- {
- unsigned int req_sz;
- int err;
-@@ -325,8 +333,7 @@ static int brcmf_sdiod_buff_write(struct
- req_sz = pkt->len + 3;
- req_sz &= (uint)~3;
-
-- err = sdio_memcpy_toio(sdiodev->func[fn], addr,
-- ((u8 *)(pkt->data)), req_sz);
-+ err = sdio_memcpy_toio(func, addr, ((u8 *)(pkt->data)), req_sz);
-
- if (err == -ENOMEDIUM)
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-@@ -337,7 +344,7 @@ static int brcmf_sdiod_buff_write(struct
- /**
- * brcmf_sdiod_sglist_rw - SDIO interface function for block data access
- * @sdiodev: brcmfmac sdio device
-- * @fn: SDIO function number
-+ * @func: SDIO function
- * @write: direction flag
- * @addr: dongle memory address as source/destination
- * @pkt: skb pointer
-@@ -346,7 +353,8 @@ static int brcmf_sdiod_buff_write(struct
- * stack for block data access. It assumes that the skb passed down by the
- * caller has already been padded and aligned.
- */
--static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev, uint fn,
-+static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev,
-+ struct sdio_func *func,
- bool write, u32 addr,
- struct sk_buff_head *pktlist)
- {
-@@ -372,7 +380,7 @@ static int brcmf_sdiod_sglist_rw(struct
- req_sz = 0;
- skb_queue_walk(pktlist, pkt_next)
- req_sz += pkt_next->len;
-- req_sz = ALIGN(req_sz, sdiodev->func[fn]->cur_blksize);
-+ req_sz = ALIGN(req_sz, func->cur_blksize);
- while (req_sz > PAGE_SIZE) {
- pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE);
- if (pkt_next == NULL) {
-@@ -391,7 +399,7 @@ static int brcmf_sdiod_sglist_rw(struct
- target_list = &local_list;
- }
-
-- func_blk_sz = sdiodev->func[fn]->cur_blksize;
-+ func_blk_sz = func->cur_blksize;
- max_req_sz = sdiodev->max_request_size;
- max_seg_cnt = min_t(unsigned short, sdiodev->max_segment_count,
- target_list->qlen);
-@@ -408,10 +416,10 @@ static int brcmf_sdiod_sglist_rw(struct
- mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
- mmc_cmd.opcode = SD_IO_RW_EXTENDED;
- mmc_cmd.arg = write ? 1<<31 : 0; /* write flag */
-- mmc_cmd.arg |= (fn & 0x7) << 28; /* SDIO func num */
-- mmc_cmd.arg |= 1<<27; /* block mode */
-+ mmc_cmd.arg |= (func->num & 0x7) << 28; /* SDIO func num */
-+ mmc_cmd.arg |= 1 << 27; /* block mode */
- /* for function 1 the addr will be incremented */
-- mmc_cmd.arg |= (fn == 1) ? 1<<26 : 0;
-+ mmc_cmd.arg |= (func->num == 1) ? 1 << 26 : 0;
- mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
- mmc_req.cmd = &mmc_cmd;
- mmc_req.data = &mmc_dat;
-@@ -457,11 +465,11 @@ static int brcmf_sdiod_sglist_rw(struct
- mmc_cmd.arg |= (addr & 0x1FFFF) << 9; /* address */
- mmc_cmd.arg |= mmc_dat.blocks & 0x1FF; /* block count */
- /* incrementing addr for function 1 */
-- if (fn == 1)
-+ if (func->num == 1)
- addr += req_sz;
-
-- mmc_set_data_timeout(&mmc_dat, sdiodev->func[fn]->card);
-- mmc_wait_for_req(sdiodev->func[fn]->card->host, &mmc_req);
-+ mmc_set_data_timeout(&mmc_dat, func->card);
-+ mmc_wait_for_req(func->card->host, &mmc_req);
-
- ret = mmc_cmd.error ? mmc_cmd.error : mmc_dat.error;
- if (ret == -ENOMEDIUM) {
-@@ -541,7 +549,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr, pkt);
-+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, pkt);
-
- done:
- return err;
-@@ -566,13 +574,13 @@ int brcmf_sdiod_recv_chain(struct brcmf_
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- if (pktq->qlen == 1)
-- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
-+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr,
- pktq->next);
- else if (!sdiodev->sg_support) {
- glom_skb = brcmu_pkt_buf_get_skb(totlen);
- if (!glom_skb)
- return -ENOMEM;
-- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_2, addr,
-+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr,
- glom_skb);
- if (err)
- goto done;
-@@ -582,8 +590,8 @@ int brcmf_sdiod_recv_chain(struct brcmf_
- skb_pull(glom_skb, skb->len);
- }
- } else
-- err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, false, addr,
-- pktq);
-+ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], false,
-+ addr, pktq);
-
- done:
- brcmu_pkt_buf_free_skb(glom_skb);
-@@ -614,7 +622,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- if (!err)
-- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2, addr, mypkt);
-+ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2], addr,
-+ mypkt);
-
- brcmu_pkt_buf_free_skb(mypkt);
-
-@@ -639,14 +648,14 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
-
- if (pktq->qlen == 1 || !sdiodev->sg_support) {
- skb_queue_walk(pktq, skb) {
-- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_2,
-+ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2],
- addr, skb);
- if (err)
- break;
- }
- } else {
-- err = brcmf_sdiod_sglist_rw(sdiodev, SDIO_FUNC_2, true, addr,
-- pktq);
-+ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], true,
-+ addr, pktq);
- }
-
- return err;
-@@ -696,10 +705,10 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
-
- if (write) {
- memcpy(pkt->data, data, dsize);
-- err = brcmf_sdiod_buff_write(sdiodev, SDIO_FUNC_1,
-+ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[1],
- sdaddr, pkt);
- } else {
-- err = brcmf_sdiod_buff_read(sdiodev, SDIO_FUNC_1,
-+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[1],
- sdaddr, pkt);
- }
-
-@@ -728,12 +737,12 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
- return err;
- }
-
--int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn)
-+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func)
- {
- brcmf_dbg(SDIO, "Enter\n");
-
- /* Issue abort cmd52 command through F0 */
-- brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, fn, NULL);
-+ brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_ABORT, func->num, NULL);
-
- brcmf_dbg(SDIO, "Exit\n");
- return 0;
-@@ -1105,7 +1114,7 @@ static int brcmf_ops_sdio_suspend(struct
-
- func = container_of(dev, struct sdio_func, dev);
- brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
-- if (func->num != SDIO_FUNC_1)
-+ if (func->num != 1)
- return 0;
-
-
-@@ -1134,7 +1143,7 @@ static int brcmf_ops_sdio_resume(struct
- struct sdio_func *func = container_of(dev, struct sdio_func, dev);
-
- brcmf_dbg(SDIO, "Enter: F%d\n", func->num);
-- if (func->num != SDIO_FUNC_2)
-+ if (func->num != 2)
- return 0;
-
- brcmf_sdiod_freezer_off(sdiodev);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -1157,7 +1157,7 @@ static void brcmf_sdio_rxfail(struct brc
- rtx ? ", send NAK" : "");
-
- if (abort)
-- brcmf_sdiod_abort(bus->sdiodev, SDIO_FUNC_2);
-+ brcmf_sdiod_abort(bus->sdiodev, bus->sdiodev->func[2]);
-
- brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
- &err);
-@@ -1209,7 +1209,7 @@ static void brcmf_sdio_txfail(struct brc
- brcmf_err("sdio error, abort command and terminate frame\n");
- bus->sdcnt.tx_sderrs++;
-
-- brcmf_sdiod_abort(sdiodev, SDIO_FUNC_2);
-+ brcmf_sdiod_abort(sdiodev, sdiodev->func[2]);
- brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
- bus->sdcnt.f1regdata++;
-
-@@ -2072,7 +2072,7 @@ static int brcmf_sdio_txpkt_prep_sg(stru
- int ntail, ret;
-
- sdiodev = bus->sdiodev;
-- blksize = sdiodev->func[SDIO_FUNC_2]->cur_blksize;
-+ blksize = sdiodev->func[2]->cur_blksize;
- /* sg entry alignment should be a divisor of block size */
- WARN_ON(blksize % bus->sgentry_align);
-
-@@ -2441,7 +2441,7 @@ static void brcmf_sdio_bus_stop(struct d
-
- /* Turn off the bus (F2), free any pending packets */
- brcmf_dbg(INTR, "disable SDIO interrupts\n");
-- sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
-+ sdio_disable_func(sdiodev->func[2]);
-
- /* Clear any pending interrupts now that F2 is disabled */
- brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus),
-@@ -4066,8 +4066,7 @@ static void brcmf_sdio_firmware_callback
- brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata),
- SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL);
-
-- err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
--
-+ err = sdio_enable_func(sdiodev->func[2]);
-
- brcmf_dbg(INFO, "enable F2: err=%d\n", err);
-
-@@ -4082,7 +4081,7 @@ static void brcmf_sdio_firmware_callback
- brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
- } else {
- /* Disable F2 again */
-- sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
-+ sdio_disable_func(sdiodev->func[2]);
- goto release;
- }
-
-@@ -4219,7 +4218,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- sdio_claim_host(bus->sdiodev->func[1]);
-
- /* Disable F2 to clear any intermediate frame state on the dongle */
-- sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
-+ sdio_disable_func(bus->sdiodev->func[2]);
-
- bus->rxflow = false;
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -45,9 +45,6 @@
- #define REG_F0_REG_MASK 0x7FF
- #define REG_F1_MISC_MASK 0x1FFFF
-
--/* as of sdiod rev 0, supports 3 functions */
--#define SBSDIO_NUM_FUNCTION 3
--
- /* function 0 vendor specific CCCR registers */
-
- #define SDIO_CCCR_BRCM_CARDCAP 0xf0
-@@ -350,7 +347,8 @@ int brcmf_sdiod_ramrw(struct brcmf_sdio_
- u8 *data, uint size);
-
- /* Issue an abort to the specified function */
--int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, u8 fn);
-+int brcmf_sdiod_abort(struct brcmf_sdio_dev *sdiodev, struct sdio_func *func);
-+
- void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev);
- void brcmf_sdiod_change_state(struct brcmf_sdio_dev *sdiodev,
- enum brcmf_sdiod_state state);
+++ /dev/null
-From 9c3438ed215adba7025268ee1f0b6f7a2af12316 Mon Sep 17 00:00:00 2001
-From: Ian Molton <ian@mnementh.co.uk>
-Date: Tue, 19 Dec 2017 13:47:14 +0100
-Subject: [PATCH] brcmfmac: Clean up interrupt macros
-
-Make it more obvious that this code acually enables interrupts, and
-provide nice definitions for the bits in the register.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 3 ++-
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 8 +++++---
- 2 files changed, 7 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -149,7 +149,8 @@ int brcmf_sdiod_intr_register(struct brc
-
- /* must configure SDIO_CCCR_IENx to enable irq */
- data = brcmf_sdiod_func0_rb(sdiodev, SDIO_CCCR_IENx, &ret);
-- data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1;
-+ data |= SDIO_CCCR_IEN_FUNC1 | SDIO_CCCR_IEN_FUNC2 |
-+ SDIO_CCCR_IEN_FUNC0;
- brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, data, &ret);
-
- /* redirect, configure and enable io for interrupt signal */
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -24,9 +24,6 @@
- /* Maximum number of I/O funcs */
- #define NUM_SDIO_FUNCS 3
-
--#define SDIO_FUNC_1 1
--#define SDIO_FUNC_2 2
--
- #define SDIOD_FBR_SIZE 0x100
-
- /* io_en */
-@@ -52,6 +49,11 @@
- #define SDIO_CCCR_BRCM_CARDCAP_CMD14_EXT BIT(2)
- #define SDIO_CCCR_BRCM_CARDCAP_CMD_NODEC BIT(3)
-
-+/* Interrupt enable bits for each function */
-+#define SDIO_CCCR_IEN_FUNC0 BIT(0)
-+#define SDIO_CCCR_IEN_FUNC1 BIT(1)
-+#define SDIO_CCCR_IEN_FUNC2 BIT(2)
-+
- #define SDIO_CCCR_BRCM_CARDCTRL 0xf1
- #define SDIO_CCCR_BRCM_CARDCTRL_WLANRESET BIT(1)
-
+++ /dev/null
-From e3720dad99859251a8b0fe2807275a8afcfb560d Mon Sep 17 00:00:00 2001
-From: Double Lo <double.lo@cypress.com>
-Date: Tue, 19 Dec 2017 14:56:44 +0800
-Subject: [PATCH] brcmfmac: Support 43455 save-restore (SR) feature if FW
- include -sr
-
-This patch will add 43455 into the save-restore(SR) capable chip list, so
-the SR engine will be enabled with 43455 FW which built-in the -sr
-function.
-
-Signed-off-by: Double Lo <double.lo@cypress.com>
-Signed-off-by: Wright Feng <wright.feng@cypress.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-@@ -1338,6 +1338,7 @@ bool brcmf_chip_sr_capable(struct brcmf_
- switch (pub->chip) {
- case BRCM_CC_4354_CHIP_ID:
- case BRCM_CC_4356_CHIP_ID:
-+ case BRCM_CC_4345_CHIP_ID:
- /* explicitly check SR engine enable bit */
- pmu_cc3_mask = BIT(2);
- /* fall-through */
+++ /dev/null
-From c9aa7a91de740c537dc8c2f9f3d36fc651371b13 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 9 Jan 2018 13:22:52 +0100
-Subject: [PATCH] brcmfmac: Remove array of functions
-
-Replace the array of functions with a pair of pointers to the
-relevant functions.
-
-Signed-off-by: Ian Molton <ian@mnementh.co.uk>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 115 +++++++-------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 168 ++++++++++-----------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 15 +-
- 3 files changed, 146 insertions(+), 152 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -118,7 +118,7 @@ int brcmf_sdiod_intr_register(struct brc
-
- ret = request_irq(pdata->oob_irq_nr, brcmf_sdiod_oob_irqhandler,
- pdata->oob_irq_flags, "brcmf_oob_intr",
-- &sdiodev->func[1]->dev);
-+ &sdiodev->func1->dev);
- if (ret != 0) {
- brcmf_err("request_irq failed %d\n", ret);
- return ret;
-@@ -132,7 +132,7 @@ int brcmf_sdiod_intr_register(struct brc
- }
- sdiodev->irq_wake = true;
-
-- sdio_claim_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
-
- if (sdiodev->bus_if->chip == BRCM_CC_43362_CHIP_ID) {
- /* assign GPIO to SDIO core */
-@@ -159,13 +159,13 @@ int brcmf_sdiod_intr_register(struct brc
- data |= SDIO_CCCR_BRCM_SEPINT_ACT_HI;
- brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT,
- data, &ret);
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
- } else {
- brcmf_dbg(SDIO, "Entering\n");
-- sdio_claim_host(sdiodev->func[1]);
-- sdio_claim_irq(sdiodev->func[1], brcmf_sdiod_ib_irqhandler);
-- sdio_claim_irq(sdiodev->func[2], brcmf_sdiod_dummy_irqhandler);
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
-+ sdio_claim_irq(sdiodev->func1, brcmf_sdiod_ib_irqhandler);
-+ sdio_claim_irq(sdiodev->func2, brcmf_sdiod_dummy_irqhandler);
-+ sdio_release_host(sdiodev->func1);
- sdiodev->sd_irq_requested = true;
- }
-
-@@ -183,26 +183,26 @@ void brcmf_sdiod_intr_unregister(struct
- struct brcmfmac_sdio_pd *pdata;
-
- pdata = &sdiodev->settings->bus.sdio;
-- sdio_claim_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
- brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL);
- brcmf_sdiod_func0_wb(sdiodev, SDIO_CCCR_IENx, 0, NULL);
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
-
- sdiodev->oob_irq_requested = false;
- if (sdiodev->irq_wake) {
- disable_irq_wake(pdata->oob_irq_nr);
- sdiodev->irq_wake = false;
- }
-- free_irq(pdata->oob_irq_nr, &sdiodev->func[1]->dev);
-+ free_irq(pdata->oob_irq_nr, &sdiodev->func1->dev);
- sdiodev->irq_en = false;
- sdiodev->oob_irq_requested = false;
- }
-
- if (sdiodev->sd_irq_requested) {
-- sdio_claim_host(sdiodev->func[1]);
-- sdio_release_irq(sdiodev->func[2]);
-- sdio_release_irq(sdiodev->func[1]);
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
-+ sdio_release_irq(sdiodev->func2);
-+ sdio_release_irq(sdiodev->func1);
-+ sdio_release_host(sdiodev->func1);
- sdiodev->sd_irq_requested = false;
- }
- }
-@@ -264,7 +264,7 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-- data = sdio_readl(sdiodev->func[1], addr, &retval);
-+ data = sdio_readl(sdiodev->func1, addr, &retval);
-
- out:
- if (ret)
-@@ -285,7 +285,7 @@ void brcmf_sdiod_writel(struct brcmf_sdi
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-- sdio_writel(sdiodev->func[1], data, addr, &retval);
-+ sdio_writel(sdiodev->func1, data, addr, &retval);
-
- out:
- if (ret)
-@@ -550,7 +550,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr, pkt);
-+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr, pkt);
-
- done:
- return err;
-@@ -575,13 +575,13 @@ int brcmf_sdiod_recv_chain(struct brcmf_
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- if (pktq->qlen == 1)
-- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr,
-+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr,
- pktq->next);
- else if (!sdiodev->sg_support) {
- glom_skb = brcmu_pkt_buf_get_skb(totlen);
- if (!glom_skb)
- return -ENOMEM;
-- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[2], addr,
-+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr,
- glom_skb);
- if (err)
- goto done;
-@@ -591,7 +591,7 @@ int brcmf_sdiod_recv_chain(struct brcmf_
- skb_pull(glom_skb, skb->len);
- }
- } else
-- err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], false,
-+ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func2, false,
- addr, pktq);
-
- done:
-@@ -623,7 +623,7 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- if (!err)
-- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2], addr,
-+ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2, addr,
- mypkt);
-
- brcmu_pkt_buf_free_skb(mypkt);
-@@ -649,13 +649,13 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
-
- if (pktq->qlen == 1 || !sdiodev->sg_support) {
- skb_queue_walk(pktq, skb) {
-- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[2],
-+ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2,
- addr, skb);
- if (err)
- break;
- }
- } else {
-- err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func[2], true,
-+ err = brcmf_sdiod_sglist_rw(sdiodev, sdiodev->func2, true,
- addr, pktq);
- }
-
-@@ -686,7 +686,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
- else
- dsize = size;
-
-- sdio_claim_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
-
- /* Do the transfer(s) */
- while (size) {
-@@ -706,10 +706,10 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
-
- if (write) {
- memcpy(pkt->data, data, dsize);
-- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func[1],
-+ err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func1,
- sdaddr, pkt);
- } else {
-- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func[1],
-+ err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func1,
- sdaddr, pkt);
- }
-
-@@ -733,7 +733,7 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
-
- dev_kfree_skb(pkt);
-
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
-
- return err;
- }
-@@ -757,7 +757,7 @@ void brcmf_sdiod_sgtable_alloc(struct br
- uint nents;
- int err;
-
-- func = sdiodev->func[2];
-+ func = sdiodev->func2;
- host = func->card->host;
- sdiodev->sg_support = host->max_segs > 1;
- max_blocks = min_t(uint, host->max_blk_count, 511u);
-@@ -818,17 +818,17 @@ static int brcmf_sdiod_freezer_on(struct
- brcmf_sdio_trigger_dpc(sdiodev->bus);
- wait_event(sdiodev->freezer->thread_freeze,
- atomic_read(expect) == sdiodev->freezer->frozen_count);
-- sdio_claim_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
- res = brcmf_sdio_sleep(sdiodev->bus, true);
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
- return res;
- }
-
- static void brcmf_sdiod_freezer_off(struct brcmf_sdio_dev *sdiodev)
- {
-- sdio_claim_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
- brcmf_sdio_sleep(sdiodev->bus, false);
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
- atomic_set(&sdiodev->freezer->freezing, 0);
- complete_all(&sdiodev->freezer->resumed);
- }
-@@ -878,19 +878,19 @@ static int brcmf_sdiod_remove(struct brc
- brcmf_sdiod_freezer_detach(sdiodev);
-
- /* Disable Function 2 */
-- sdio_claim_host(sdiodev->func[2]);
-- sdio_disable_func(sdiodev->func[2]);
-- sdio_release_host(sdiodev->func[2]);
-+ sdio_claim_host(sdiodev->func2);
-+ sdio_disable_func(sdiodev->func2);
-+ sdio_release_host(sdiodev->func2);
-
- /* Disable Function 1 */
-- sdio_claim_host(sdiodev->func[1]);
-- sdio_disable_func(sdiodev->func[1]);
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
-+ sdio_disable_func(sdiodev->func1);
-+ sdio_release_host(sdiodev->func1);
-
- sg_free_table(&sdiodev->sgtable);
- sdiodev->sbwad = 0;
-
-- pm_runtime_allow(sdiodev->func[1]->card->host->parent);
-+ pm_runtime_allow(sdiodev->func1->card->host->parent);
- return 0;
- }
-
-@@ -906,29 +906,27 @@ static int brcmf_sdiod_probe(struct brcm
- {
- int ret = 0;
-
-- sdiodev->num_funcs = 2;
-+ sdio_claim_host(sdiodev->func1);
-
-- sdio_claim_host(sdiodev->func[1]);
--
-- ret = sdio_set_block_size(sdiodev->func[1], SDIO_FUNC1_BLOCKSIZE);
-+ ret = sdio_set_block_size(sdiodev->func1, SDIO_FUNC1_BLOCKSIZE);
- if (ret) {
- brcmf_err("Failed to set F1 blocksize\n");
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
- goto out;
- }
-- ret = sdio_set_block_size(sdiodev->func[2], SDIO_FUNC2_BLOCKSIZE);
-+ ret = sdio_set_block_size(sdiodev->func2, SDIO_FUNC2_BLOCKSIZE);
- if (ret) {
- brcmf_err("Failed to set F2 blocksize\n");
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
- goto out;
- }
-
- /* increase F2 timeout */
-- sdiodev->func[2]->enable_timeout = SDIO_WAIT_F2RDY;
-+ sdiodev->func2->enable_timeout = SDIO_WAIT_F2RDY;
-
- /* Enable Function 1 */
-- ret = sdio_enable_func(sdiodev->func[1]);
-- sdio_release_host(sdiodev->func[1]);
-+ ret = sdio_enable_func(sdiodev->func1);
-+ sdio_release_host(sdiodev->func1);
- if (ret) {
- brcmf_err("Failed to enable F1: err=%d\n", ret);
- goto out;
-@@ -944,7 +942,7 @@ static int brcmf_sdiod_probe(struct brcm
- ret = -ENODEV;
- goto out;
- }
-- brcmf_sdiod_host_fixup(sdiodev->func[2]->card->host);
-+ brcmf_sdiod_host_fixup(sdiodev->func2->card->host);
- out:
- if (ret)
- brcmf_sdiod_remove(sdiodev);
-@@ -1032,16 +1030,15 @@ static int brcmf_ops_sdio_probe(struct s
- /* store refs to functions used. mmc_card does
- * not hold the F0 function pointer.
- */
-- sdiodev->func[0] = NULL;
-- sdiodev->func[1] = func->card->sdio_func[0];
-- sdiodev->func[2] = func;
-+ sdiodev->func1 = func->card->sdio_func[0];
-+ sdiodev->func2 = func;
-
- sdiodev->bus_if = bus_if;
- bus_if->bus_priv.sdio = sdiodev;
- bus_if->proto_type = BRCMF_PROTO_BCDC;
- dev_set_drvdata(&func->dev, bus_if);
-- dev_set_drvdata(&sdiodev->func[1]->dev, bus_if);
-- sdiodev->dev = &sdiodev->func[1]->dev;
-+ dev_set_drvdata(&sdiodev->func1->dev, bus_if);
-+ sdiodev->dev = &sdiodev->func1->dev;
-
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN);
-
-@@ -1057,7 +1054,7 @@ static int brcmf_ops_sdio_probe(struct s
-
- fail:
- dev_set_drvdata(&func->dev, NULL);
-- dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
-+ dev_set_drvdata(&sdiodev->func1->dev, NULL);
- kfree(sdiodev);
- kfree(bus_if);
- return err;
-@@ -1086,8 +1083,8 @@ static void brcmf_ops_sdio_remove(struct
- /* only proceed with rest of cleanup if func 1 */
- brcmf_sdiod_remove(sdiodev);
-
-- dev_set_drvdata(&sdiodev->func[1]->dev, NULL);
-- dev_set_drvdata(&sdiodev->func[2]->dev, NULL);
-+ dev_set_drvdata(&sdiodev->func1->dev, NULL);
-+ dev_set_drvdata(&sdiodev->func2->dev, NULL);
-
- kfree(bus_if);
- kfree(sdiodev);
-@@ -1132,7 +1129,7 @@ static int brcmf_ops_sdio_suspend(struct
- else
- sdio_flags |= MMC_PM_WAKE_SDIO_IRQ;
- }
-- if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
-+ if (sdio_set_host_pm_flags(sdiodev->func1, sdio_flags))
- brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
- return 0;
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -979,7 +979,7 @@ static int brcmf_sdio_readshared(struct
- struct sdpcm_shared_le sh_le;
- __le32 addr_le;
-
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- brcmf_sdio_bus_sleep(bus, false, false);
-
- /*
-@@ -1013,7 +1013,7 @@ static int brcmf_sdio_readshared(struct
- if (rv < 0)
- goto fail;
-
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
-
- /* Endianness */
- sh->flags = le32_to_cpu(sh_le.flags);
-@@ -1035,7 +1035,7 @@ static int brcmf_sdio_readshared(struct
- fail:
- brcmf_err("unable to obtain sdpcm_shared info: rv=%d (addr=0x%x)\n",
- rv, addr);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- return rv;
- }
-
-@@ -1157,7 +1157,7 @@ static void brcmf_sdio_rxfail(struct brc
- rtx ? ", send NAK" : "");
-
- if (abort)
-- brcmf_sdiod_abort(bus->sdiodev, bus->sdiodev->func[2]);
-+ brcmf_sdiod_abort(bus->sdiodev, bus->sdiodev->func2);
-
- brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM,
- &err);
-@@ -1209,7 +1209,7 @@ static void brcmf_sdio_txfail(struct brc
- brcmf_err("sdio error, abort command and terminate frame\n");
- bus->sdcnt.tx_sderrs++;
-
-- brcmf_sdiod_abort(sdiodev, sdiodev->func[2]);
-+ brcmf_sdiod_abort(sdiodev, sdiodev->func2);
- brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, NULL);
- bus->sdcnt.f1regdata++;
-
-@@ -1565,10 +1565,10 @@ static u8 brcmf_sdio_rxglom(struct brcmf
- * read directly into the chained packet, or allocate a large
- * packet and and copy into the chain.
- */
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- errcode = brcmf_sdiod_recv_chain(bus->sdiodev,
- &bus->glom, dlen);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- bus->sdcnt.f2rxdata++;
-
- /* On failure, kill the superframe */
-@@ -1576,11 +1576,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf
- brcmf_err("glom read of %d bytes failed: %d\n",
- dlen, errcode);
-
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- brcmf_sdio_rxfail(bus, true, false);
- bus->sdcnt.rxglomfail++;
- brcmf_sdio_free_glom(bus);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- return 0;
- }
-
-@@ -1590,10 +1590,10 @@ static u8 brcmf_sdio_rxglom(struct brcmf
-
- rd_new.seq_num = rxseq;
- rd_new.len = dlen;
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- errcode = brcmf_sdio_hdparse(bus, pfirst->data, &rd_new,
- BRCMF_SDIO_FT_SUPER);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- bus->cur_read.len = rd_new.len_nxtfrm << 4;
-
- /* Remove superframe header, remember offset */
-@@ -1609,10 +1609,10 @@ static u8 brcmf_sdio_rxglom(struct brcmf
-
- rd_new.len = pnext->len;
- rd_new.seq_num = rxseq++;
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- errcode = brcmf_sdio_hdparse(bus, pnext->data, &rd_new,
- BRCMF_SDIO_FT_SUB);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
- pnext->data, 32, "subframe:\n");
-
-@@ -1621,11 +1621,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf
-
- if (errcode) {
- /* Terminate frame on error */
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- brcmf_sdio_rxfail(bus, true, false);
- bus->sdcnt.rxglomfail++;
- brcmf_sdio_free_glom(bus);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- bus->cur_read.len = 0;
- return 0;
- }
-@@ -1833,7 +1833,7 @@ static uint brcmf_sdio_readframes(struct
-
- rd->len_left = rd->len;
- /* read header first for unknow frame length */
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- if (!rd->len) {
- ret = brcmf_sdiod_recv_buf(bus->sdiodev,
- bus->rxhdr, BRCMF_FIRSTREAD);
-@@ -1843,7 +1843,7 @@ static uint brcmf_sdio_readframes(struct
- ret);
- bus->sdcnt.rx_hdrfail++;
- brcmf_sdio_rxfail(bus, true, true);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- continue;
- }
-
-@@ -1853,7 +1853,7 @@ static uint brcmf_sdio_readframes(struct
-
- if (brcmf_sdio_hdparse(bus, bus->rxhdr, rd,
- BRCMF_SDIO_FT_NORMAL)) {
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- if (!bus->rxpending)
- break;
- else
-@@ -1869,7 +1869,7 @@ static uint brcmf_sdio_readframes(struct
- rd->len_nxtfrm = 0;
- /* treat all packet as event if we don't know */
- rd->channel = SDPCM_EVENT_CHANNEL;
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- continue;
- }
- rd->len_left = rd->len > BRCMF_FIRSTREAD ?
-@@ -1886,7 +1886,7 @@ static uint brcmf_sdio_readframes(struct
- brcmf_err("brcmu_pkt_buf_get_skb failed\n");
- brcmf_sdio_rxfail(bus, false,
- RETRYCHAN(rd->channel));
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- continue;
- }
- skb_pull(pkt, head_read);
-@@ -1894,16 +1894,16 @@ static uint brcmf_sdio_readframes(struct
-
- ret = brcmf_sdiod_recv_pkt(bus->sdiodev, pkt);
- bus->sdcnt.f2rxdata++;
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
-
- if (ret < 0) {
- brcmf_err("read %d bytes from channel %d failed: %d\n",
- rd->len, rd->channel, ret);
- brcmu_pkt_buf_free_skb(pkt);
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- brcmf_sdio_rxfail(bus, true,
- RETRYCHAN(rd->channel));
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- continue;
- }
-
-@@ -1914,7 +1914,7 @@ static uint brcmf_sdio_readframes(struct
- } else {
- memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
- rd_new.seq_num = rd->seq_num;
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new,
- BRCMF_SDIO_FT_NORMAL)) {
- rd->len = 0;
-@@ -1927,11 +1927,11 @@ static uint brcmf_sdio_readframes(struct
- roundup(rd_new.len, 16) >> 4);
- rd->len = 0;
- brcmf_sdio_rxfail(bus, true, true);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- brcmu_pkt_buf_free_skb(pkt);
- continue;
- }
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- rd->len_nxtfrm = rd_new.len_nxtfrm;
- rd->channel = rd_new.channel;
- rd->dat_offset = rd_new.dat_offset;
-@@ -1947,9 +1947,9 @@ static uint brcmf_sdio_readframes(struct
- rd_new.seq_num);
- /* Force retry w/normal header read */
- rd->len = 0;
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- brcmf_sdio_rxfail(bus, false, true);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- brcmu_pkt_buf_free_skb(pkt);
- continue;
- }
-@@ -1972,9 +1972,9 @@ static uint brcmf_sdio_readframes(struct
- } else {
- brcmf_err("%s: glom superframe w/o "
- "descriptor!\n", __func__);
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- brcmf_sdio_rxfail(bus, false, false);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- }
- /* prepare the descriptor for the next read */
- rd->len = rd->len_nxtfrm << 4;
-@@ -2072,7 +2072,7 @@ static int brcmf_sdio_txpkt_prep_sg(stru
- int ntail, ret;
-
- sdiodev = bus->sdiodev;
-- blksize = sdiodev->func[2]->cur_blksize;
-+ blksize = sdiodev->func2->cur_blksize;
- /* sg entry alignment should be a divisor of block size */
- WARN_ON(blksize % bus->sgentry_align);
-
-@@ -2251,14 +2251,14 @@ static int brcmf_sdio_txpkt(struct brcmf
- if (ret)
- goto done;
-
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- ret = brcmf_sdiod_send_pkt(bus->sdiodev, pktq);
- bus->sdcnt.f2txdata++;
-
- if (ret < 0)
- brcmf_sdio_txfail(bus);
-
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
-
- done:
- brcmf_sdio_txpkt_postp(bus, pktq);
-@@ -2314,10 +2314,11 @@ static uint brcmf_sdio_sendfromq(struct
- /* In poll mode, need to check for other events */
- if (!bus->intr) {
- /* Check device status, signal pending interrupt */
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- intstatus = brcmf_sdiod_readl(bus->sdiodev,
- intstat_addr, &ret);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
-+
- bus->sdcnt.f2txdata++;
- if (ret != 0)
- break;
-@@ -2417,7 +2418,7 @@ static void brcmf_sdio_bus_stop(struct d
- }
-
- if (sdiodev->state != BRCMF_SDIOD_NOMEDIUM) {
-- sdio_claim_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
-
- /* Enable clock for device interrupts */
- brcmf_sdio_bus_sleep(bus, false, false);
-@@ -2441,13 +2442,13 @@ static void brcmf_sdio_bus_stop(struct d
-
- /* Turn off the bus (F2), free any pending packets */
- brcmf_dbg(INTR, "disable SDIO interrupts\n");
-- sdio_disable_func(sdiodev->func[2]);
-+ sdio_disable_func(sdiodev->func2);
-
- /* Clear any pending interrupts now that F2 is disabled */
- brcmf_sdiod_writel(sdiodev, core->base + SD_REG(intstatus),
- local_hostintmask, NULL);
-
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
- }
- /* Clear the data packet queues */
- brcmu_pktq_flush(&bus->txq, true, NULL, NULL);
-@@ -2522,7 +2523,7 @@ static void brcmf_sdio_dpc(struct brcmf_
-
- brcmf_dbg(TRACE, "Enter\n");
-
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
-
- /* If waiting for HTAVAIL, check status */
- if (!bus->sr_enabled && bus->clkstate == CLK_PENDING) {
-@@ -2585,7 +2586,7 @@ static void brcmf_sdio_dpc(struct brcmf_
- intstatus |= brcmf_sdio_hostmail(bus);
- }
-
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
-
- /* Generally don't ask for these, can get CRC errors... */
- if (intstatus & I_WR_OOSYNC) {
-@@ -2628,7 +2629,7 @@ 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]);
-+ sdio_claim_host(bus->sdiodev->func1);
- if (bus->ctrl_frame_stat) {
- err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf,
- bus->ctrl_frame_len);
-@@ -2636,7 +2637,7 @@ static void brcmf_sdio_dpc(struct brcmf_
- wmb();
- bus->ctrl_frame_stat = false;
- }
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- brcmf_sdio_wait_event_wakeup(bus);
- }
- /* Send queued frames (limit 1 if rx may still be pending) */
-@@ -2652,14 +2653,14 @@ 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) {
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- if (bus->ctrl_frame_stat) {
- bus->ctrl_frame_err = -ENODEV;
- wmb();
- bus->ctrl_frame_stat = false;
- brcmf_sdio_wait_event_wakeup(bus);
- }
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- }
- } else if (atomic_read(&bus->intstatus) ||
- atomic_read(&bus->ipend) > 0 ||
-@@ -2874,13 +2875,13 @@ brcmf_sdio_bus_txctl(struct device *dev,
- CTL_DONE_TIMEOUT);
- ret = 0;
- if (bus->ctrl_frame_stat) {
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- 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]);
-+ sdio_release_host(bus->sdiodev->func1);
- }
- if (!ret) {
- brcmf_dbg(SDIO, "ctrl_frame complete, err=%d\n",
-@@ -3004,7 +3005,7 @@ static int brcmf_sdio_assert_info(struct
- return 0;
- }
-
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- if (sh->assert_file_addr != 0) {
- error = brcmf_sdiod_ramrw(bus->sdiodev, false,
- sh->assert_file_addr, (u8 *)file, 80);
-@@ -3017,7 +3018,7 @@ static int brcmf_sdio_assert_info(struct
- if (error < 0)
- return error;
- }
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
-
- seq_printf(seq, "dongle assert: %s:%d: assert(%s)\n",
- file, sh->assert_line, expr);
-@@ -3291,7 +3292,7 @@ static int brcmf_sdio_download_firmware(
- int bcmerror;
- u32 rstvec;
-
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
-
- rstvec = get_unaligned_le32(fw->data);
-@@ -3320,7 +3321,7 @@ static int brcmf_sdio_download_firmware(
-
- err:
- brcmf_sdio_clkctl(bus, CLK_SDONLY, false);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- return bcmerror;
- }
-
-@@ -3435,7 +3436,7 @@ static int brcmf_sdio_bus_preinit(struct
- if (sdiodev->sg_support) {
- bus->txglom = false;
- value = 1;
-- pad_size = bus->sdiodev->func[2]->cur_blksize << 1;
-+ pad_size = bus->sdiodev->func2->cur_blksize << 1;
- err = brcmf_iovar_data_set(bus->sdiodev->dev, "bus:rxglom",
- &value, sizeof(u32));
- if (err < 0) {
-@@ -3477,7 +3478,7 @@ static int brcmf_sdio_bus_get_memdump(st
-
- address = bus->ci->rambase;
- offset = err = 0;
-- sdio_claim_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
- while (offset < mem_size) {
- len = ((offset + MEMBLOCK) < mem_size) ? MEMBLOCK :
- mem_size - offset;
-@@ -3493,7 +3494,7 @@ static int brcmf_sdio_bus_get_memdump(st
- }
-
- done:
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
- return err;
- }
-
-@@ -3550,11 +3551,10 @@ static void brcmf_sdio_bus_watchdog(stru
- if (!bus->dpc_triggered) {
- u8 devpend;
-
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- devpend = brcmf_sdiod_func0_rb(bus->sdiodev,
-- SDIO_CCCR_INTx,
-- NULL);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ SDIO_CCCR_INTx, NULL);
-+ sdio_release_host(bus->sdiodev->func1);
- intstatus = devpend & (INTR_STATUS_FUNC1 |
- INTR_STATUS_FUNC2);
- }
-@@ -3580,13 +3580,13 @@ static void brcmf_sdio_bus_watchdog(stru
- bus->console.count += jiffies_to_msecs(BRCMF_WD_POLL);
- if (bus->console.count >= bus->console_interval) {
- bus->console.count -= bus->console_interval;
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- /* Make sure backplane clock is on */
- brcmf_sdio_bus_sleep(bus, false, false);
- if (brcmf_sdio_readconsole(bus) < 0)
- /* stop on error */
- bus->console_interval = 0;
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- }
- }
- #endif /* DEBUG */
-@@ -3599,11 +3599,11 @@ static void brcmf_sdio_bus_watchdog(stru
- bus->idlecount++;
- if (bus->idlecount > bus->idletime) {
- brcmf_dbg(SDIO, "idle\n");
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- brcmf_sdio_wd_timer(bus, false);
- bus->idlecount = 0;
- brcmf_sdio_bus_sleep(bus, true, false);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- }
- } else {
- bus->idlecount = 0;
-@@ -3773,8 +3773,8 @@ static u32 brcmf_sdio_buscore_read32(voi
- val = brcmf_sdiod_readl(sdiodev, addr, NULL);
-
- if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) &&
-- (sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4339 ||
-- sdiodev->func[1]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) {
-+ (sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4339 ||
-+ sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) {
- rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
- if (rev >= 2) {
- val &= ~CID_ID_MASK;
-@@ -3810,7 +3810,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
- u32 drivestrength;
-
- sdiodev = bus->sdiodev;
-- sdio_claim_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
-
- pr_debug("F1 signature read @0x18000000=0x%4x\n",
- brcmf_sdiod_readl(sdiodev, SI_ENUM_BASE, NULL));
-@@ -3877,8 +3877,8 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
- /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
- * is true or when platform data OOB irq is true).
- */
-- if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
-- ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
-+ if ((sdio_get_host_pm_caps(sdiodev->func1) & MMC_PM_KEEP_POWER) &&
-+ ((sdio_get_host_pm_caps(sdiodev->func1) & MMC_PM_WAKE_SDIO_IRQ) ||
- (sdiodev->settings->bus.sdio.oob_irq_supported)))
- sdiodev->bus_if->wowl_supported = true;
- #endif
-@@ -3917,7 +3917,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
- if (err)
- goto fail;
-
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
-
- brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
-
-@@ -3938,7 +3938,7 @@ brcmf_sdio_probe_attach(struct brcmf_sdi
- return true;
-
- fail:
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
- return false;
- }
-
-@@ -4044,7 +4044,7 @@ static void brcmf_sdio_firmware_callback
- bus->sdcnt.tickcnt = 0;
- brcmf_sdio_wd_timer(bus, true);
-
-- sdio_claim_host(sdiodev->func[1]);
-+ sdio_claim_host(sdiodev->func1);
-
- /* Make sure backplane clock is on, needed to generate F2 interrupt */
- brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
-@@ -4066,7 +4066,7 @@ static void brcmf_sdio_firmware_callback
- brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata),
- SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL);
-
-- err = sdio_enable_func(sdiodev->func[2]);
-+ err = sdio_enable_func(sdiodev->func2);
-
- brcmf_dbg(INFO, "enable F2: err=%d\n", err);
-
-@@ -4081,7 +4081,7 @@ static void brcmf_sdio_firmware_callback
- brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
- } else {
- /* Disable F2 again */
-- sdio_disable_func(sdiodev->func[2]);
-+ sdio_disable_func(sdiodev->func2);
- goto release;
- }
-
-@@ -4106,7 +4106,7 @@ static void brcmf_sdio_firmware_callback
- if (err != 0)
- brcmf_sdio_clkctl(bus, CLK_NONE, false);
-
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
-
- err = brcmf_bus_started(dev);
- if (err != 0) {
-@@ -4116,10 +4116,10 @@ static void brcmf_sdio_firmware_callback
- return;
-
- release:
-- sdio_release_host(sdiodev->func[1]);
-+ sdio_release_host(sdiodev->func1);
- fail:
- brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
-- device_release_driver(&sdiodev->func[2]->dev);
-+ device_release_driver(&sdiodev->func2->dev);
- device_release_driver(dev);
- }
-
-@@ -4146,7 +4146,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
-
- /* single-threaded workqueue */
- wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM,
-- dev_name(&sdiodev->func[1]->dev));
-+ dev_name(&sdiodev->func1->dev));
- if (!wq) {
- brcmf_err("insufficient memory to create txworkqueue\n");
- goto fail;
-@@ -4173,7 +4173,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- init_completion(&bus->watchdog_wait);
- bus->watchdog_tsk = kthread_run(brcmf_sdio_watchdog_thread,
- bus, "brcmf_wdog/%s",
-- dev_name(&sdiodev->func[1]->dev));
-+ dev_name(&sdiodev->func1->dev));
- if (IS_ERR(bus->watchdog_tsk)) {
- pr_warn("brcmf_watchdog thread failed to start\n");
- bus->watchdog_tsk = NULL;
-@@ -4199,7 +4199,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- }
-
- /* Query the F2 block size, set roundup accordingly */
-- bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
-+ bus->blocksize = bus->sdiodev->func2->cur_blksize;
- bus->roundup = min(max_roundup, bus->blocksize);
-
- /* Allocate buffers */
-@@ -4215,17 +4215,17 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- }
- }
-
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
-
- /* Disable F2 to clear any intermediate frame state on the dongle */
-- sdio_disable_func(bus->sdiodev->func[2]);
-+ sdio_disable_func(bus->sdiodev->func2);
-
- bus->rxflow = false;
-
- /* Done with backplane-dependent accesses, can drop clock... */
- brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
-
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
-
- /* ...and initialize clock/power states */
- bus->clkstate = CLK_SDONLY;
-@@ -4277,7 +4277,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]);
-+ sdio_claim_host(bus->sdiodev->func1);
- brcmf_sdio_wd_timer(bus, false);
- brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
- /* Leave the device in state where it is
-@@ -4287,7 +4287,7 @@ void brcmf_sdio_remove(struct brcmf_sdio
- msleep(20);
- brcmf_chip_set_passive(bus->ci);
- brcmf_sdio_clkctl(bus, CLK_NONE, false);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
- }
- brcmf_chip_detach(bus->ci);
- }
-@@ -4334,9 +4334,9 @@ int brcmf_sdio_sleep(struct brcmf_sdio *
- {
- int ret;
-
-- sdio_claim_host(bus->sdiodev->func[1]);
-+ sdio_claim_host(bus->sdiodev->func1);
- ret = brcmf_sdio_bus_sleep(bus, sleep, false);
-- sdio_release_host(bus->sdiodev->func[1]);
-+ sdio_release_host(bus->sdiodev->func1);
-
- return ret;
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
-@@ -21,9 +21,6 @@
- #include <linux/firmware.h>
- #include "firmware.h"
-
--/* Maximum number of I/O funcs */
--#define NUM_SDIO_FUNCS 3
--
- #define SDIOD_FBR_SIZE 0x100
-
- /* io_en */
-@@ -173,8 +170,8 @@ struct brcmf_sdio;
- struct brcmf_sdiod_freezer;
-
- struct brcmf_sdio_dev {
-- struct sdio_func *func[NUM_SDIO_FUNCS];
-- u8 num_funcs; /* Supported funcs on client */
-+ struct sdio_func *func1;
-+ struct sdio_func *func2;
- u32 sbwad; /* Save backplane window address */
- struct brcmf_core *cc_core; /* chipcommon core info struct */
- struct brcmf_sdio *bus;
-@@ -295,17 +292,17 @@ void brcmf_sdiod_intr_unregister(struct
- /* SDIO device register access interface */
- /* Accessors for SDIO Function 0 */
- #define brcmf_sdiod_func0_rb(sdiodev, addr, r) \
-- sdio_f0_readb((sdiodev)->func[1], (addr), (r))
-+ sdio_f0_readb((sdiodev)->func1, (addr), (r))
-
- #define brcmf_sdiod_func0_wb(sdiodev, addr, v, ret) \
-- sdio_f0_writeb((sdiodev)->func[1], (v), (addr), (ret))
-+ sdio_f0_writeb((sdiodev)->func1, (v), (addr), (ret))
-
- /* Accessors for SDIO Function 1 */
- #define brcmf_sdiod_readb(sdiodev, addr, r) \
-- sdio_readb((sdiodev)->func[1], (addr), (r))
-+ sdio_readb((sdiodev)->func1, (addr), (r))
-
- #define brcmf_sdiod_writeb(sdiodev, addr, v, ret) \
-- sdio_writeb((sdiodev)->func[1], (v), (addr), (ret))
-+ sdio_writeb((sdiodev)->func1, (v), (addr), (ret))
-
- u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret);
- void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr, u32 data,
+++ /dev/null
-From 32adbcaa5df49f1977441f7a4bf180a0bcfe9966 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 9 Jan 2018 13:22:53 +0100
-Subject: [PATCH] brcmfmac: add comment block in brcmf_sdio_buscore_read()
-
-In brcmf_sdio_buscore_read() there is some special handling upon
-register access to chipid register of the chipcommon core. Add
-comment explaining why it is done here.
-
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -3772,6 +3772,13 @@ static u32 brcmf_sdio_buscore_read32(voi
-
- val = brcmf_sdiod_readl(sdiodev, addr, NULL);
-
-+ /*
-+ * this is a bit of special handling if reading the chipcommon chipid
-+ * register. The 4339 is a next-gen of the 4335. It uses the same
-+ * SDIO device id as 4335 and the chipid register returns 4335 as well.
-+ * It can be identified as 4339 by looking at the chip revision. It
-+ * is corrected here so the chip.c module has the right info.
-+ */
- if (addr == CORE_CC_REG(SI_ENUM_BASE, chipid) &&
- (sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4339 ||
- sdiodev->func1->device == SDIO_DEVICE_ID_BROADCOM_4335_4339)) {
+++ /dev/null
-From 378f6a16043e5d3346301fc618f503e97aea335b Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 9 Jan 2018 13:22:54 +0100
-Subject: [PATCH] brcmfmac: rename brcmf_sdiod_buff_{read,write}() functions
-
-Rename functions to brcmf_sdio_skbuff_{read,write}() as we pass an
-skbuff to this function.
-
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 48 +++++++++++-----------
- 1 file changed, 24 insertions(+), 24 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -292,24 +292,24 @@ out:
- *ret = retval;
- }
-
--static int brcmf_sdiod_buff_read(struct brcmf_sdio_dev *sdiodev,
-- struct sdio_func *func, u32 addr,
-- struct sk_buff *pkt)
-+static int brcmf_sdiod_skbuff_read(struct brcmf_sdio_dev *sdiodev,
-+ struct sdio_func *func, u32 addr,
-+ struct sk_buff *skb)
- {
- unsigned int req_sz;
- int err;
-
- /* Single skb use the standard mmc interface */
-- req_sz = pkt->len + 3;
-+ req_sz = skb->len + 3;
- req_sz &= (uint)~3;
-
- switch (func->num) {
- case 1:
-- err = sdio_memcpy_fromio(func, ((u8 *)(pkt->data)), addr,
-+ err = sdio_memcpy_fromio(func, ((u8 *)(skb->data)), addr,
- req_sz);
- break;
- case 2:
-- err = sdio_readsb(func, ((u8 *)(pkt->data)), addr, req_sz);
-+ err = sdio_readsb(func, ((u8 *)(skb->data)), addr, req_sz);
- break;
- default:
- /* bail out as things are really fishy here */
-@@ -323,18 +323,18 @@ static int brcmf_sdiod_buff_read(struct
- return err;
- }
-
--static int brcmf_sdiod_buff_write(struct brcmf_sdio_dev *sdiodev,
-- struct sdio_func *func, u32 addr,
-- struct sk_buff *pkt)
-+static int brcmf_sdiod_skbuff_write(struct brcmf_sdio_dev *sdiodev,
-+ struct sdio_func *func, u32 addr,
-+ struct sk_buff *skb)
- {
- unsigned int req_sz;
- int err;
-
- /* Single skb use the standard mmc interface */
-- req_sz = pkt->len + 3;
-+ req_sz = skb->len + 3;
- req_sz &= (uint)~3;
-
-- err = sdio_memcpy_toio(func, addr, ((u8 *)(pkt->data)), req_sz);
-+ err = sdio_memcpy_toio(func, addr, ((u8 *)(skb->data)), req_sz);
-
- if (err == -ENOMEDIUM)
- brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_NOMEDIUM);
-@@ -550,7 +550,7 @@ int brcmf_sdiod_recv_pkt(struct brcmf_sd
- addr &= SBSDIO_SB_OFT_ADDR_MASK;
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr, pkt);
-+ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr, pkt);
-
- done:
- return err;
-@@ -575,14 +575,14 @@ int brcmf_sdiod_recv_chain(struct brcmf_
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- if (pktq->qlen == 1)
-- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr,
-- pktq->next);
-+ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr,
-+ pktq->next);
- else if (!sdiodev->sg_support) {
- glom_skb = brcmu_pkt_buf_get_skb(totlen);
- if (!glom_skb)
- return -ENOMEM;
-- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func2, addr,
-- glom_skb);
-+ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func2, addr,
-+ glom_skb);
- if (err)
- goto done;
-
-@@ -623,8 +623,8 @@ int brcmf_sdiod_send_buf(struct brcmf_sd
- addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
- if (!err)
-- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2, addr,
-- mypkt);
-+ err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2, addr,
-+ mypkt);
-
- brcmu_pkt_buf_free_skb(mypkt);
-
-@@ -649,8 +649,8 @@ int brcmf_sdiod_send_pkt(struct brcmf_sd
-
- if (pktq->qlen == 1 || !sdiodev->sg_support) {
- skb_queue_walk(pktq, skb) {
-- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func2,
-- addr, skb);
-+ err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func2,
-+ addr, skb);
- if (err)
- break;
- }
-@@ -706,11 +706,11 @@ brcmf_sdiod_ramrw(struct brcmf_sdio_dev
-
- if (write) {
- memcpy(pkt->data, data, dsize);
-- err = brcmf_sdiod_buff_write(sdiodev, sdiodev->func1,
-- sdaddr, pkt);
-+ err = brcmf_sdiod_skbuff_write(sdiodev, sdiodev->func1,
-+ sdaddr, pkt);
- } else {
-- err = brcmf_sdiod_buff_read(sdiodev, sdiodev->func1,
-- sdaddr, pkt);
-+ err = brcmf_sdiod_skbuff_read(sdiodev, sdiodev->func1,
-+ sdaddr, pkt);
- }
-
- if (err) {
+++ /dev/null
-From b7acadaf038740c43515dc1548f43d01cc92823a Mon Sep 17 00:00:00 2001
-From: Himanshu Jha <himanshujha199640@gmail.com>
-Date: Tue, 9 Jan 2018 02:15:31 +0530
-Subject: [PATCH] brcmfmac: Use zeroing memory allocator than allocator/memset
-
-Use dma_zalloc_coherent for allocating zeroed
-memory and remove unnecessary memset function.
-
-Generated-by: scripts/coccinelle/api/alloc/kzalloc-simple.cocci
-
-Suggested-by: Luis R. Rodriguez <mcgrof@kernel.org>
-Signed-off-by: Himanshu Jha <himanshujha199640@gmail.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 20 ++++++++++----------
- 1 file changed, 10 insertions(+), 10 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -1251,14 +1251,14 @@ static int brcmf_pcie_init_scratchbuffer
- u64 address;
- u32 addr;
-
-- devinfo->shared.scratch = dma_alloc_coherent(&devinfo->pdev->dev,
-- BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
-- &devinfo->shared.scratch_dmahandle, GFP_KERNEL);
-+ devinfo->shared.scratch =
-+ dma_zalloc_coherent(&devinfo->pdev->dev,
-+ BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
-+ &devinfo->shared.scratch_dmahandle,
-+ GFP_KERNEL);
- if (!devinfo->shared.scratch)
- goto fail;
-
-- memset(devinfo->shared.scratch, 0, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
--
- addr = devinfo->shared.tcm_base_address +
- BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
- address = (u64)devinfo->shared.scratch_dmahandle;
-@@ -1268,14 +1268,14 @@ static int brcmf_pcie_init_scratchbuffer
- BRCMF_SHARED_DMA_SCRATCH_LEN_OFFSET;
- brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
-
-- devinfo->shared.ringupd = dma_alloc_coherent(&devinfo->pdev->dev,
-- BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
-- &devinfo->shared.ringupd_dmahandle, GFP_KERNEL);
-+ devinfo->shared.ringupd =
-+ dma_zalloc_coherent(&devinfo->pdev->dev,
-+ BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
-+ &devinfo->shared.ringupd_dmahandle,
-+ GFP_KERNEL);
- if (!devinfo->shared.ringupd)
- goto fail;
-
-- memset(devinfo->shared.ringupd, 0, BRCMF_DMA_D2H_RINGUPD_BUF_LEN);
--
- addr = devinfo->shared.tcm_base_address +
- BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
- address = (u64)devinfo->shared.ringupd_dmahandle;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 9 Feb 2018 19:46:54 +0100
-Subject: [PATCH] mac80211: round IEEE80211_TX_STATUS_HEADROOM up to multiple
- of 4
-
-This ensures that mac80211 allocated management frames are properly
-aligned, which makes copying them more efficient.
-For instance, mt76 uses iowrite32_copy to copy beacon frames to beacon
-template memory on the chip.
-Misaligned 32-bit accesses cause CPU exceptions on MIPS and should be
-avoided.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -4145,7 +4145,7 @@ void ieee80211_sta_uapsd_trigger(struct
- * The TX headroom reserved by mac80211 for its own tx_status functions.
- * This is enough for the radiotap header.
- */
--#define IEEE80211_TX_STATUS_HEADROOM 14
-+#define IEEE80211_TX_STATUS_HEADROOM ALIGN(14, 4)
-
- /**
- * ieee80211_sta_set_buffered - inform mac80211 about driver-buffered frames
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 23 Feb 2018 09:59:35 +0100
-Subject: [PATCH] mac80211: drop frames with unexpected DS bits from
- fast-rx to slow path
-
-Fixes rx for 4-addr packets in AP mode
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -3928,7 +3928,7 @@ static bool ieee80211_invoke_fast_rx(str
- if ((hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FROMDS |
- IEEE80211_FCTL_TODS)) !=
- fast_rx->expected_ds_bits)
-- goto drop;
-+ return false;
-
- /* assign the key to drop unencrypted frames (later)
- * and strip the IV/MIC if necessary
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 23 Feb 2018 10:00:22 +0100
-Subject: [PATCH] mac80211: support AP 4-addr mode fast-rx
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -3774,6 +3774,15 @@ void ieee80211_check_fast_rx(struct sta_
- !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
- (sdata->vif.type != NL80211_IFTYPE_AP_VLAN ||
- !sdata->u.vlan.sta);
-+
-+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
-+ sdata->u.vlan.sta) {
-+ fastrx.expected_ds_bits |=
-+ cpu_to_le16(IEEE80211_FCTL_FROMDS);
-+ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
-+ fastrx.internal_forward = 0;
-+ }
-+
- break;
- default:
- goto clear;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 23 Feb 2018 10:01:53 +0100
-Subject: [PATCH] mac80211: support fast-rx with incompatible PS
- capabilities when PS is disabled
-
-When powersave is disabled for the interface, we can do fast-rx anyway.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -2658,6 +2658,7 @@ static int ieee80211_set_power_mgmt(stru
-
- ieee80211_recalc_ps(local);
- ieee80211_recalc_ps_vif(sdata);
-+ ieee80211_check_fast_rx_iface(sdata);
-
- return 0;
- }
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -3741,12 +3741,7 @@ void ieee80211_check_fast_rx(struct sta_
- /* 4-addr is harder to deal with, later maybe */
- if (sdata->u.mgd.use_4addr)
- goto clear;
-- /* software powersave is a huge mess, avoid all of it */
-- if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK))
-- goto clear;
-- if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) &&
-- !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
-- goto clear;
-+
- if (sta->sta.tdls) {
- fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1);
- fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2);
-@@ -3758,6 +3753,16 @@ void ieee80211_check_fast_rx(struct sta_
- fastrx.expected_ds_bits =
- cpu_to_le16(IEEE80211_FCTL_FROMDS);
- }
-+
-+ if (!sdata->u.mgd.powersave)
-+ break;
-+
-+ /* software powersave is a huge mess, avoid all of it */
-+ if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK))
-+ goto clear;
-+ if (ieee80211_hw_check(&local->hw, SUPPORTS_PS) &&
-+ !ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
-+ goto clear;
- break;
- case NL80211_IFTYPE_AP_VLAN:
- case NL80211_IFTYPE_AP:
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 23 Feb 2018 10:05:08 +0100
-Subject: [PATCH] mac80211: support station 4-addr mode fast-rx
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -3738,10 +3738,6 @@ void ieee80211_check_fast_rx(struct sta_
-
- switch (sdata->vif.type) {
- case NL80211_IFTYPE_STATION:
-- /* 4-addr is harder to deal with, later maybe */
-- if (sdata->u.mgd.use_4addr)
-- goto clear;
--
- if (sta->sta.tdls) {
- fastrx.da_offs = offsetof(struct ieee80211_hdr, addr1);
- fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr2);
-@@ -3754,6 +3750,13 @@ void ieee80211_check_fast_rx(struct sta_
- cpu_to_le16(IEEE80211_FCTL_FROMDS);
- }
-
-+ if (sdata->u.mgd.use_4addr && !sta->sta.tdls) {
-+ fastrx.expected_ds_bits |=
-+ cpu_to_le16(IEEE80211_FCTL_TODS);
-+ fastrx.da_offs = offsetof(struct ieee80211_hdr, addr3);
-+ fastrx.sa_offs = offsetof(struct ieee80211_hdr, addr4);
-+ }
-+
- if (!sdata->u.mgd.powersave)
- break;
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 26 Feb 2018 22:09:29 +0100
-Subject: [PATCH] mac80211: support A-MSDU in fast-rx
-
-Only works if the IV was stripped from packets. Create a smaller
-variant of ieee80211_rx_h_amsdu, which bypasses checks already done
-within the fast-rx context.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rx.c
-+++ b/net/mac80211/rx.c
-@@ -2358,39 +2358,17 @@ ieee80211_deliver_skb(struct ieee80211_r
- }
-
- static ieee80211_rx_result debug_noinline
--ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
-+__ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
- {
- struct net_device *dev = rx->sdata->dev;
- struct sk_buff *skb = rx->skb;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- __le16 fc = hdr->frame_control;
- struct sk_buff_head frame_list;
-- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
- struct ethhdr ethhdr;
- const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
-
-- if (unlikely(!ieee80211_is_data(fc)))
-- return RX_CONTINUE;
--
-- if (unlikely(!ieee80211_is_data_present(fc)))
-- return RX_DROP_MONITOR;
--
-- if (!(status->rx_flags & IEEE80211_RX_AMSDU))
-- return RX_CONTINUE;
--
- if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
-- switch (rx->sdata->vif.type) {
-- case NL80211_IFTYPE_AP_VLAN:
-- if (!rx->sdata->u.vlan.sta)
-- return RX_DROP_UNUSABLE;
-- break;
-- case NL80211_IFTYPE_STATION:
-- if (!rx->sdata->u.mgd.use_4addr)
-- return RX_DROP_UNUSABLE;
-- break;
-- default:
-- return RX_DROP_UNUSABLE;
-- }
- check_da = NULL;
- check_sa = NULL;
- } else switch (rx->sdata->vif.type) {
-@@ -2410,15 +2388,13 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
- break;
- }
-
-- if (is_multicast_ether_addr(hdr->addr1))
-- return RX_DROP_UNUSABLE;
--
- skb->dev = dev;
- __skb_queue_head_init(&frame_list);
-
- if (ieee80211_data_to_8023_exthdr(skb, ðhdr,
- rx->sdata->vif.addr,
-- rx->sdata->vif.type))
-+ rx->sdata->vif.type,
-+ data_offset))
- return RX_DROP_UNUSABLE;
-
- ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
-@@ -2440,6 +2416,44 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
- return RX_QUEUED;
- }
-
-+static ieee80211_rx_result debug_noinline
-+ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
-+{
-+ struct sk_buff *skb = rx->skb;
-+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-+ __le16 fc = hdr->frame_control;
-+
-+ if (!(status->rx_flags & IEEE80211_RX_AMSDU))
-+ return RX_CONTINUE;
-+
-+ if (unlikely(!ieee80211_is_data(fc)))
-+ return RX_CONTINUE;
-+
-+ if (unlikely(!ieee80211_is_data_present(fc)))
-+ return RX_DROP_MONITOR;
-+
-+ if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
-+ switch (rx->sdata->vif.type) {
-+ case NL80211_IFTYPE_AP_VLAN:
-+ if (!rx->sdata->u.vlan.sta)
-+ return RX_DROP_UNUSABLE;
-+ break;
-+ case NL80211_IFTYPE_STATION:
-+ if (!rx->sdata->u.mgd.use_4addr)
-+ return RX_DROP_UNUSABLE;
-+ break;
-+ default:
-+ return RX_DROP_UNUSABLE;
-+ }
-+ }
-+
-+ if (is_multicast_ether_addr(hdr->addr1))
-+ return RX_DROP_UNUSABLE;
-+
-+ return __ieee80211_rx_h_amsdu(rx, 0);
-+}
-+
- #ifdef CPTCFG_MAC80211_MESH
- static ieee80211_rx_result
- ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
-@@ -3889,7 +3903,8 @@ static bool ieee80211_invoke_fast_rx(str
- struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
- struct sta_info *sta = rx->sta;
- int orig_len = skb->len;
-- int snap_offs = ieee80211_hdrlen(hdr->frame_control);
-+ int hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ int snap_offs = hdrlen;
- struct {
- u8 snap[sizeof(rfc1042_header)];
- __be16 proto;
-@@ -3920,10 +3935,6 @@ static bool ieee80211_invoke_fast_rx(str
- (status->flag & FAST_RX_CRYPT_FLAGS) != FAST_RX_CRYPT_FLAGS)
- return false;
-
-- /* we don't deal with A-MSDU deaggregation here */
-- if (status->rx_flags & IEEE80211_RX_AMSDU)
-- return false;
--
- if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
- return false;
-
-@@ -3955,21 +3966,24 @@ static bool ieee80211_invoke_fast_rx(str
- snap_offs += IEEE80211_CCMP_HDR_LEN;
- }
-
-- if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
-- goto drop;
-- payload = (void *)(skb->data + snap_offs);
-+ if (!(status->rx_flags & IEEE80211_RX_AMSDU)) {
-+ if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
-+ goto drop;
-
-- if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr))
-- return false;
-+ payload = (void *)(skb->data + snap_offs);
-
-- /* Don't handle these here since they require special code.
-- * Accept AARP and IPX even though they should come with a
-- * bridge-tunnel header - but if we get them this way then
-- * there's little point in discarding them.
-- */
-- if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) ||
-- payload->proto == fast_rx->control_port_protocol))
-- return false;
-+ if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr))
-+ return false;
-+
-+ /* Don't handle these here since they require special code.
-+ * Accept AARP and IPX even though they should come with a
-+ * bridge-tunnel header - but if we get them this way then
-+ * there's little point in discarding them.
-+ */
-+ if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) ||
-+ payload->proto == fast_rx->control_port_protocol))
-+ return false;
-+ }
-
- /* after this point, don't punt to the slowpath! */
-
-@@ -3983,12 +3997,6 @@ static bool ieee80211_invoke_fast_rx(str
- }
-
- /* statistics part of ieee80211_rx_h_sta_process() */
-- stats->last_rx = jiffies;
-- stats->last_rate = sta_stats_encode_rate(status);
--
-- stats->fragments++;
-- stats->packets++;
--
- if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
- stats->last_signal = status->signal;
- if (!fast_rx->uses_rss)
-@@ -4017,6 +4025,20 @@ static bool ieee80211_invoke_fast_rx(str
- if (rx->key && !ieee80211_has_protected(hdr->frame_control))
- goto drop;
-
-+ if (status->rx_flags & IEEE80211_RX_AMSDU) {
-+ if (__ieee80211_rx_h_amsdu(rx, snap_offs - hdrlen) !=
-+ RX_QUEUED)
-+ goto drop;
-+
-+ return true;
-+ }
-+
-+ stats->last_rx = jiffies;
-+ stats->last_rate = sta_stats_encode_rate(status);
-+
-+ stats->fragments++;
-+ stats->packets++;
-+
- /* do the header conversion - first grab the addresses */
- ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs);
- ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs);
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -4331,10 +4331,12 @@ unsigned int ieee80211_get_mesh_hdrlen(s
- * of it being pushed into the SKB
- * @addr: the device MAC address
- * @iftype: the virtual interface type
-+ * @data_offset: offset of payload after the 802.11 header
- * Return: 0 on success. Non-zero on error.
- */
- int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
-- const u8 *addr, enum nl80211_iftype iftype);
-+ const u8 *addr, enum nl80211_iftype iftype,
-+ u8 data_offset);
-
- /**
- * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
-@@ -4346,7 +4348,7 @@ int ieee80211_data_to_8023_exthdr(struct
- static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
- enum nl80211_iftype iftype)
- {
-- return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype);
-+ return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0);
- }
-
- /**
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -419,7 +419,8 @@ unsigned int ieee80211_get_mesh_hdrlen(s
- EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
-
- int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
-- const u8 *addr, enum nl80211_iftype iftype)
-+ const u8 *addr, enum nl80211_iftype iftype,
-+ u8 data_offset)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct {
-@@ -433,7 +434,7 @@ int ieee80211_data_to_8023_exthdr(struct
- if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
- return -1;
-
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ hdrlen = ieee80211_hdrlen(hdr->frame_control) + data_offset;
- if (skb->len < hdrlen + 8)
- return -1;
-
+++ /dev/null
-From 5242a5444e0b6464d7455beb55d936dd192b5e9d Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Mon, 22 Jan 2018 21:46:39 +0100
-Subject: [PATCH] brcmfmac: assure bcdc dcmd api does not return value > 0
-
-The protocol layer api defines callbacks for dongle commands.
-Although not really well documented these should only return an
-error code in case of an error, or 0 upon success. In the bcdc
-protocol it can return value above 0 and we carry a fix in the
-caller of the protocol layer api. This patch makes it adhere to
-the intent of the api as described above.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 6 +++++-
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 8 +++-----
- 2 files changed, 8 insertions(+), 6 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
-@@ -211,6 +211,8 @@ retry:
- memcpy(buf, info, len);
- }
-
-+ ret = 0;
-+
- /* Check the ERROR flag */
- if (flags & BCDC_DCMD_ERROR)
- ret = le32_to_cpu(msg->status);
-@@ -225,7 +227,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
- {
- struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
- struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
-- int ret = 0;
-+ int ret;
- u32 flags, id;
-
- brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
-@@ -249,6 +251,8 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
- goto done;
- }
-
-+ ret = 0;
-+
- /* Check the ERROR flag */
- if (flags & BCDC_DCMD_ERROR)
- ret = le32_to_cpu(msg->status);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
-@@ -121,11 +121,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
- else
- err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
-
-- if (err >= 0)
-- return 0;
--
-- brcmf_dbg(FIL, "Failed: %s (%d)\n",
-- brcmf_fil_get_errstr((u32)(-err)), err);
-+ if (err)
-+ brcmf_dbg(FIL, "Failed: %s (%d)\n",
-+ brcmf_fil_get_errstr((u32)(-err)), err);
-
- return err;
- }
+++ /dev/null
-From b69c1df47281ad47bd2037a42b98f5c7115b7fd5 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Mon, 22 Jan 2018 21:46:40 +0100
-Subject: [PATCH] brcmfmac: separate firmware errors from i/o errors
-
-When using the firmware api it can fail simply because firmware does
-not like the request or it fails due to issues in the host interface.
-Currently, there is only a single error code which is confusing. So
-adding a parameter to pass the firmware error separately and in case
-of a firmware error always return -EBADE to user-space.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 11 ++++++-----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 16 +++++++++++-----
- .../net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 10 ++++++----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h | 14 ++++++++------
- 4 files changed, 31 insertions(+), 20 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
-@@ -165,7 +165,7 @@ static int brcmf_proto_bcdc_cmplt(struct
-
- static int
- brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
-- void *buf, uint len)
-+ void *buf, uint len, int *fwerr)
- {
- struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
- struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
-@@ -175,6 +175,7 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf
-
- brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
-
-+ *fwerr = 0;
- ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
- if (ret < 0) {
- brcmf_err("brcmf_proto_bcdc_msg failed w/status %d\n",
-@@ -215,15 +216,14 @@ retry:
-
- /* Check the ERROR flag */
- if (flags & BCDC_DCMD_ERROR)
-- ret = le32_to_cpu(msg->status);
--
-+ *fwerr = le32_to_cpu(msg->status);
- done:
- return ret;
- }
-
- static int
- brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
-- void *buf, uint len)
-+ void *buf, uint len, int *fwerr)
- {
- struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
- struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
-@@ -232,6 +232,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
-
- brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
-
-+ *fwerr = 0;
- ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true);
- if (ret < 0)
- goto done;
-@@ -255,7 +256,7 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_p
-
- /* Check the ERROR flag */
- if (flags & BCDC_DCMD_ERROR)
-- ret = le32_to_cpu(msg->status);
-+ *fwerr = le32_to_cpu(msg->status);
-
- done:
- return ret;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
-@@ -107,7 +107,7 @@ static s32
- brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
- {
- struct brcmf_pub *drvr = ifp->drvr;
-- s32 err;
-+ s32 err, fwerr;
-
- if (drvr->bus_if->state != BRCMF_BUS_UP) {
- brcmf_err("bus is down. we have nothing to do.\n");
-@@ -117,14 +117,20 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
- if (data != NULL)
- len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
- if (set)
-- err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd, data, len);
-+ err = brcmf_proto_set_dcmd(drvr, ifp->ifidx, cmd,
-+ data, len, &fwerr);
- else
-- err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
-+ err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd,
-+ data, len, &fwerr);
-
-- if (err)
-+ if (err) {
- brcmf_dbg(FIL, "Failed: %s (%d)\n",
- brcmf_fil_get_errstr((u32)(-err)), err);
--
-+ } else if (fwerr < 0) {
-+ brcmf_dbg(FIL, "Firmware error: %s (%d)\n",
-+ brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
-+ err = -EBADE;
-+ }
- return err;
- }
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-@@ -477,7 +477,7 @@ static void brcmf_msgbuf_ioctl_resp_wake
-
-
- static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,
-- uint cmd, void *buf, uint len)
-+ uint cmd, void *buf, uint len, int *fwerr)
- {
- struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
- struct sk_buff *skb = NULL;
-@@ -485,6 +485,7 @@ static int brcmf_msgbuf_query_dcmd(struc
- int err;
-
- brcmf_dbg(MSGBUF, "ifidx=%d, cmd=%d, len=%d\n", ifidx, cmd, len);
-+ *fwerr = 0;
- msgbuf->ctl_completed = false;
- err = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len);
- if (err)
-@@ -508,14 +509,15 @@ static int brcmf_msgbuf_query_dcmd(struc
- }
- brcmu_pkt_buf_free_skb(skb);
-
-- return msgbuf->ioctl_resp_status;
-+ *fwerr = msgbuf->ioctl_resp_status;
-+ return 0;
- }
-
-
- static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx,
-- uint cmd, void *buf, uint len)
-+ uint cmd, void *buf, uint len, int *fwerr)
- {
-- return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len);
-+ return brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
- }
-
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
-@@ -30,9 +30,9 @@ struct brcmf_proto {
- 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);
-+ void *buf, uint len, int *fwerr);
- int (*set_dcmd)(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
-- uint len);
-+ uint len, int *fwerr);
- int (*tx_queue_data)(struct brcmf_pub *drvr, int ifidx,
- struct sk_buff *skb);
- int (*txdata)(struct brcmf_pub *drvr, int ifidx, u8 offset,
-@@ -71,14 +71,16 @@ static inline int brcmf_proto_hdrpull(st
- 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)
-+ uint cmd, void *buf, uint len,
-+ int *fwerr)
- {
-- return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len);
-+ return drvr->proto->query_dcmd(drvr, ifidx, cmd, buf, len,fwerr);
- }
- static inline int brcmf_proto_set_dcmd(struct brcmf_pub *drvr, int ifidx,
-- uint cmd, void *buf, uint len)
-+ uint cmd, void *buf, uint len,
-+ int *fwerr)
- {
-- return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len);
-+ return drvr->proto->set_dcmd(drvr, ifidx, cmd, buf, len, fwerr);
- }
-
- static inline int brcmf_proto_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
+++ /dev/null
-From 933897342d0714ae1c10729cbaeecea0c6178db5 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 28 Feb 2018 21:15:19 +0100
-Subject: [PATCH] brcmfmac: add possibility to obtain firmware error
-
-The feature module needs to evaluate the actual firmware error return
-upon a control command. This adds a flag to struct brcmf_if that the
-caller can set. This flag is checked to determine the error code that
-needs to be returned.
-
-Fixes: b69c1df47281 ("brcmfmac: separate firmware errors from i/o errors")
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h | 2 ++
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 10 ++++++++++
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 3 +++
- 3 files changed, 15 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-@@ -181,6 +181,7 @@ enum brcmf_netif_stop_reason {
- * @netif_stop_lock: spinlock for update netif_stop from multiple sources.
- * @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
- * @pend_8021x_wait: used for signalling change in count.
-+ * @fwil_fwerr: flag indicating fwil layer should return firmware error codes.
- */
- struct brcmf_if {
- struct brcmf_pub *drvr;
-@@ -198,6 +199,7 @@ struct brcmf_if {
- wait_queue_head_t pend_8021x_wait;
- struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES];
- u8 ipv6addr_idx;
-+ bool fwil_fwerr;
- };
-
- int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-@@ -104,6 +104,9 @@ static void brcmf_feat_iovar_int_get(str
- u32 data;
- int err;
-
-+ /* we need to know firmware error */
-+ ifp->fwil_fwerr = true;
-+
- err = brcmf_fil_iovar_int_get(ifp, name, &data);
- if (err == 0) {
- brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
-@@ -112,6 +115,8 @@ static void brcmf_feat_iovar_int_get(str
- brcmf_dbg(TRACE, "%s feature check failed: %d\n",
- brcmf_feat_names[id], err);
- }
-+
-+ ifp->fwil_fwerr = false;
- }
-
- static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
-@@ -120,6 +125,9 @@ static void brcmf_feat_iovar_data_set(st
- {
- int err;
-
-+ /* we need to know firmware error */
-+ ifp->fwil_fwerr = true;
-+
- err = brcmf_fil_iovar_data_set(ifp, name, data, len);
- if (err != -BRCMF_FW_UNSUPPORTED) {
- brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
-@@ -128,6 +136,8 @@ static void brcmf_feat_iovar_data_set(st
- brcmf_dbg(TRACE, "%s feature check failed: %d\n",
- brcmf_feat_names[id], err);
- }
-+
-+ ifp->fwil_fwerr = false;
- }
-
- #define MAX_CAPS_BUFFER_SIZE 512
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
-@@ -131,6 +131,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
- brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
- err = -EBADE;
- }
-+ if (ifp->fwil_fwerr)
-+ return fwerr;
-+
- return err;
- }
-
+++ /dev/null
-From 455f3e76cfc0d893585a5f358b9ddbe9c1e1e53b Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 28 Feb 2018 21:15:20 +0100
-Subject: [PATCH] brcmfmac: fix P2P_DEVICE ethernet address generation
-
-The firmware has a requirement that the P2P_DEVICE address should
-be different from the address of the primary interface. When not
-specified by user-space, the driver generates the MAC address for
-the P2P_DEVICE interface using the MAC address of the primary
-interface and setting the locally administered bit. However, the MAC
-address of the primary interface may already have that bit set causing
-the creation of the P2P_DEVICE interface to fail with -EBUSY. Fix this
-by using a random address instead to determine the P2P_DEVICE address.
-
-Cc: stable@vger.kernel.org # 3.10.y
-Reported-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 24 ++++++++++------------
- 1 file changed, 11 insertions(+), 13 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-@@ -462,25 +462,23 @@ static int brcmf_p2p_set_firmware(struct
- * @dev_addr: optional device address.
- *
- * P2P needs mac addresses for P2P device and interface. If no device
-- * address it specified, these are derived from the primary net device, ie.
-- * the permanent ethernet address of the device.
-+ * address it specified, these are derived from a random ethernet
-+ * address.
- */
- static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
- {
-- struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
-- bool local_admin = false;
-+ bool random_addr = false;
-
-- if (!dev_addr || is_zero_ether_addr(dev_addr)) {
-- dev_addr = pri_ifp->mac_addr;
-- local_admin = true;
-- }
-+ if (!dev_addr || is_zero_ether_addr(dev_addr))
-+ random_addr = true;
-
-- /* Generate the P2P Device Address. This consists of the device's
-- * primary MAC address with the locally administered bit set.
-+ /* Generate the P2P Device Address obtaining a random ethernet
-+ * address with the locally administered bit set.
- */
-- memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
-- if (local_admin)
-- p2p->dev_addr[0] |= 0x02;
-+ if (random_addr)
-+ eth_random_addr(p2p->dev_addr);
-+ else
-+ memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
-
- /* Generate the P2P Interface Address. If the discovery and connection
- * BSSCFGs need to simultaneously co-exist, then this address must be
+++ /dev/null
-From 1259055170287a350cad453e9eac139c81609860 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 15 Mar 2018 08:29:09 +0100
-Subject: [PATCH] brcmfmac: drop Inter-Access Point Protocol packets by default
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Testing brcmfmac with more recent firmwares resulted in AP interfaces
-not working in some specific setups. Debugging resulted in discovering
-support for IAPP in Broadcom's firmwares.
-
-Older firmwares were only generating 802.11f frames. Newer ones like:
-1) 10.10 (TOB) (r663589)
-2) 10.10.122.20 (r683106)
-for 4366b1 and 4366c0 respectively seem to also /respect/ 802.11f frames
-in the Tx path by performing a STA disassociation.
-
-This obsoleted standard and its implementation is something that:
-1) Most people don't need / want to use
-2) Can allow local DoS attacks
-3) Breaks AP interfaces in some specific bridge setups
-
-To solve issues it can cause this commit modifies brcmfmac to drop IAPP
-packets. If affects:
-1) Rx path: driver won't be sending these unwanted packets up.
-2) Tx path: driver will reject packets that would trigger STA
- disassociation perfromed by a firmware (possible local DoS attack).
-
-It appears there are some Broadcom's clients/users who care about this
-feature despite the drawbacks. They can switch it on using a new module
-param.
-
-This change results in only two more comparisons (check for module param
-and check for Ethernet packet length) for 99.9% of packets. Its overhead
-should be very minimal.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/common.c | 5 ++
- .../wireless/broadcom/brcm80211/brcmfmac/common.h | 1 +
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 57 ++++++++++++++++++++++
- 3 files changed, 63 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -75,6 +75,10 @@ static int brcmf_roamoff;
- module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
- MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
-
-+static int brcmf_iapp_enable;
-+module_param_named(iapp, brcmf_iapp_enable, int, 0);
-+MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol");
-+
- #ifdef DEBUG
- /* always succeed brcmf_bus_started() */
- static int brcmf_ignore_probe_fail;
-@@ -441,6 +445,7 @@ struct brcmf_mp_device *brcmf_get_module
- settings->feature_disable = brcmf_feature_disable;
- settings->fcmode = brcmf_fcmode;
- settings->roamoff = !!brcmf_roamoff;
-+ settings->iapp = !!brcmf_iapp_enable;
- #ifdef DEBUG
- settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
- #endif
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
-@@ -58,6 +58,7 @@ struct brcmf_mp_device {
- unsigned int feature_disable;
- int fcmode;
- bool roamoff;
-+ bool iapp;
- bool ignore_probe_fail;
- struct brcmfmac_pd_cc *country_codes;
- union {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -230,6 +230,37 @@ static void brcmf_netdev_set_multicast_l
- schedule_work(&ifp->multicast_work);
- }
-
-+/**
-+ * brcmf_skb_is_iapp - checks if skb is an IAPP packet
-+ *
-+ * @skb: skb to check
-+ */
-+static bool brcmf_skb_is_iapp(struct sk_buff *skb)
-+{
-+ static const u8 iapp_l2_update_packet[6] __aligned(2) = {
-+ 0x00, 0x01, 0xaf, 0x81, 0x01, 0x00,
-+ };
-+ unsigned char *eth_data;
-+#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
-+ const u16 *a, *b;
-+#endif
-+
-+ if (skb->len - skb->mac_len != 6 ||
-+ !is_multicast_ether_addr(eth_hdr(skb)->h_dest))
-+ return false;
-+
-+ eth_data = skb_mac_header(skb) + ETH_HLEN;
-+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
-+ return !(((*(const u32 *)eth_data) ^ (*(const u32 *)iapp_l2_update_packet)) |
-+ ((*(const u16 *)(eth_data + 4)) ^ (*(const u16 *)(iapp_l2_update_packet + 4))));
-+#else
-+ a = (const u16 *)eth_data;
-+ b = (const u16 *)iapp_l2_update_packet;
-+
-+ return !((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]));
-+#endif
-+}
-+
- static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
- struct net_device *ndev)
- {
-@@ -250,6 +281,23 @@ static netdev_tx_t brcmf_netdev_start_xm
- goto done;
- }
-
-+ /* Some recent Broadcom's firmwares disassociate STA when they receive
-+ * an 802.11f ADD frame. This behavior can lead to a local DoS security
-+ * issue. Attacker may trigger disassociation of any STA by sending a
-+ * proper Ethernet frame to the wireless interface.
-+ *
-+ * Moreover this feature may break AP interfaces in some specific
-+ * setups. This applies e.g. to the bridge with hairpin mode enabled and
-+ * IFLA_BRPORT_MCAST_TO_UCAST set. IAPP packet generated by a firmware
-+ * will get passed back to the wireless interface and cause immediate
-+ * disassociation of a just-connected STA.
-+ */
-+ if (!drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
-+ dev_kfree_skb(skb);
-+ ret = -EINVAL;
-+ goto done;
-+ }
-+
- /* Make sure there's enough writeable headroom */
- if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) {
- head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0);
-@@ -325,6 +373,15 @@ void brcmf_txflowblock_if(struct brcmf_i
-
- void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
- {
-+ /* Most of Broadcom's firmwares send 802.11f ADD frame every time a new
-+ * STA connects to the AP interface. This is an obsoleted standard most
-+ * users don't use, so don't pass these frames up unless requested.
-+ */
-+ if (!ifp->drvr->settings->iapp && brcmf_skb_is_iapp(skb)) {
-+ brcmu_pkt_buf_free_skb(skb);
-+ return;
-+ }
-+
- if (skb->pkt_type == PACKET_MULTICAST)
- ifp->ndev->stats.multicast++;
-
+++ /dev/null
-From 9b9322db5c5a1917a66c71fe47c3848a9a31227e Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Wed, 14 Mar 2018 20:02:59 +0100
-Subject: [PATCH] brcmfmac: Fix check for ISO3166 code
-
-The commit "regulatory: add NUL to request alpha2" increases the length of
-alpha2 to 3. This causes a regression on brcmfmac, because
-brcmf_cfg80211_reg_notifier() expect valid ISO3166 codes in the complete
-array. So fix this accordingly.
-
-Fixes: 657308f73e67 ("regulatory: add NUL to request alpha2")
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Acked-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -6803,7 +6803,7 @@ static void brcmf_cfg80211_reg_notifier(
- return;
-
- /* ignore non-ISO3166 country codes */
-- for (i = 0; i < sizeof(req->alpha2); i++)
-+ for (i = 0; i < 2; i++)
- if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
- brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n",
- req->alpha2[0], req->alpha2[1]);
+++ /dev/null
-From da472385a29f1fddcac7cfa0499482704310bd16 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 20 Feb 2018 00:14:18 +0100
-Subject: [PATCH] brcmfmac: move brcmf_bus_preinit() call just after changing
- bus state
-
-Moving the brcmf_bus_preinit() call allows the bus code to do some
-required initialization before handling firmware control messages.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 3 ---
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 5 +++++
- 2 files changed, 5 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -369,9 +369,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
-
- /* Enable tx beamforming, errors can be ignored (not supported) */
- (void)brcmf_fil_iovar_int_set(ifp, "txbf", 1);
--
-- /* do bus specific preinit here */
-- err = brcmf_bus_preinit(ifp->drvr->bus_if);
- done:
- return err;
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1091,6 +1091,11 @@ int brcmf_bus_started(struct device *dev
- /* signal bus ready */
- brcmf_bus_change_state(bus_if, BRCMF_BUS_UP);
-
-+ /* do bus specific preinit here */
-+ ret = brcmf_bus_preinit(ifp->drvr->bus_if);
-+ if (ret < 0)
-+ goto fail;
-+
- /* Bus is ready, do any initialization */
- ret = brcmf_c_preinit_dcmds(ifp);
- if (ret < 0)
+++ /dev/null
-From 4b5adc736828dc25ca33e263ad8c0b9dcd3bf325 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 20 Feb 2018 00:14:19 +0100
-Subject: [PATCH] brcmfmac: move allocation of control rx buffer to
- brcmf_sdio_bus_preinit()
-
-Allocate the control rx buffer needed for firmware control interface
-during brcmf_sdio_bus_preinit(). This relies on common layer setting
-struct brcmf_bus::maxctl during brcmf_attach(). By moving the allocation
-we can move brcmf_attach() in subsequent change.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 26 ++++++++++------------
- 1 file changed, 12 insertions(+), 14 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -1707,7 +1707,6 @@ brcmf_sdio_read_control(struct brcmf_sdi
- int sdret;
-
- brcmf_dbg(TRACE, "Enter\n");
--
- if (bus->rxblen)
- buf = vzalloc(bus->rxblen);
- if (!buf)
-@@ -3411,6 +3410,18 @@ static int brcmf_sdio_bus_preinit(struct
- u32 value;
- int err;
-
-+ /* maxctl provided by common layer */
-+ if (WARN_ON(!bus_if->maxctl))
-+ return -EINVAL;
-+
-+ /* Allocate control receive buffer */
-+ bus_if->maxctl += bus->roundup;
-+ value = roundup((bus_if->maxctl + SDPCM_HDRLEN), ALIGNMENT);
-+ value += bus->head_align;
-+ bus->rxbuf = kmalloc(value, GFP_ATOMIC);
-+ if (bus->rxbuf)
-+ bus->rxblen = value;
-+
- /* the commands below use the terms tx and rx from
- * a device perspective, ie. bus:txglom affects the
- * bus transfers from device to host.
-@@ -4209,19 +4220,6 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- bus->blocksize = bus->sdiodev->func2->cur_blksize;
- bus->roundup = min(max_roundup, bus->blocksize);
-
-- /* Allocate buffers */
-- if (bus->sdiodev->bus_if->maxctl) {
-- bus->sdiodev->bus_if->maxctl += bus->roundup;
-- bus->rxblen =
-- roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN),
-- ALIGNMENT) + bus->head_align;
-- bus->rxbuf = kmalloc(bus->rxblen, GFP_ATOMIC);
-- if (!(bus->rxbuf)) {
-- brcmf_err("rxbuf allocation failed\n");
-- goto fail;
-- }
-- }
--
- sdio_claim_host(bus->sdiodev->func1);
-
- /* Disable F2 to clear any intermediate frame state on the dongle */
+++ /dev/null
-From 262f2b53f67936b59cc8dfc6f3899ab8905bf1ed Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 20 Feb 2018 00:14:20 +0100
-Subject: [PATCH] brcmfmac: call brcmf_attach() just before calling
- brcmf_bus_started()
-
-Now we can move brcmf_attach() until after the firmware has been downloaded
-to the device. Make the call just before brcmf_bus_started().
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 6 ++++
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 34 +++++++++++-----------
- 2 files changed, 23 insertions(+), 17 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1268,6 +1268,12 @@ void brcmf_bus_change_state(struct brcmf
- int ifidx;
-
- brcmf_dbg(TRACE, "%d -> %d\n", bus->state, state);
-+
-+ if (!drvr) {
-+ brcmf_dbg(INFO, "ignoring transition, bus not attached yet\n");
-+ return;
-+ }
-+
- bus->state = state;
-
- if (state == BRCMF_BUS_UP) {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -4048,9 +4048,6 @@ static void brcmf_sdio_firmware_callback
- if (err)
- goto fail;
-
-- if (!bus_if->drvr)
-- return;
--
- /* try to download image and nvram to the dongle */
- bus->alp_only = true;
- err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
-@@ -4126,11 +4123,28 @@ static void brcmf_sdio_firmware_callback
-
- sdio_release_host(sdiodev->func1);
-
-+ /* Assign bus interface call back */
-+ sdiodev->bus_if->dev = sdiodev->dev;
-+ sdiodev->bus_if->ops = &brcmf_sdio_bus_ops;
-+ sdiodev->bus_if->chip = bus->ci->chip;
-+ sdiodev->bus_if->chiprev = bus->ci->chiprev;
-+
-+ /* Attach to the common layer, reserve hdr space */
-+ err = brcmf_attach(sdiodev->dev, sdiodev->settings);
-+ if (err != 0) {
-+ brcmf_err("brcmf_attach failed\n");
-+ goto fail;
-+ }
-+
-+ brcmf_sdio_debugfs_create(bus);
-+
- err = brcmf_bus_started(dev);
- if (err != 0) {
- brcmf_err("dongle is not responding\n");
- goto fail;
- }
-+
-+ /* ready */
- return;
-
- release:
-@@ -4200,22 +4214,9 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- bus->dpc_triggered = false;
- bus->dpc_running = false;
-
-- /* Assign bus interface call back */
-- bus->sdiodev->bus_if->dev = bus->sdiodev->dev;
-- bus->sdiodev->bus_if->ops = &brcmf_sdio_bus_ops;
-- bus->sdiodev->bus_if->chip = bus->ci->chip;
-- bus->sdiodev->bus_if->chiprev = bus->ci->chiprev;
--
- /* default sdio bus header length for tx packet */
- bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN;
-
-- /* Attach to the common layer, reserve hdr space */
-- ret = brcmf_attach(bus->sdiodev->dev, bus->sdiodev->settings);
-- if (ret != 0) {
-- brcmf_err("brcmf_attach failed\n");
-- goto fail;
-- }
--
- /* Query the F2 block size, set roundup accordingly */
- bus->blocksize = bus->sdiodev->func2->cur_blksize;
- bus->roundup = min(max_roundup, bus->blocksize);
-@@ -4240,7 +4241,6 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- /* SR state */
- bus->sr_enabled = false;
-
-- brcmf_sdio_debugfs_create(bus);
- brcmf_dbg(INFO, "completed!!\n");
-
- ret = brcmf_fw_map_chip_to_name(bus->ci->chip, bus->ci->chiprev,
+++ /dev/null
-From a7f4a80c0070b673d4a4ce94b99979ea6d0c6296 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 20 Feb 2018 00:14:21 +0100
-Subject: [PATCH] brcmfmac: usb: call brcmf_usb_up() during brcmf_bus_preinit()
-
-By calling brcmf_usb_up() during brcmf_bus_preinit() it does not need
-to be called in brcmf_usb_bus_setup().
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 7 ++-----
- 1 file changed, 2 insertions(+), 5 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -1146,8 +1146,9 @@ static int brcmf_usb_get_fwname(struct d
- }
-
- static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
-- .txdata = brcmf_usb_tx,
-+ .preinit = brcmf_usb_up,
- .stop = brcmf_usb_down,
-+ .txdata = brcmf_usb_tx,
- .txctl = brcmf_usb_tx_ctlpkt,
- .rxctl = brcmf_usb_rx_ctlpkt,
- .wowl_config = brcmf_usb_wowl_config,
-@@ -1165,10 +1166,6 @@ static int brcmf_usb_bus_setup(struct br
- return ret;
- }
-
-- ret = brcmf_usb_up(devinfo->dev);
-- if (ret)
-- goto fail;
--
- ret = brcmf_bus_started(devinfo->dev);
- if (ret)
- goto fail;
+++ /dev/null
-From 0542503c4c164c65cd1567b0f2b3f887af6c81eb Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 20 Feb 2018 00:14:22 +0100
-Subject: [PATCH] brcmfmac: move brcmf_attach() function in core.c
-
-Moving the function in preparation of subsequent patch.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 98 +++++++++++-----------
- 1 file changed, 49 insertions(+), 49 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -992,55 +992,6 @@ static int brcmf_inet6addr_changed(struc
- }
- #endif
-
--int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
--{
-- struct brcmf_pub *drvr = NULL;
-- int ret = 0;
-- int i;
--
-- brcmf_dbg(TRACE, "Enter\n");
--
-- /* Allocate primary brcmf_info */
-- drvr = kzalloc(sizeof(struct brcmf_pub), GFP_ATOMIC);
-- if (!drvr)
-- return -ENOMEM;
--
-- for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
-- drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
--
-- mutex_init(&drvr->proto_block);
--
-- /* Link to bus module */
-- drvr->hdrlen = 0;
-- drvr->bus_if = dev_get_drvdata(dev);
-- drvr->bus_if->drvr = drvr;
-- drvr->settings = settings;
--
-- /* attach debug facilities */
-- brcmf_debug_attach(drvr);
--
-- /* Attach and link in the protocol */
-- ret = brcmf_proto_attach(drvr);
-- if (ret != 0) {
-- brcmf_err("brcmf_prot_attach failed\n");
-- goto fail;
-- }
--
-- /* Attach to events important for core code */
-- brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG,
-- brcmf_psm_watchdog_notify);
--
-- /* attach firmware event handler */
-- brcmf_fweh_attach(drvr);
--
-- return ret;
--
--fail:
-- brcmf_detach(dev);
--
-- return ret;
--}
--
- static int brcmf_revinfo_read(struct seq_file *s, void *data)
- {
- struct brcmf_bus *bus_if = dev_get_drvdata(s->private);
-@@ -1170,6 +1121,55 @@ fail:
-
- return ret;
- }
-+
-+int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
-+{
-+ struct brcmf_pub *drvr = NULL;
-+ int ret = 0;
-+ int i;
-+
-+ brcmf_dbg(TRACE, "Enter\n");
-+
-+ /* Allocate primary brcmf_info */
-+ drvr = kzalloc(sizeof(*drvr), GFP_ATOMIC);
-+ if (!drvr)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
-+ drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
-+
-+ mutex_init(&drvr->proto_block);
-+
-+ /* Link to bus module */
-+ drvr->hdrlen = 0;
-+ drvr->bus_if = dev_get_drvdata(dev);
-+ drvr->bus_if->drvr = drvr;
-+ drvr->settings = settings;
-+
-+ /* attach debug facilities */
-+ brcmf_debug_attach(drvr);
-+
-+ /* Attach and link in the protocol */
-+ ret = brcmf_proto_attach(drvr);
-+ if (ret != 0) {
-+ brcmf_err("brcmf_prot_attach failed\n");
-+ goto fail;
-+ }
-+
-+ /* Attach to events important for core code */
-+ brcmf_fweh_register(drvr, BRCMF_E_PSM_WATCHDOG,
-+ brcmf_psm_watchdog_notify);
-+
-+ /* attach firmware event handler */
-+ brcmf_fweh_attach(drvr);
-+
-+ return ret;
-+
-+fail:
-+ brcmf_detach(dev);
-+
-+ return ret;
-+}
-
- void brcmf_bus_add_txhdrlen(struct device *dev, uint len)
- {
+++ /dev/null
-From de2a3027f6f15e2f6558dc4d178282ccc1f054db Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 20 Feb 2018 00:14:23 +0100
-Subject: [PATCH] brcmfmac: remove brcmf_bus_started() from bus api
-
-No longer needed to call this in bus layer so make it static and call
-it in the last phase of brcmf_attach() instead.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 1 -
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 14 +++++++----
- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 20 +---------------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 10 ++------
- .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 28 ++++------------------
- 5 files changed, 16 insertions(+), 57 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-@@ -253,7 +253,6 @@ void brcmf_dev_reset(struct device *dev)
- /* Configure the "global" bus state used by upper layers */
- void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state);
-
--int brcmf_bus_started(struct device *dev);
- s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len);
- void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1022,11 +1022,10 @@ static int brcmf_revinfo_read(struct seq
- return 0;
- }
-
--int brcmf_bus_started(struct device *dev)
-+static int brcmf_bus_started(struct brcmf_pub *drvr)
- {
- int ret = -1;
-- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-- struct brcmf_pub *drvr = bus_if->drvr;
-+ struct brcmf_bus *bus_if = drvr->bus_if;
- struct brcmf_if *ifp;
- struct brcmf_if *p2p_ifp;
-
-@@ -1043,7 +1042,7 @@ int brcmf_bus_started(struct device *dev
- brcmf_bus_change_state(bus_if, BRCMF_BUS_UP);
-
- /* do bus specific preinit here */
-- ret = brcmf_bus_preinit(ifp->drvr->bus_if);
-+ ret = brcmf_bus_preinit(bus_if);
- if (ret < 0)
- goto fail;
-
-@@ -1163,7 +1162,12 @@ int brcmf_attach(struct device *dev, str
- /* attach firmware event handler */
- brcmf_fweh_attach(drvr);
-
-- return ret;
-+ ret = brcmf_bus_started(drvr);
-+ if (ret != 0) {
-+ brcmf_err("dongle is not responding: err=%d\n", ret);
-+ goto fail;
-+ }
-+ return 0;
-
- fail:
- brcmf_detach(dev);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -1581,24 +1581,6 @@ static void brcmf_pcie_release_resource(
- }
-
-
--static int brcmf_pcie_attach_bus(struct brcmf_pciedev_info *devinfo)
--{
-- int ret;
--
-- /* Attach to the common driver interface */
-- ret = brcmf_attach(&devinfo->pdev->dev, devinfo->settings);
-- if (ret) {
-- brcmf_err("brcmf_attach failed\n");
-- } else {
-- ret = brcmf_bus_started(&devinfo->pdev->dev);
-- if (ret)
-- brcmf_err("dongle is not responding\n");
-- }
--
-- return ret;
--}
--
--
- static u32 brcmf_pcie_buscore_prep_addr(const struct pci_dev *pdev, u32 addr)
- {
- u32 ret_addr;
-@@ -1735,7 +1717,7 @@ static void brcmf_pcie_setup(struct devi
- init_waitqueue_head(&devinfo->mbdata_resp_wait);
-
- brcmf_pcie_intr_enable(devinfo);
-- if (brcmf_pcie_attach_bus(devinfo) == 0)
-+ if (brcmf_attach(&devinfo->pdev->dev, devinfo->settings) == 0)
- return;
-
- brcmf_pcie_bus_console_read(devinfo);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -3422,6 +3422,8 @@ static int brcmf_sdio_bus_preinit(struct
- if (bus->rxbuf)
- bus->rxblen = value;
-
-+ brcmf_sdio_debugfs_create(bus);
-+
- /* the commands below use the terms tx and rx from
- * a device perspective, ie. bus:txglom affects the
- * bus transfers from device to host.
-@@ -4136,14 +4138,6 @@ static void brcmf_sdio_firmware_callback
- goto fail;
- }
-
-- brcmf_sdio_debugfs_create(bus);
--
-- err = brcmf_bus_started(dev);
-- if (err != 0) {
-- brcmf_err("dongle is not responding\n");
-- goto fail;
-- }
--
- /* ready */
- return;
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -1155,27 +1155,6 @@ static const struct brcmf_bus_ops brcmf_
- .get_fwname = brcmf_usb_get_fwname,
- };
-
--static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
--{
-- int ret;
--
-- /* Attach to the common driver interface */
-- ret = brcmf_attach(devinfo->dev, devinfo->settings);
-- if (ret) {
-- brcmf_err("brcmf_attach failed\n");
-- return ret;
-- }
--
-- ret = brcmf_bus_started(devinfo->dev);
-- if (ret)
-- goto fail;
--
-- return 0;
--fail:
-- brcmf_detach(devinfo->dev);
-- return ret;
--}
--
- static void brcmf_usb_probe_phase2(struct device *dev, int ret,
- const struct firmware *fw,
- void *nvram, u32 nvlen)
-@@ -1203,7 +1182,8 @@ static void brcmf_usb_probe_phase2(struc
- if (ret)
- goto error;
-
-- ret = brcmf_usb_bus_setup(devinfo);
-+ /* Attach to the common driver interface */
-+ ret = brcmf_attach(devinfo->dev, devinfo->settings);
- if (ret)
- goto error;
-
-@@ -1253,7 +1233,7 @@ static int brcmf_usb_probe_cb(struct brc
- }
-
- if (!brcmf_usb_dlneeded(devinfo)) {
-- ret = brcmf_usb_bus_setup(devinfo);
-+ ret = brcmf_attach(devinfo->dev, devinfo->settings);
- if (ret)
- goto fail;
- /* we are done */
-@@ -1456,7 +1436,7 @@ static int brcmf_usb_resume(struct usb_i
-
- brcmf_dbg(USB, "Enter\n");
- if (!devinfo->wowl_enabled)
-- return brcmf_usb_bus_setup(devinfo);
-+ return brcmf_attach(devinfo->dev, devinfo->settings);
-
- devinfo->bus_pub.state = BRCMFMAC_USB_STATE_UP;
- brcmf_usb_rx_fill_all(devinfo);
+++ /dev/null
-From d678296bfb9a630d0000222fc21f4ed0d0d65332 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 20 Feb 2018 00:14:24 +0100
-Subject: [PATCH] brcmfmac: change log level for some low-level sdio functions
-
-Reducing the number of trace level messages in sdio code giving
-them sdio log level instead.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -1706,7 +1706,7 @@ brcmf_sdio_read_control(struct brcmf_sdi
- u8 *buf = NULL, *rbuf;
- int sdret;
-
-- brcmf_dbg(TRACE, "Enter\n");
-+ brcmf_dbg(SDIO, "Enter\n");
- if (bus->rxblen)
- buf = vzalloc(bus->rxblen);
- if (!buf)
-@@ -1809,7 +1809,7 @@ static uint brcmf_sdio_readframes(struct
- struct brcmf_sdio_hdrinfo *rd = &bus->cur_read, rd_new;
- u8 head_read = 0;
-
-- brcmf_dbg(TRACE, "Enter\n");
-+ brcmf_dbg(SDIO, "Enter\n");
-
- /* Not finished unless we encounter no more frames indication */
- bus->rxpending = true;
-@@ -2344,7 +2344,7 @@ static int brcmf_sdio_tx_ctrlframe(struc
- struct brcmf_sdio_hdrinfo hd_info = {0};
- int ret;
-
-- brcmf_dbg(TRACE, "Enter\n");
-+ brcmf_dbg(SDIO, "Enter\n");
-
- /* Back the pointer to make room for bus header */
- frame -= bus->tx_hdrlen;
-@@ -2520,7 +2520,7 @@ static void brcmf_sdio_dpc(struct brcmf_
- uint framecnt; /* Temporary counter of tx/rx frames */
- int err = 0;
-
-- brcmf_dbg(TRACE, "Enter\n");
-+ brcmf_dbg(SDIO, "Enter\n");
-
- sdio_claim_host(bus->sdiodev->func1);
-
-@@ -2605,7 +2605,7 @@ static void brcmf_sdio_dpc(struct brcmf_
-
- /* Would be active due to wake-wlan in gSPI */
- if (intstatus & I_CHIPACTIVE) {
-- brcmf_dbg(INFO, "Dongle reports CHIPACTIVE\n");
-+ brcmf_dbg(SDIO, "Dongle reports CHIPACTIVE\n");
- intstatus &= ~I_CHIPACTIVE;
- }
-
+++ /dev/null
-From 2d6edad4b2da1991f74e7b02053eeb4a043b887f Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 20 Feb 2018 00:14:25 +0100
-Subject: [PATCH] brcmfmac: remove duplicate pointer variable from
- brcmf_sdio_firmware_callback()
-
-In brcmf_sdio_firmware_callback() two pointer variables were used
-pointing to the same construct. Get rid of sdiodev variable.
-
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 37 +++++++++++-----------
- 1 file changed, 18 insertions(+), 19 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -4039,9 +4039,8 @@ static void brcmf_sdio_firmware_callback
- void *nvram, u32 nvram_len)
- {
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-- struct brcmf_sdio *bus = sdiodev->bus;
-- struct brcmf_sdio_dev *sdiod = bus->sdiodev;
-+ struct brcmf_sdio_dev *sdiod = bus_if->bus_priv.sdio;
-+ struct brcmf_sdio *bus = sdiod->bus;
- struct brcmf_core *core = bus->sdio_core;
- u8 saveclk;
-
-@@ -4061,7 +4060,7 @@ static void brcmf_sdio_firmware_callback
- bus->sdcnt.tickcnt = 0;
- brcmf_sdio_wd_timer(bus, true);
-
-- sdio_claim_host(sdiodev->func1);
-+ sdio_claim_host(sdiod->func1);
-
- /* Make sure backplane clock is on, needed to generate F2 interrupt */
- brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
-@@ -4069,9 +4068,9 @@ static void brcmf_sdio_firmware_callback
- goto release;
-
- /* Force clocks on backplane to be sure F2 interrupt propagates */
-- saveclk = brcmf_sdiod_readb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, &err);
-+ saveclk = brcmf_sdiod_readb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (!err) {
-- brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
- }
- if (err) {
-@@ -4083,7 +4082,7 @@ static void brcmf_sdio_firmware_callback
- brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailboxdata),
- SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, NULL);
-
-- err = sdio_enable_func(sdiodev->func2);
-+ err = sdio_enable_func(sdiod->func2);
-
- brcmf_dbg(INFO, "enable F2: err=%d\n", err);
-
-@@ -4095,10 +4094,10 @@ static void brcmf_sdio_firmware_callback
- bus->hostintmask, NULL);
-
-
-- brcmf_sdiod_writeb(sdiodev, SBSDIO_WATERMARK, 8, &err);
-+ brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, 8, &err);
- } else {
- /* Disable F2 again */
-- sdio_disable_func(sdiodev->func2);
-+ sdio_disable_func(sdiod->func2);
- goto release;
- }
-
-@@ -4106,7 +4105,7 @@ static void brcmf_sdio_firmware_callback
- brcmf_sdio_sr_init(bus);
- } else {
- /* Restore previous clock setting */
-- brcmf_sdiod_writeb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
-+ brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_CHIPCLKCSR,
- saveclk, &err);
- }
-
-@@ -4114,7 +4113,7 @@ static void brcmf_sdio_firmware_callback
- /* Allow full data communication using DPC from now on. */
- brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
-
-- err = brcmf_sdiod_intr_register(sdiodev);
-+ err = brcmf_sdiod_intr_register(sdiod);
- if (err != 0)
- brcmf_err("intr register failed:%d\n", err);
- }
-@@ -4123,16 +4122,16 @@ static void brcmf_sdio_firmware_callback
- if (err != 0)
- brcmf_sdio_clkctl(bus, CLK_NONE, false);
-
-- sdio_release_host(sdiodev->func1);
-+ sdio_release_host(sdiod->func1);
-
- /* Assign bus interface call back */
-- sdiodev->bus_if->dev = sdiodev->dev;
-- sdiodev->bus_if->ops = &brcmf_sdio_bus_ops;
-- sdiodev->bus_if->chip = bus->ci->chip;
-- sdiodev->bus_if->chiprev = bus->ci->chiprev;
-+ sdiod->bus_if->dev = sdiod->dev;
-+ sdiod->bus_if->ops = &brcmf_sdio_bus_ops;
-+ sdiod->bus_if->chip = bus->ci->chip;
-+ sdiod->bus_if->chiprev = bus->ci->chiprev;
-
- /* Attach to the common layer, reserve hdr space */
-- err = brcmf_attach(sdiodev->dev, sdiodev->settings);
-+ err = brcmf_attach(sdiod->dev, sdiod->settings);
- if (err != 0) {
- brcmf_err("brcmf_attach failed\n");
- goto fail;
-@@ -4142,10 +4141,10 @@ static void brcmf_sdio_firmware_callback
- return;
-
- release:
-- sdio_release_host(sdiodev->func1);
-+ sdio_release_host(sdiod->func1);
- fail:
- brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
-- device_release_driver(&sdiodev->func2->dev);
-+ device_release_driver(&sdiod->func2->dev);
- device_release_driver(dev);
- }
-
+++ /dev/null
-From 64d1519edc959f5b8f86a66a51c40971c215e4ec Mon Sep 17 00:00:00 2001
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Mon, 19 Feb 2018 13:30:45 +0100
-Subject: [PATCH] brcmfmac: reject too long PSK
-
-nl80211 already allows specifying 48 bytes, but brcmfmac
-only supports 32. Reject keys that are too long.
-
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -5125,6 +5125,9 @@ static int brcmf_cfg80211_set_pmk(struct
- if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
- return -EINVAL;
-
-+ if (conf->pmk_len > BRCMF_WSEC_MAX_PSK_LEN)
-+ return -ERANGE;
-+
- return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);
- }
-
+++ /dev/null
-From 1170f6d1be6a39e1a115a2c0f50923eb4ce2a7ec Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:20 +0100
-Subject: [PATCH] brcmfmac: do not convert linux error to firmware error string
-
-In case of a linux error brcmf_fil_cmd_data() blurts an error message
-in which the error code is translated to an error string. However, it
-maps it to a firmware error string which should not happen. Simply
-print only the numeric error code and be done with it.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
-@@ -124,8 +124,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp,
- data, len, &fwerr);
-
- if (err) {
-- brcmf_dbg(FIL, "Failed: %s (%d)\n",
-- brcmf_fil_get_errstr((u32)(-err)), err);
-+ brcmf_dbg(FIL, "Failed: error=%d\n", err);
- } else if (fwerr < 0) {
- brcmf_dbg(FIL, "Firmware error: %s (%d)\n",
- brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
+++ /dev/null
-From 756a2b390874d274f2f615921318ef0856ff9313 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:21 +0100
-Subject: [PATCH] brcmfmac: use brcmf_chip_name() to store name in revinfo
-
-The chip id can either be four or five digits. For the chip name either
-the hexadecimal value needs to be taken (four digits) or the decimal
-value (five digits). The function brcmf_chip_name() does this conversion
-so use it to store the name in driver revision info.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/chip.c | 9 +++++----
- .../wireless/broadcom/brcm80211/brcmfmac/chip.h | 3 ++-
- .../wireless/broadcom/brcm80211/brcmfmac/common.c | 23 ++++++++++++++++------
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 10 +---------
- .../wireless/broadcom/brcm80211/brcmfmac/core.h | 3 +--
- 5 files changed, 26 insertions(+), 22 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-@@ -464,12 +464,12 @@ static void brcmf_chip_ai_resetcore(stru
- ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL);
- }
-
--static char *brcmf_chip_name(uint chipid, char *buf, uint len)
-+char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len)
- {
- const char *fmt;
-
-- fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
-- snprintf(buf, len, fmt, chipid);
-+ fmt = ((id > 0xa000) || (id < 0x4000)) ? "BCM%d/%u" : "BCM%x/%u";
-+ snprintf(buf, len, fmt, id, rev);
- return buf;
- }
-
-@@ -924,7 +924,8 @@ static int brcmf_chip_recognition(struct
- ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT;
- socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
-
-- brcmf_chip_name(ci->pub.chip, ci->pub.name, sizeof(ci->pub.name));
-+ brcmf_chip_name(ci->pub.chip, ci->pub.chiprev,
-+ ci->pub.name, sizeof(ci->pub.name));
- brcmf_dbg(INFO, "found %s chip: BCM%s, rev=%d\n",
- socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name,
- ci->pub.chiprev);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h
-@@ -45,7 +45,7 @@ struct brcmf_chip {
- u32 rambase;
- u32 ramsize;
- u32 srsize;
-- char name[8];
-+ char name[12];
- };
-
- /**
-@@ -93,5 +93,6 @@ void brcmf_chip_resetcore(struct brcmf_c
- 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);
-+char *brcmf_chip_name(u32 chipid, u32 chiprev, char *buf, uint len);
-
- #endif /* BRCMF_AXIDMP_H */
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -30,6 +30,7 @@
- #include "common.h"
- #include "of.h"
- #include "firmware.h"
-+#include "chip.h"
-
- MODULE_AUTHOR("Broadcom Corporation");
- MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
-@@ -131,14 +132,13 @@ static int brcmf_c_download(struct brcmf
- static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name)
- {
- struct brcmf_bus *bus = ifp->drvr->bus_if;
-- struct brcmf_rev_info *ri = &ifp->drvr->revinfo;
- u8 fw_name[BRCMF_FW_NAME_LEN];
- u8 *ptr;
- size_t len;
- s32 err;
-
- memset(fw_name, 0, BRCMF_FW_NAME_LEN);
-- err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name);
-+ err = brcmf_bus_get_fwname(bus, bus->chip, bus->chiprev, fw_name);
- if (err) {
- brcmf_err("get firmware name failed (%d)\n", err);
- goto done;
-@@ -238,6 +238,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
- {
- s8 eventmask[BRCMF_EVENTING_MASK_LEN];
- u8 buf[BRCMF_DCMD_SMLEN];
-+ struct brcmf_bus *bus;
- struct brcmf_rev_info_le revinfo;
- struct brcmf_rev_info *ri;
- char *clmver;
-@@ -253,16 +254,18 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
- }
- memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
-
-+ bus = ifp->drvr->bus_if;
-+ ri = &ifp->drvr->revinfo;
-+
- err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO,
- &revinfo, sizeof(revinfo));
-- ri = &ifp->drvr->revinfo;
- if (err < 0) {
- brcmf_err("retrieving revision info failed, %d\n", err);
-+ strlcpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname));
- } else {
- ri->vendorid = le32_to_cpu(revinfo.vendorid);
- ri->deviceid = le32_to_cpu(revinfo.deviceid);
- ri->radiorev = le32_to_cpu(revinfo.radiorev);
-- ri->chiprev = le32_to_cpu(revinfo.chiprev);
- ri->corerev = le32_to_cpu(revinfo.corerev);
- ri->boardid = le32_to_cpu(revinfo.boardid);
- ri->boardvendor = le32_to_cpu(revinfo.boardvendor);
-@@ -270,15 +273,23 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
- ri->driverrev = le32_to_cpu(revinfo.driverrev);
- ri->ucoderev = le32_to_cpu(revinfo.ucoderev);
- ri->bus = le32_to_cpu(revinfo.bus);
-- ri->chipnum = le32_to_cpu(revinfo.chipnum);
- ri->phytype = le32_to_cpu(revinfo.phytype);
- ri->phyrev = le32_to_cpu(revinfo.phyrev);
- ri->anarev = le32_to_cpu(revinfo.anarev);
- ri->chippkg = le32_to_cpu(revinfo.chippkg);
- ri->nvramrev = le32_to_cpu(revinfo.nvramrev);
-+
-+ if (!bus->chip) {
-+ bus->chip = le32_to_cpu(revinfo.chipnum);
-+ bus->chiprev = le32_to_cpu(revinfo.chiprev);
-+ }
- }
- ri->result = err;
-
-+ if (bus->chip)
-+ brcmf_chip_name(bus->chip, bus->chiprev,
-+ ri->chipname, sizeof(ri->chipname));
-+
- /* Do any CLM downloading */
- err = brcmf_c_process_clm_blob(ifp);
- if (err < 0) {
-@@ -299,7 +310,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
- strsep(&ptr, "\n");
-
- /* Print fw version info */
-- brcmf_info("Firmware version = %s\n", buf);
-+ brcmf_info("Firmware: %s %s\n", ri->chipname, buf);
-
- /* locate firmware version number for ethtool */
- ptr = strrchr(buf, ' ') + 1;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1002,8 +1002,7 @@ static int brcmf_revinfo_read(struct seq
- seq_printf(s, "vendorid: 0x%04x\n", ri->vendorid);
- seq_printf(s, "deviceid: 0x%04x\n", ri->deviceid);
- seq_printf(s, "radiorev: %s\n", brcmu_dotrev_str(ri->radiorev, drev));
-- seq_printf(s, "chipnum: %u (%x)\n", ri->chipnum, ri->chipnum);
-- seq_printf(s, "chiprev: %u\n", ri->chiprev);
-+ seq_printf(s, "chip: %s\n", ri->chipname);
- seq_printf(s, "chippkg: %u\n", ri->chippkg);
- seq_printf(s, "corerev: %u\n", ri->corerev);
- seq_printf(s, "boardid: 0x%04x\n", ri->boardid);
-@@ -1053,13 +1052,6 @@ static int brcmf_bus_started(struct brcm
-
- brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);
-
-- /* assure we have chipid before feature attach */
-- if (!bus_if->chip) {
-- bus_if->chip = drvr->revinfo.chipnum;
-- bus_if->chiprev = drvr->revinfo.chiprev;
-- brcmf_dbg(INFO, "firmware revinfo: chip %x (%d) rev %d\n",
-- bus_if->chip, bus_if->chip, bus_if->chiprev);
-- }
- brcmf_feat_attach(drvr);
-
- ret = brcmf_proto_init_done(drvr);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-@@ -87,7 +87,6 @@ struct brcmf_rev_info {
- u32 vendorid;
- u32 deviceid;
- u32 radiorev;
-- u32 chiprev;
- u32 corerev;
- u32 boardid;
- u32 boardvendor;
-@@ -95,7 +94,7 @@ struct brcmf_rev_info {
- u32 driverrev;
- u32 ucoderev;
- u32 bus;
-- u32 chipnum;
-+ char chipname[12];
- u32 phytype;
- u32 phyrev;
- u32 anarev;
+++ /dev/null
-From c88cfa075de356ddf40c668896b2126340f19ba4 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:22 +0100
-Subject: [PATCH] brcmfmac: use brcmf_chip_name() for consistency
-
-When logging the chip id/revision information make use of
-brcmf_chip_name() so it is always the same.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 5 ++---
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 7 +++++--
- 2 files changed, 7 insertions(+), 5 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-@@ -926,9 +926,8 @@ static int brcmf_chip_recognition(struct
-
- brcmf_chip_name(ci->pub.chip, ci->pub.chiprev,
- ci->pub.name, sizeof(ci->pub.name));
-- brcmf_dbg(INFO, "found %s chip: BCM%s, rev=%d\n",
-- socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name,
-- ci->pub.chiprev);
-+ brcmf_dbg(INFO, "found %s chip: %s\n",
-+ socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name);
-
- if (socitype == SOCI_SB) {
- if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -25,6 +25,7 @@
- #include "firmware.h"
- #include "core.h"
- #include "common.h"
-+#include "chip.h"
-
- #define BRCMF_FW_MAX_NVRAM_SIZE 64000
- #define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
-@@ -567,6 +568,7 @@ int brcmf_fw_map_chip_to_name(u32 chip,
- u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
- char nvram_name[BRCMF_FW_NAME_LEN])
- {
-+ char chipname[12];
- u32 i;
- char end;
-
-@@ -581,6 +583,8 @@ int brcmf_fw_map_chip_to_name(u32 chip,
- return -ENODEV;
- }
-
-+ brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname));
-+
- /* check if firmware path is provided by module parameter */
- if (brcmf_mp_global.firmware_path[0] != '\0') {
- strlcpy(fw_name, brcmf_mp_global.firmware_path,
-@@ -601,8 +605,7 @@ int brcmf_fw_map_chip_to_name(u32 chip,
- if ((nvram_name) && (mapping_table[i].nvram))
- strlcat(nvram_name, mapping_table[i].nvram, BRCMF_FW_NAME_LEN);
-
-- brcmf_info("using %s for chip %#08x(%d) rev %#08x\n",
-- fw_name, chip, chip, chiprev);
-+ brcmf_info("using %s for chip %s\n", fw_name, chipname);
-
- return 0;
- }
+++ /dev/null
-From 856d5a011c86b59f6564be4508912fb1d866adfc Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:23 +0100
-Subject: [PATCH] brcmfmac: allocate struct brcmf_pub instance using
- wiphy_new()
-
-Rework the driver so the wiphy instance holds the main driver information
-in its private buffer. Previously it held struct brcmf_cfg80211_info
-instance so a bit of reorg was needed. This was done so that the wiphy
-name or its parent device can be shown in debug output.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/btcoex.c | 2 +-
- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 86 ++++++++++------------
- .../broadcom/brcm80211/brcmfmac/cfg80211.h | 17 +++--
- .../wireless/broadcom/brcm80211/brcmfmac/common.c | 2 +
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 27 +++++--
- .../wireless/broadcom/brcm80211/brcmfmac/core.h | 1 +
- .../net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 2 +-
- 7 files changed, 76 insertions(+), 61 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c
-@@ -462,7 +462,7 @@ static void brcmf_btcoex_dhcp_end(struct
- int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif,
- enum brcmf_btcoex_mode mode, u16 duration)
- {
-- struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy);
-+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
- struct brcmf_btcoex_info *btci = cfg->btcoex;
- struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -753,7 +753,7 @@ s32 brcmf_notify_escan_complete(struct b
- static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
- struct wireless_dev *wdev)
- {
-- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
-+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct net_device *ndev = wdev->netdev;
- struct brcmf_if *ifp = netdev_priv(ndev);
- int ret;
-@@ -786,7 +786,7 @@ err_unarm:
- static
- int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
- {
-- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
-+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct net_device *ndev = wdev->netdev;
-
- if (ndev && ndev == cfg_to_ndev(cfg))
-@@ -831,7 +831,7 @@ brcmf_cfg80211_change_iface(struct wiphy
- enum nl80211_iftype type,
- struct vif_params *params)
- {
-- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
-+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_if *ifp = netdev_priv(ndev);
- struct brcmf_cfg80211_vif *vif = ifp->vif;
- s32 infra = 0;
-@@ -2127,17 +2127,15 @@ static s32
- brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
- s32 *dbm)
- {
-- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-- struct net_device *ndev = cfg_to_ndev(cfg);
-- struct brcmf_if *ifp = netdev_priv(ndev);
-+ struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev);
- s32 qdbm = 0;
- s32 err;
-
- brcmf_dbg(TRACE, "Enter\n");
-- if (!check_vif_up(ifp->vif))
-+ if (!check_vif_up(vif))
- return -EIO;
-
-- err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &qdbm);
-+ err = brcmf_fil_iovar_int_get(vif->ifp, "qtxpower", &qdbm);
- if (err) {
- brcmf_err("error (%d)\n", err);
- goto done;
-@@ -3359,7 +3357,7 @@ brcmf_cfg80211_sched_scan_start(struct w
- struct cfg80211_sched_scan_request *req)
- {
- struct brcmf_if *ifp = netdev_priv(ndev);
-- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
-+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-
- brcmf_dbg(SCAN, "Enter: n_match_sets=%d n_ssids=%d\n",
- req->n_match_sets, req->n_ssids);
-@@ -5191,6 +5189,12 @@ static struct cfg80211_ops brcmf_cfg8021
- .del_pmk = brcmf_cfg80211_del_pmk,
- };
-
-+struct cfg80211_ops *brcmf_cfg80211_get_ops(void)
-+{
-+ return kmemdup(&brcmf_cfg80211_ops, sizeof(brcmf_cfg80211_ops),
-+ GFP_KERNEL);
-+}
-+
- struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
- enum nl80211_iftype type)
- {
-@@ -5898,7 +5902,7 @@ static void brcmf_update_bw40_channel_fl
- static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
- u32 bw_cap[])
- {
-- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
-+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
- struct ieee80211_supported_band *band;
- struct ieee80211_channel *channel;
- struct wiphy *wiphy;
-@@ -6013,7 +6017,7 @@ fail_pbuf:
-
- static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg)
- {
-- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
-+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
- struct ieee80211_supported_band *band;
- struct brcmf_fil_bwcap_le band_bwcap;
- struct brcmf_chanspec_list *list;
-@@ -6198,10 +6202,10 @@ static void brcmf_update_vht_cap(struct
- }
- }
-
--static int brcmf_setup_wiphybands(struct wiphy *wiphy)
-+static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg)
- {
-- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
-- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
-+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
-+ struct wiphy *wiphy;
- u32 nmode = 0;
- u32 vhtmode = 0;
- u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
-@@ -6795,8 +6799,8 @@ static s32 brcmf_translate_country_code(
- static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
- struct regulatory_request *req)
- {
-- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
-- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
-+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
-+ struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0);
- struct brcmf_fil_country_le ccreq;
- s32 err;
- int i;
-@@ -6831,7 +6835,7 @@ static void brcmf_cfg80211_reg_notifier(
- brcmf_err("Firmware rejected country setting\n");
- return;
- }
-- brcmf_setup_wiphybands(wiphy);
-+ brcmf_setup_wiphybands(cfg);
- }
-
- static void brcmf_free_wiphy(struct wiphy *wiphy)
-@@ -6858,17 +6862,15 @@ static void brcmf_free_wiphy(struct wiph
- if (wiphy->wowlan != &brcmf_wowlan_support)
- kfree(wiphy->wowlan);
- #endif
-- wiphy_free(wiphy);
- }
-
- struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
-- struct device *busdev,
-+ struct cfg80211_ops *ops,
- bool p2pdev_forced)
- {
-+ struct wiphy *wiphy = drvr->wiphy;
- struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev;
- struct brcmf_cfg80211_info *cfg;
-- struct wiphy *wiphy;
-- struct cfg80211_ops *ops;
- struct brcmf_cfg80211_vif *vif;
- struct brcmf_if *ifp;
- s32 err = 0;
-@@ -6880,26 +6882,13 @@ struct brcmf_cfg80211_info *brcmf_cfg802
- return NULL;
- }
-
-- ops = kmemdup(&brcmf_cfg80211_ops, sizeof(*ops), GFP_KERNEL);
-- if (!ops)
-- return NULL;
--
-- ifp = netdev_priv(ndev);
--#ifdef CONFIG_PM
-- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
-- ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
--#endif
-- wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info));
-- if (!wiphy) {
-+ cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
-+ if (!cfg) {
- brcmf_err("Could not allocate wiphy device\n");
-- goto ops_out;
-+ return NULL;
- }
-- memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
-- set_wiphy_dev(wiphy, busdev);
-
-- cfg = wiphy_priv(wiphy);
- cfg->wiphy = wiphy;
-- cfg->ops = ops;
- cfg->pub = drvr;
- init_vif_event(&cfg->vif_event);
- INIT_LIST_HEAD(&cfg->vif_list);
-@@ -6908,6 +6897,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
- if (IS_ERR(vif))
- goto wiphy_out;
-
-+ ifp = netdev_priv(ndev);
- vif->ifp = ifp;
- vif->wdev.netdev = ndev;
- ndev->ieee80211_ptr = &vif->wdev;
-@@ -6934,6 +6924,11 @@ struct brcmf_cfg80211_info *brcmf_cfg802
- if (err < 0)
- goto priv_out;
-
-+ /* regulatory notifer below needs access to cfg so
-+ * assign it now.
-+ */
-+ drvr->config = cfg;
-+
- brcmf_dbg(INFO, "Registering custom regulatory\n");
- wiphy->reg_notifier = brcmf_cfg80211_reg_notifier;
- wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
-@@ -6947,13 +6942,17 @@ struct brcmf_cfg80211_info *brcmf_cfg802
- cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap;
- *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- }
-+#ifdef CONFIG_PM
-+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK))
-+ ops->set_rekey_data = brcmf_cfg80211_set_rekey_data;
-+#endif
- err = wiphy_register(wiphy);
- if (err < 0) {
- brcmf_err("Could not register wiphy device (%d)\n", err);
- goto priv_out;
- }
-
-- err = brcmf_setup_wiphybands(wiphy);
-+ err = brcmf_setup_wiphybands(cfg);
- if (err) {
- brcmf_err("Setting wiphy bands failed (%d)\n", err);
- goto wiphy_unreg_out;
-@@ -6970,12 +6969,7 @@ struct brcmf_cfg80211_info *brcmf_cfg802
- else
- *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- }
-- /* p2p might require that "if-events" get processed by fweh. So
-- * activate the already registered event handlers now and activate
-- * the rest when initialization has completed. drvr->config needs to
-- * be assigned before activating events.
-- */
-- drvr->config = cfg;
-+
- err = brcmf_fweh_activate_events(ifp);
- if (err) {
- brcmf_err("FWEH activation failed (%d)\n", err);
-@@ -7043,8 +7037,7 @@ priv_out:
- ifp->vif = NULL;
- wiphy_out:
- brcmf_free_wiphy(wiphy);
--ops_out:
-- kfree(ops);
-+ kfree(cfg);
- return NULL;
- }
-
-@@ -7059,4 +7052,5 @@ void brcmf_cfg80211_detach(struct brcmf_
- kfree(cfg->ops);
- wl_deinit_priv(cfg);
- brcmf_free_wiphy(cfg->wiphy);
-+ kfree(cfg);
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
-@@ -355,20 +355,24 @@ static inline struct wiphy *cfg_to_wiphy
-
- static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
- {
-- return (struct brcmf_cfg80211_info *)(wiphy_priv(w));
-+ struct brcmf_pub *drvr = wiphy_priv(w);
-+ return drvr->config;
- }
-
- static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd)
- {
-- return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
-+ return wiphy_to_cfg(wd->wiphy);
-+}
-+
-+static inline struct brcmf_cfg80211_vif *wdev_to_vif(struct wireless_dev *wdev)
-+{
-+ return container_of(wdev, struct brcmf_cfg80211_vif, wdev);
- }
-
- static inline
- struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
- {
-- struct brcmf_cfg80211_vif *vif;
-- vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list);
-- return vif->wdev.netdev;
-+ return brcmf_get_ifp(cfg->pub, 0)->ndev;
- }
-
- static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
-@@ -395,11 +399,12 @@ brcmf_cfg80211_connect_info *cfg_to_conn
- }
-
- struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
-- struct device *busdev,
-+ struct cfg80211_ops *ops,
- bool p2pdev_forced);
- void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
- s32 brcmf_cfg80211_up(struct net_device *ndev);
- s32 brcmf_cfg80211_down(struct net_device *ndev);
-+struct cfg80211_ops *brcmf_cfg80211_get_ops(void);
- enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp);
-
- struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -252,6 +252,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
- brcmf_err("Retreiving cur_etheraddr failed, %d\n", err);
- goto done;
- }
-+ memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN);
- memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
-
- bus = ifp->drvr->bus_if;
-@@ -279,6 +280,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_i
- ri->chippkg = le32_to_cpu(revinfo.chippkg);
- ri->nvramrev = le32_to_cpu(revinfo.nvramrev);
-
-+ /* use revinfo if not known yet */
- if (!bus->chip) {
- bus->chip = le32_to_cpu(revinfo.chipnum);
- bus->chiprev = le32_to_cpu(revinfo.chiprev);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1021,7 +1021,7 @@ static int brcmf_revinfo_read(struct seq
- return 0;
- }
-
--static int brcmf_bus_started(struct brcmf_pub *drvr)
-+static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
- {
- int ret = -1;
- struct brcmf_bus *bus_if = drvr->bus_if;
-@@ -1060,7 +1060,7 @@ static int brcmf_bus_started(struct brcm
-
- brcmf_proto_add_if(drvr, ifp);
-
-- drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev,
-+ drvr->config = brcmf_cfg80211_attach(drvr, ops,
- drvr->settings->p2p_enable);
- if (drvr->config == NULL) {
- ret = -ENOMEM;
-@@ -1115,17 +1115,26 @@ fail:
-
- int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings)
- {
-+ struct wiphy *wiphy;
-+ struct cfg80211_ops *ops;
- struct brcmf_pub *drvr = NULL;
- int ret = 0;
- int i;
-
- brcmf_dbg(TRACE, "Enter\n");
-
-- /* Allocate primary brcmf_info */
-- drvr = kzalloc(sizeof(*drvr), GFP_ATOMIC);
-- if (!drvr)
-+ ops = brcmf_cfg80211_get_ops();
-+ if (!ops)
- return -ENOMEM;
-
-+ wiphy = wiphy_new(ops, sizeof(*drvr));
-+ if (!wiphy)
-+ return -ENOMEM;
-+
-+ set_wiphy_dev(wiphy, dev);
-+ drvr = wiphy_priv(wiphy);
-+ drvr->wiphy = wiphy;
-+
- for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++)
- drvr->if2bss[i] = BRCMF_BSSIDX_INVALID;
-
-@@ -1154,15 +1163,18 @@ int brcmf_attach(struct device *dev, str
- /* attach firmware event handler */
- brcmf_fweh_attach(drvr);
-
-- ret = brcmf_bus_started(drvr);
-+ ret = brcmf_bus_started(drvr, ops);
- if (ret != 0) {
- brcmf_err("dongle is not responding: err=%d\n", ret);
- goto fail;
- }
-+
-+ drvr->config->ops = ops;
- return 0;
-
- fail:
- brcmf_detach(dev);
-+ kfree(ops);
-
- return ret;
- }
-@@ -1220,6 +1232,7 @@ void brcmf_detach(struct device *dev)
- brcmf_remove_interface(drvr->iflist[i], false);
-
- brcmf_cfg80211_detach(drvr->config);
-+ drvr->config = NULL;
-
- brcmf_bus_stop(drvr->bus_if);
-
-@@ -1227,7 +1240,7 @@ void brcmf_detach(struct device *dev)
-
- brcmf_debug_detach(drvr);
- bus_if->drvr = NULL;
-- kfree(drvr);
-+ wiphy_free(drvr->wiphy);
- }
-
- s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len)
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-@@ -107,6 +107,7 @@ struct brcmf_pub {
- /* Linkage ponters */
- struct brcmf_bus *bus_if;
- struct brcmf_proto *proto;
-+ struct wiphy *wiphy;
- struct brcmf_cfg80211_info *config;
-
- /* Internal brcmf items */
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-@@ -2229,7 +2229,7 @@ fail:
- */
- int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
- {
-- struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
-+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_p2p_info *p2p = &cfg->p2p;
- struct brcmf_cfg80211_vif *vif;
- enum nl80211_iftype iftype;
+++ /dev/null
-From 34789d0cf682c643862792750a06c31ccf016cbc Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:24 +0100
-Subject: [PATCH] brcmfmac: use wiphy debugfs dir entry
-
-The driver used to create a brcmfmac dir entry at the top level
-debugfs mount point. This moves the debugfs entries into the
-wiphy debugfs dir entry.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 6 ++++
- .../wireless/broadcom/brcm80211/brcmfmac/common.c | 5 ---
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 11 +++---
- .../wireless/broadcom/brcm80211/brcmfmac/debug.c | 42 ++--------------------
- .../wireless/broadcom/brcm80211/brcmfmac/debug.h | 17 ---------
- .../wireless/broadcom/brcm80211/brcmfmac/feature.c | 3 ++
- .../wireless/broadcom/brcm80211/brcmfmac/feature.h | 7 ++++
- .../broadcom/brcm80211/brcmfmac/fwsignal.c | 11 +++---
- .../broadcom/brcm80211/brcmfmac/fwsignal.h | 1 +
- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 8 +++--
- .../wireless/broadcom/brcm80211/brcmfmac/proto.c | 3 +-
- .../wireless/broadcom/brcm80211/brcmfmac/proto.h | 7 ++++
- 12 files changed, 47 insertions(+), 74 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
-@@ -445,6 +445,11 @@ brcmf_proto_bcdc_init_done(struct brcmf_
- return 0;
- }
-
-+static void brcmf_proto_bcdc_debugfs_create(struct brcmf_pub *drvr)
-+{
-+ brcmf_fws_debugfs_create(drvr);
-+}
-+
- int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
- {
- struct brcmf_bcdc *bcdc;
-@@ -472,6 +477,7 @@ int brcmf_proto_bcdc_attach(struct brcmf
- drvr->proto->del_if = brcmf_proto_bcdc_del_if;
- drvr->proto->reset_if = brcmf_proto_bcdc_reset_if;
- drvr->proto->init_done = brcmf_proto_bcdc_init_done;
-+ drvr->proto->debugfs_create = brcmf_proto_bcdc_debugfs_create;
- drvr->proto->pd = bcdc;
-
- drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -529,9 +529,6 @@ static int __init brcmfmac_module_init(v
- {
- int err;
-
-- /* Initialize debug system first */
-- brcmf_debugfs_init();
--
- /* Get the platform data (if available) for our devices */
- err = platform_driver_probe(&brcmf_pd, brcmf_common_pd_probe);
- if (err == -ENODEV)
-@@ -543,7 +540,6 @@ static int __init brcmfmac_module_init(v
- /* Continue the initialization by registering the different busses */
- err = brcmf_core_init();
- if (err) {
-- brcmf_debugfs_exit();
- if (brcmfmac_pdata)
- platform_driver_unregister(&brcmf_pd);
- }
-@@ -556,7 +552,6 @@ static void __exit brcmfmac_module_exit(
- brcmf_core_exit();
- if (brcmfmac_pdata)
- platform_driver_unregister(&brcmf_pd);
-- brcmf_debugfs_exit();
- }
-
- module_init(brcmfmac_module_init);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1050,8 +1050,6 @@ static int brcmf_bus_started(struct brcm
- if (ret < 0)
- goto fail;
-
-- brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);
--
- brcmf_feat_attach(drvr);
-
- ret = brcmf_proto_init_done(drvr);
-@@ -1094,6 +1092,11 @@ static int brcmf_bus_started(struct brcm
- #endif
- #endif /* CONFIG_INET */
-
-+ /* populate debugfs */
-+ brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read);
-+ brcmf_feat_debugfs_create(drvr);
-+ brcmf_proto_debugfs_create(drvr);
-+
- return 0;
-
- fail:
-@@ -1146,9 +1149,6 @@ int brcmf_attach(struct device *dev, str
- drvr->bus_if->drvr = drvr;
- drvr->settings = settings;
-
-- /* attach debug facilities */
-- brcmf_debug_attach(drvr);
--
- /* Attach and link in the protocol */
- ret = brcmf_proto_attach(drvr);
- if (ret != 0) {
-@@ -1238,7 +1238,6 @@ void brcmf_detach(struct device *dev)
-
- brcmf_proto_detach(drvr);
-
-- brcmf_debug_detach(drvr);
- bus_if->drvr = NULL;
- wiphy_free(drvr->wiphy);
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
-@@ -25,8 +25,6 @@
- #include "fweh.h"
- #include "debug.h"
-
--static struct dentry *root_folder;
--
- int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
- size_t len)
- {
-@@ -54,44 +52,9 @@ int brcmf_debug_create_memdump(struct br
- return 0;
- }
-
--void brcmf_debugfs_init(void)
--{
-- root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL);
-- if (IS_ERR(root_folder))
-- root_folder = NULL;
--}
--
--void brcmf_debugfs_exit(void)
--{
-- if (!root_folder)
-- return;
--
-- debugfs_remove_recursive(root_folder);
-- root_folder = NULL;
--}
--
--int brcmf_debug_attach(struct brcmf_pub *drvr)
--{
-- struct device *dev = drvr->bus_if->dev;
--
-- if (!root_folder)
-- return -ENODEV;
--
-- drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
-- return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
--}
--
--void brcmf_debug_detach(struct brcmf_pub *drvr)
--{
-- brcmf_fweh_unregister(drvr, BRCMF_E_PSM_WATCHDOG);
--
-- if (!IS_ERR_OR_NULL(drvr->dbgfs_dir))
-- debugfs_remove_recursive(drvr->dbgfs_dir);
--}
--
- struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
- {
-- return drvr->dbgfs_dir;
-+ return drvr->wiphy->debugfsdir;
- }
-
- int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
-@@ -99,7 +62,8 @@ int brcmf_debugfs_add_entry(struct brcmf
- {
- struct dentry *e;
-
-+ WARN(!drvr->wiphy->debugfsdir, "wiphy not (yet) registered\n");
- e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn,
-- drvr->dbgfs_dir, read_fn);
-+ drvr->wiphy->debugfsdir, read_fn);
- return PTR_ERR_OR_ZERO(e);
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
-@@ -113,29 +113,12 @@ extern int brcmf_msg_level;
- struct brcmf_bus;
- struct brcmf_pub;
- #ifdef DEBUG
--void brcmf_debugfs_init(void);
--void brcmf_debugfs_exit(void);
--int brcmf_debug_attach(struct brcmf_pub *drvr);
--void brcmf_debug_detach(struct brcmf_pub *drvr);
- struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
- int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
- int (*read_fn)(struct seq_file *seq, void *data));
- int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data,
- size_t len);
- #else
--static inline void brcmf_debugfs_init(void)
--{
--}
--static inline void brcmf_debugfs_exit(void)
--{
--}
--static inline int brcmf_debug_attach(struct brcmf_pub *drvr)
--{
-- return 0;
--}
--static inline void brcmf_debug_detach(struct brcmf_pub *drvr)
--{
--}
- static inline
- int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
- int (*read_fn)(struct seq_file *seq, void *data))
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-@@ -228,7 +228,10 @@ void brcmf_feat_attach(struct brcmf_pub
- /* no quirks */
- break;
- }
-+}
-
-+void brcmf_feat_debugfs_create(struct brcmf_pub *drvr)
-+{
- brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read);
- }
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
-@@ -90,6 +90,13 @@ enum brcmf_feat_quirk {
- void brcmf_feat_attach(struct brcmf_pub *drvr);
-
- /**
-+ * brcmf_feat_debugfs_create() - create debugfs entries.
-+ *
-+ * @drvr: driver instance.
-+ */
-+void brcmf_feat_debugfs_create(struct brcmf_pub *drvr);
-+
-+/**
- * brcmf_feat_is_enabled() - query feature.
- *
- * @ifp: interface instance.
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
-@@ -2399,10 +2399,6 @@ struct brcmf_fws_info *brcmf_fws_attach(
- brcmu_pktq_init(&fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT,
- BRCMF_FWS_PSQ_LEN);
-
-- /* create debugfs file for statistics */
-- brcmf_debugfs_add_entry(drvr, "fws_stats",
-- brcmf_debugfs_fws_stats_read);
--
- brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
- fws->fw_signals ? "enabled" : "disabled", tlv);
- return fws;
-@@ -2429,6 +2425,13 @@ void brcmf_fws_detach(struct brcmf_fws_i
- kfree(fws);
- }
-
-+void brcmf_fws_debugfs_create(struct brcmf_pub *drvr)
-+{
-+ /* create debugfs file for statistics */
-+ brcmf_debugfs_add_entry(drvr, "fws_stats",
-+ brcmf_debugfs_fws_stats_read);
-+}
-+
- bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws)
- {
- return !fws->avoid_queueing;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
-@@ -20,6 +20,7 @@
-
- struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr);
- void brcmf_fws_detach(struct brcmf_fws_info *fws);
-+void brcmf_fws_debugfs_create(struct brcmf_pub *drvr);
- bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws);
- bool brcmf_fws_fc_active(struct brcmf_fws_info *fws);
- void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-@@ -1418,6 +1418,11 @@ static int brcmf_msgbuf_stats_read(struc
- }
- #endif
-
-+static void brcmf_msgbuf_debugfs_create(struct brcmf_pub *drvr)
-+{
-+ brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read);
-+}
-+
- int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
- {
- struct brcmf_bus_msgbuf *if_msgbuf;
-@@ -1472,6 +1477,7 @@ int brcmf_proto_msgbuf_attach(struct brc
- drvr->proto->delete_peer = brcmf_msgbuf_delete_peer;
- drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer;
- drvr->proto->rxreorder = brcmf_msgbuf_rxreorder;
-+ drvr->proto->debugfs_create = brcmf_msgbuf_debugfs_create;
- drvr->proto->pd = msgbuf;
-
- init_waitqueue_head(&msgbuf->ioctl_resp_wait);
-@@ -1525,8 +1531,6 @@ 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:
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c
-@@ -54,7 +54,8 @@ int brcmf_proto_attach(struct brcmf_pub
- if (!proto->tx_queue_data || (proto->hdrpull == NULL) ||
- (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) ||
- (proto->configure_addr_mode == NULL) ||
-- (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL)) {
-+ (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL) ||
-+ (proto->debugfs_create == NULL)) {
- brcmf_err("Not all proto handlers have been installed\n");
- goto fail;
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h
-@@ -48,6 +48,7 @@ struct brcmf_proto {
- void (*del_if)(struct brcmf_if *ifp);
- void (*reset_if)(struct brcmf_if *ifp);
- int (*init_done)(struct brcmf_pub *drvr);
-+ void (*debugfs_create)(struct brcmf_pub *drvr);
- void *pd;
- };
-
-@@ -156,4 +157,10 @@ brcmf_proto_init_done(struct brcmf_pub *
- return drvr->proto->init_done(drvr);
- }
-
-+static inline void
-+brcmf_proto_debugfs_create(struct brcmf_pub *drvr)
-+{
-+ drvr->proto->debugfs_create(drvr);
-+}
-+
- #endif /* BRCMFMAC_PROTO_H */
+++ /dev/null
-From 41f573dbb534f14e62a4a5411f602c970cad1d77 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:25 +0100
-Subject: [PATCH] brcmfmac: derive firmware filenames from basename mapping
-
-Instead of defining individual filenames for firmware and nvram
-use a basename and derive the names from that.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/firmware.c | 31 ++++++---
- .../broadcom/brcm80211/brcmfmac/firmware.h | 24 ++-----
- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 56 ++++++++---------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 73 +++++++++++-----------
- .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 10 +--
- 5 files changed, 96 insertions(+), 98 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -563,6 +563,13 @@ int brcmf_fw_get_firmwares(struct device
- 0);
- }
-
-+static void brcmf_fw_get_full_name(char fw_name[BRCMF_FW_NAME_LEN],
-+ const char *fw_base, const char *extension)
-+{
-+ strlcat(fw_name, fw_base, BRCMF_FW_NAME_LEN);
-+ strlcat(fw_name, extension, BRCMF_FW_NAME_LEN);
-+}
-+
- int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
- struct brcmf_firmware_mapping mapping_table[],
- u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
-@@ -587,25 +594,31 @@ int brcmf_fw_map_chip_to_name(u32 chip,
-
- /* check if firmware path is provided by module parameter */
- if (brcmf_mp_global.firmware_path[0] != '\0') {
-- strlcpy(fw_name, brcmf_mp_global.firmware_path,
-- BRCMF_FW_NAME_LEN);
-- if ((nvram_name) && (mapping_table[i].nvram))
-+ if (fw_name)
-+ strlcpy(fw_name, brcmf_mp_global.firmware_path,
-+ BRCMF_FW_NAME_LEN);
-+ if (nvram_name)
- strlcpy(nvram_name, brcmf_mp_global.firmware_path,
- BRCMF_FW_NAME_LEN);
-
- end = brcmf_mp_global.firmware_path[
- strlen(brcmf_mp_global.firmware_path) - 1];
- if (end != '/') {
-- strlcat(fw_name, "/", BRCMF_FW_NAME_LEN);
-- if ((nvram_name) && (mapping_table[i].nvram))
-+ if (fw_name)
-+ strlcat(fw_name, "/", BRCMF_FW_NAME_LEN);
-+ if (nvram_name)
- strlcat(nvram_name, "/", BRCMF_FW_NAME_LEN);
- }
- }
-- strlcat(fw_name, mapping_table[i].fw, BRCMF_FW_NAME_LEN);
-- if ((nvram_name) && (mapping_table[i].nvram))
-- strlcat(nvram_name, mapping_table[i].nvram, BRCMF_FW_NAME_LEN);
-
-- brcmf_info("using %s for chip %s\n", fw_name, chipname);
-+ brcmf_info("using %s for chip %s\n",
-+ mapping_table[i].fw_base, chipname);
-+ if (fw_name)
-+ brcmf_fw_get_full_name(fw_name,
-+ mapping_table[i].fw_base, ".bin");
-+ if (nvram_name)
-+ brcmf_fw_get_full_name(nvram_name,
-+ mapping_table[i].fw_base, ".txt");
-
- return 0;
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-@@ -38,28 +38,16 @@
- struct brcmf_firmware_mapping {
- u32 chipid;
- u32 revmask;
-- const char *fw;
-- const char *nvram;
-+ const char *fw_base;
- };
-
--#define BRCMF_FW_NVRAM_DEF(fw_nvram_name, fw, nvram) \
--static const char BRCM_ ## fw_nvram_name ## _FIRMWARE_NAME[] = \
-- BRCMF_FW_DEFAULT_PATH fw; \
--static const char BRCM_ ## fw_nvram_name ## _NVRAM_NAME[] = \
-- BRCMF_FW_DEFAULT_PATH nvram; \
--MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw);
--
--#define BRCMF_FW_DEF(fw_name, fw) \
--static const char BRCM_ ## fw_name ## _FIRMWARE_NAME[] = \
-- BRCMF_FW_DEFAULT_PATH fw; \
--MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw) \
--
--#define BRCMF_FW_NVRAM_ENTRY(chipid, mask, name) \
-- { chipid, mask, \
-- BRCM_ ## name ## _FIRMWARE_NAME, BRCM_ ## name ## _NVRAM_NAME }
-+#define BRCMF_FW_DEF(fw_name, fw_base) \
-+static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \
-+ BRCMF_FW_DEFAULT_PATH fw_base; \
-+MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw_base ".bin")
-
- #define BRCMF_FW_ENTRY(chipid, mask, name) \
-- { chipid, mask, BRCM_ ## name ## _FIRMWARE_NAME, NULL }
-+ { chipid, mask, BRCM_ ## name ## _FIRMWARE_BASENAME }
-
- int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
- struct brcmf_firmware_mapping mapping_table[],
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -46,36 +46,36 @@ enum brcmf_pcie_state {
- BRCMFMAC_PCIE_STATE_UP
- };
-
--BRCMF_FW_NVRAM_DEF(43602, "brcmfmac43602-pcie.bin", "brcmfmac43602-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4350, "brcmfmac4350-pcie.bin", "brcmfmac4350-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4350C, "brcmfmac4350c2-pcie.bin", "brcmfmac4350c2-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-pcie.bin", "brcmfmac4356-pcie.txt");
--BRCMF_FW_NVRAM_DEF(43570, "brcmfmac43570-pcie.bin", "brcmfmac43570-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4358, "brcmfmac4358-pcie.bin", "brcmfmac4358-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4359, "brcmfmac4359-pcie.bin", "brcmfmac4359-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4365B, "brcmfmac4365b-pcie.bin", "brcmfmac4365b-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4365C, "brcmfmac4365c-pcie.bin", "brcmfmac4365c-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4366B, "brcmfmac4366b-pcie.bin", "brcmfmac4366b-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4366C, "brcmfmac4366c-pcie.bin", "brcmfmac4366c-pcie.txt");
--BRCMF_FW_NVRAM_DEF(4371, "brcmfmac4371-pcie.bin", "brcmfmac4371-pcie.txt");
-+BRCMF_FW_DEF(43602, "brcmfmac43602-pcie");
-+BRCMF_FW_DEF(4350, "brcmfmac4350-pcie");
-+BRCMF_FW_DEF(4350C, "brcmfmac4350c2-pcie");
-+BRCMF_FW_DEF(4356, "brcmfmac4356-pcie");
-+BRCMF_FW_DEF(43570, "brcmfmac43570-pcie");
-+BRCMF_FW_DEF(4358, "brcmfmac4358-pcie");
-+BRCMF_FW_DEF(4359, "brcmfmac4359-pcie");
-+BRCMF_FW_DEF(4365B, "brcmfmac4365b-pcie");
-+BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie");
-+BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie");
-+BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
-+BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
-
- static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 4350),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43525_CHIP_ID, 0xFFFFFFF0, 4365C),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
-+ BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
-+ BRCMF_FW_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C),
-+ BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C),
-+ BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 4350),
-+ BRCMF_FW_ENTRY(BRCM_CC_43525_CHIP_ID, 0xFFFFFFF0, 4365C),
-+ BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
-+ BRCMF_FW_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570),
-+ BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),
-+ BRCMF_FW_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570),
-+ BRCMF_FW_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
-+ BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
-+ BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B),
-+ BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C),
-+ BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B),
-+ BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C),
-+ BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
- };
-
- #define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -600,47 +600,44 @@ static const struct sdiod_drive_str sdio
- {4, 0x1}
- };
-
--BRCMF_FW_NVRAM_DEF(43143, "brcmfmac43143-sdio.bin", "brcmfmac43143-sdio.txt");
--BRCMF_FW_NVRAM_DEF(43241B0, "brcmfmac43241b0-sdio.bin",
-- "brcmfmac43241b0-sdio.txt");
--BRCMF_FW_NVRAM_DEF(43241B4, "brcmfmac43241b4-sdio.bin",
-- "brcmfmac43241b4-sdio.txt");
--BRCMF_FW_NVRAM_DEF(43241B5, "brcmfmac43241b5-sdio.bin",
-- "brcmfmac43241b5-sdio.txt");
--BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt");
--BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt");
--BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt");
--BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt");
--BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt");
--BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt");
--BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt");
--BRCMF_FW_NVRAM_DEF(43430A0, "brcmfmac43430a0-sdio.bin", "brcmfmac43430a0-sdio.txt");
-+BRCMF_FW_DEF(43143, "brcmfmac43143-sdio");
-+BRCMF_FW_DEF(43241B0, "brcmfmac43241b0-sdio");
-+BRCMF_FW_DEF(43241B4, "brcmfmac43241b4-sdio");
-+BRCMF_FW_DEF(43241B5, "brcmfmac43241b5-sdio");
-+BRCMF_FW_DEF(4329, "brcmfmac4329-sdio");
-+BRCMF_FW_DEF(4330, "brcmfmac4330-sdio");
-+BRCMF_FW_DEF(4334, "brcmfmac4334-sdio");
-+BRCMF_FW_DEF(43340, "brcmfmac43340-sdio");
-+BRCMF_FW_DEF(4335, "brcmfmac4335-sdio");
-+BRCMF_FW_DEF(43362, "brcmfmac43362-sdio");
-+BRCMF_FW_DEF(4339, "brcmfmac4339-sdio");
-+BRCMF_FW_DEF(43430A0, "brcmfmac43430a0-sdio");
- /* Note the names are not postfixed with a1 for backward compatibility */
--BRCMF_FW_NVRAM_DEF(43430A1, "brcmfmac43430-sdio.bin", "brcmfmac43430-sdio.txt");
--BRCMF_FW_NVRAM_DEF(43455, "brcmfmac43455-sdio.bin", "brcmfmac43455-sdio.txt");
--BRCMF_FW_NVRAM_DEF(4354, "brcmfmac4354-sdio.bin", "brcmfmac4354-sdio.txt");
--BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-sdio.bin", "brcmfmac4356-sdio.txt");
--BRCMF_FW_NVRAM_DEF(4373, "brcmfmac4373-sdio.bin", "brcmfmac4373-sdio.txt");
-+BRCMF_FW_DEF(43430A1, "brcmfmac43430-sdio");
-+BRCMF_FW_DEF(43455, "brcmfmac43455-sdio");
-+BRCMF_FW_DEF(4354, "brcmfmac4354-sdio");
-+BRCMF_FW_DEF(4356, "brcmfmac4356-sdio");
-+BRCMF_FW_DEF(4373, "brcmfmac4373-sdio");
-
- static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, 43241B5),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, 4329),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
-- BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
-- BRCMF_FW_NVRAM_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373)
-+ BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
-+ BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
-+ BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
-+ BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, 43241B5),
-+ BRCMF_FW_ENTRY(BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, 4329),
-+ BRCMF_FW_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330),
-+ BRCMF_FW_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334),
-+ BRCMF_FW_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340),
-+ BRCMF_FW_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340),
-+ BRCMF_FW_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
-+ BRCMF_FW_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
-+ BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
-+ BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0),
-+ BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1),
-+ BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
-+ BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354),
-+ BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
-+ BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373)
- };
-
- static void pkt_align(struct sk_buff *p, int len, int align)
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -46,11 +46,11 @@
- #define BRCMF_USB_CBCTL_READ 1
- #define BRCMF_USB_MAX_PKT_SIZE 1600
-
--BRCMF_FW_DEF(43143, "brcmfmac43143.bin");
--BRCMF_FW_DEF(43236B, "brcmfmac43236b.bin");
--BRCMF_FW_DEF(43242A, "brcmfmac43242a.bin");
--BRCMF_FW_DEF(43569, "brcmfmac43569.bin");
--BRCMF_FW_DEF(4373, "brcmfmac4373.bin");
-+BRCMF_FW_DEF(43143, "brcmfmac43143");
-+BRCMF_FW_DEF(43236B, "brcmfmac43236b");
-+BRCMF_FW_DEF(43242A, "brcmfmac43242a");
-+BRCMF_FW_DEF(43569, "brcmfmac43569");
-+BRCMF_FW_DEF(4373, "brcmfmac4373");
-
- static struct brcmf_firmware_mapping brcmf_usb_fwnames[] = {
- BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
+++ /dev/null
-From d09ae51a4b676151edaf572bcd5f272b5532639f Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:26 +0100
-Subject: [PATCH] brcmfmac: pass struct in brcmf_fw_get_firmwares()
-
-Make the function brcmf_fw_get_firmwares() a bit more easy to extend
-using a structure to pass the request parameters.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/firmware.c | 175 ++++++++++++++-------
- .../broadcom/brcm80211/brcmfmac/firmware.h | 43 +++--
- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 38 ++++-
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 32 +++-
- .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 43 ++++-
- 5 files changed, 245 insertions(+), 86 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -438,18 +438,31 @@ void brcmf_fw_nvram_free(void *nvram)
-
- struct brcmf_fw {
- struct device *dev;
-- u16 flags;
-- const struct firmware *code;
-- const char *nvram_name;
-- u16 domain_nr;
-- u16 bus_nr;
-- void (*done)(struct device *dev, int err, const struct firmware *fw,
-- void *nvram_image, u32 nvram_len);
-+ struct brcmf_fw_request *req;
-+ u32 curpos;
-+ void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
- };
-
-+static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
-+
-+static void brcmf_fw_free_request(struct brcmf_fw_request *req)
-+{
-+ struct brcmf_fw_item *item;
-+ int i;
-+
-+ for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
-+ if (item->type == BRCMF_FW_TYPE_BINARY)
-+ release_firmware(item->binary);
-+ else if (item->type == BRCMF_FW_TYPE_NVRAM)
-+ brcmf_fw_nvram_free(item->nv_data.data);
-+ }
-+ kfree(req);
-+}
-+
- static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
- {
- struct brcmf_fw *fwctx = ctx;
-+ struct brcmf_fw_item *cur;
- u32 nvram_length = 0;
- void *nvram = NULL;
- u8 *data = NULL;
-@@ -457,83 +470,150 @@ static void brcmf_fw_request_nvram_done(
- bool raw_nvram;
-
- brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
-+
-+ cur = &fwctx->req->items[fwctx->curpos];
-+
- if (fw && fw->data) {
- data = (u8 *)fw->data;
- data_len = fw->size;
- raw_nvram = false;
- } else {
- data = bcm47xx_nvram_get_contents(&data_len);
-- if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
-+ if (!data && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
- goto fail;
- raw_nvram = true;
- }
-
- if (data)
- nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length,
-- fwctx->domain_nr, fwctx->bus_nr);
-+ fwctx->req->domain_nr,
-+ fwctx->req->bus_nr);
-
- if (raw_nvram)
- bcm47xx_nvram_release_contents(data);
- release_firmware(fw);
-- if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
-+ if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
- goto fail;
-
-- fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length);
-- kfree(fwctx);
-+ brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
-+ cur->nv_data.data = nvram;
-+ cur->nv_data.len = nvram_length;
- return;
-
- fail:
- brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
-- release_firmware(fwctx->code);
-- fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0);
-+ fwctx->done(fwctx->dev, -ENOENT, NULL);
-+ brcmf_fw_free_request(fwctx->req);
- kfree(fwctx);
- }
-
--static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
-+static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
-+{
-+ struct brcmf_fw_item *cur;
-+ const struct firmware *fw = NULL;
-+ int ret;
-+
-+ cur = &fwctx->req->items[fwctx->curpos];
-+
-+ brcmf_dbg(TRACE, "%srequest for %s\n", async ? "async " : "",
-+ cur->path);
-+
-+ if (async)
-+ ret = request_firmware_nowait(THIS_MODULE, true, cur->path,
-+ fwctx->dev, GFP_KERNEL, fwctx,
-+ brcmf_fw_request_done);
-+ else
-+ ret = request_firmware(&fw, cur->path, fwctx->dev);
-+
-+ if (ret < 0) {
-+ brcmf_fw_request_done(NULL, fwctx);
-+ } else if (!async && fw) {
-+ brcmf_dbg(TRACE, "firmware %s %sfound\n", cur->path,
-+ fw ? "" : "not ");
-+ if (cur->type == BRCMF_FW_TYPE_BINARY)
-+ cur->binary = fw;
-+ else if (cur->type == BRCMF_FW_TYPE_NVRAM)
-+ brcmf_fw_request_nvram_done(fw, fwctx);
-+ else
-+ release_firmware(fw);
-+
-+ return -EAGAIN;
-+ }
-+ return 0;
-+}
-+
-+static void brcmf_fw_request_done(const struct firmware *fw, void *ctx)
- {
- struct brcmf_fw *fwctx = ctx;
-+ struct brcmf_fw_item *cur;
- int ret = 0;
-
-- brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
-- if (!fw) {
-+ cur = &fwctx->req->items[fwctx->curpos];
-+
-+ brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
-+ fw ? "" : "not ");
-+
-+ if (fw) {
-+ if (cur->type == BRCMF_FW_TYPE_BINARY)
-+ cur->binary = fw;
-+ else if (cur->type == BRCMF_FW_TYPE_NVRAM)
-+ brcmf_fw_request_nvram_done(fw, fwctx);
-+ else
-+ release_firmware(fw);
-+ } else if (cur->type == BRCMF_FW_TYPE_NVRAM) {
-+ brcmf_fw_request_nvram_done(NULL, fwctx);
-+ } else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) {
- ret = -ENOENT;
- goto fail;
- }
-- /* only requested code so done here */
-- if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM))
-- goto done;
--
-- fwctx->code = fw;
-- ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
-- fwctx->dev, GFP_KERNEL, fwctx,
-- brcmf_fw_request_nvram_done);
-
-- /* pass NULL to nvram callback for bcm47xx fallback */
-- if (ret)
-- brcmf_fw_request_nvram_done(NULL, fwctx);
-+ do {
-+ if (++fwctx->curpos == fwctx->req->n_items) {
-+ ret = 0;
-+ goto done;
-+ }
-+
-+ ret = brcmf_fw_request_next_item(fwctx, false);
-+ } while (ret == -EAGAIN);
-+
- return;
-
- fail:
-- brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
-+ brcmf_dbg(TRACE, "failed err=%d: dev=%s, fw=%s\n", ret,
-+ dev_name(fwctx->dev), cur->path);
-+ brcmf_fw_free_request(fwctx->req);
-+ fwctx->req = NULL;
- done:
-- fwctx->done(fwctx->dev, ret, fw, NULL, 0);
-+ fwctx->done(fwctx->dev, ret, fwctx->req);
- kfree(fwctx);
- }
-
--int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags,
-- const char *code, const char *nvram,
-- void (*fw_cb)(struct device *dev, int err,
-- const struct firmware *fw,
-- void *nvram_image, u32 nvram_len),
-- u16 domain_nr, u16 bus_nr)
-+static bool brcmf_fw_request_is_valid(struct brcmf_fw_request *req)
-+{
-+ struct brcmf_fw_item *item;
-+ int i;
-+
-+ if (!req->n_items)
-+ return false;
-+
-+ for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) {
-+ if (!item->path)
-+ return false;
-+ }
-+ return true;
-+}
-+
-+int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
-+ void (*fw_cb)(struct device *dev, int err,
-+ struct brcmf_fw_request *req))
- {
- struct brcmf_fw *fwctx;
-
- brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
-- if (!fw_cb || !code)
-+ if (!fw_cb)
- return -EINVAL;
-
-- if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
-+ if (!brcmf_fw_request_is_valid(req))
- return -EINVAL;
-
- fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
-@@ -541,26 +621,11 @@ int brcmf_fw_get_firmwares_pcie(struct d
- return -ENOMEM;
-
- fwctx->dev = dev;
-- fwctx->flags = flags;
-+ fwctx->req = req;
- 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, int err,
-- const struct firmware *fw,
-- void *nvram_image, u32 nvram_len))
--{
-- return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0,
-- 0);
-+ brcmf_fw_request_next_item(fwctx, true);
-+ return 0;
- }
-
- static void brcmf_fw_get_full_name(char fw_name[BRCMF_FW_NAME_LEN],
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-@@ -16,10 +16,7 @@
- #ifndef BRCMFMAC_FIRMWARE_H
- #define BRCMFMAC_FIRMWARE_H
-
--#define BRCMF_FW_REQUEST 0x000F
--#define BRCMF_FW_REQUEST_NVRAM 0x0001
--#define BRCMF_FW_REQ_FLAGS 0x00F0
--#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
-+#define BRCMF_FW_REQF_OPTIONAL 0x0001
-
- #define BRCMF_FW_NAME_LEN 320
-
-@@ -54,21 +51,39 @@ int brcmf_fw_map_chip_to_name(u32 chip,
- u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
- char nvram_name[BRCMF_FW_NAME_LEN]);
- void brcmf_fw_nvram_free(void *nvram);
-+
-+enum brcmf_fw_type {
-+ BRCMF_FW_TYPE_BINARY,
-+ BRCMF_FW_TYPE_NVRAM
-+};
-+
-+struct brcmf_fw_item {
-+ const char *path;
-+ enum brcmf_fw_type type;
-+ u16 flags;
-+ union {
-+ const struct firmware *binary;
-+ struct {
-+ void *data;
-+ u32 len;
-+ } nv_data;
-+ };
-+};
-+
-+struct brcmf_fw_request {
-+ u16 domain_nr;
-+ u16 bus_nr;
-+ u32 n_items;
-+ struct brcmf_fw_item items[0];
-+};
-+
- /*
- * Request firmware(s) asynchronously. When the asynchronous request
- * 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, int err,
-- 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,
-+int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req,
- void (*fw_cb)(struct device *dev, int err,
-- const struct firmware *fw,
-- void *nvram_image, u32 nvram_len));
-+ struct brcmf_fw_request *req));
-
- #endif /* BRCMFMAC_FIRMWARE_H */
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -1651,15 +1651,19 @@ static const struct brcmf_buscore_ops br
- .write32 = brcmf_pcie_buscore_write32,
- };
-
-+#define BRCMF_PCIE_FW_CODE 0
-+#define BRCMF_PCIE_FW_NVRAM 1
-+
- static void brcmf_pcie_setup(struct device *dev, int ret,
-- const struct firmware *fw,
-- void *nvram, u32 nvram_len)
-+ struct brcmf_fw_request *fwreq)
- {
-+ const struct firmware *fw;
-+ void *nvram;
- struct brcmf_bus *bus;
- struct brcmf_pciedev *pcie_bus_dev;
- struct brcmf_pciedev_info *devinfo;
- struct brcmf_commonring **flowrings;
-- u32 i;
-+ u32 i, nvram_len;
-
- /* check firmware loading result */
- if (ret)
-@@ -1670,6 +1674,11 @@ static void brcmf_pcie_setup(struct devi
- devinfo = pcie_bus_dev->devinfo;
- brcmf_pcie_attach(devinfo);
-
-+ fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary;
-+ nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data;
-+ nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len;
-+ kfree(fwreq);
-+
- /* Some of the firmwares have the size of the memory of the device
- * defined inside the firmware. This is because part of the memory in
- * the device is shared and the devision is determined by FW. Parse
-@@ -1730,6 +1739,7 @@ static int
- brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
- {
- int ret;
-+ struct brcmf_fw_request *fwreq;
- struct brcmf_pciedev_info *devinfo;
- struct brcmf_pciedev *pcie_bus_dev;
- struct brcmf_bus *bus;
-@@ -1800,12 +1810,26 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
- if (ret)
- goto fail_bus;
-
-- 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);
-+ fwreq = kzalloc(sizeof(*fwreq) + 2 * sizeof(struct brcmf_fw_item),
-+ GFP_KERNEL);
-+ if (!fwreq) {
-+ ret = -ENOMEM;
-+ goto fail_bus;
-+ }
-+
-+ fwreq->items[BRCMF_PCIE_FW_CODE].path = devinfo->fw_name;
-+ fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-+ fwreq->items[BRCMF_PCIE_FW_NVRAM].path = devinfo->nvram_name;
-+ fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
-+ fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
-+ fwreq->n_items = 2;
-+ fwreq->domain_nr = domain_nr;
-+ fwreq->bus_nr = bus_nr;
-+ ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
- if (ret == 0)
- return 0;
-+
-+ kfree(fwreq);
- fail_bus:
- kfree(bus->msgbuf);
- kfree(bus);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -4031,14 +4031,19 @@ static const struct brcmf_bus_ops brcmf_
- .get_fwname = brcmf_sdio_get_fwname,
- };
-
-+#define BRCMF_SDIO_FW_CODE 0
-+#define BRCMF_SDIO_FW_NVRAM 1
-+
- static void brcmf_sdio_firmware_callback(struct device *dev, int err,
-- const struct firmware *code,
-- void *nvram, u32 nvram_len)
-+ struct brcmf_fw_request *fwreq)
- {
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiod = bus_if->bus_priv.sdio;
- struct brcmf_sdio *bus = sdiod->bus;
- struct brcmf_core *core = bus->sdio_core;
-+ const struct firmware *code;
-+ void *nvram;
-+ u32 nvram_len;
- u8 saveclk;
-
- brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err);
-@@ -4046,6 +4051,11 @@ static void brcmf_sdio_firmware_callback
- if (err)
- goto fail;
-
-+ code = fwreq->items[BRCMF_SDIO_FW_CODE].binary;
-+ nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data;
-+ nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len;
-+ kfree(fwreq);
-+
- /* try to download image and nvram to the dongle */
- bus->alp_only = true;
- err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
-@@ -4150,6 +4160,7 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- int ret;
- struct brcmf_sdio *bus;
- struct workqueue_struct *wq;
-+ struct brcmf_fw_request *fwreq;
-
- brcmf_dbg(TRACE, "Enter\n");
-
-@@ -4240,11 +4251,24 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
- if (ret)
- goto fail;
-
-- ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM,
-- sdiodev->fw_name, sdiodev->nvram_name,
-+ fwreq = kzalloc(sizeof(fwreq) + 2 * sizeof(struct brcmf_fw_item),
-+ GFP_KERNEL);
-+ if (!fwreq) {
-+ ret = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ fwreq->items[BRCMF_SDIO_FW_CODE].path = sdiodev->fw_name;
-+ fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-+ fwreq->items[BRCMF_SDIO_FW_NVRAM].path = sdiodev->nvram_name;
-+ fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
-+ fwreq->n_items = 2;
-+
-+ ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq,
- brcmf_sdio_firmware_callback);
- if (ret != 0) {
- brcmf_err("async firmware request failed: %d\n", ret);
-+ kfree(fwreq);
- goto fail;
- }
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -1155,18 +1155,23 @@ static const struct brcmf_bus_ops brcmf_
- .get_fwname = brcmf_usb_get_fwname,
- };
-
-+#define BRCMF_USB_FW_CODE 0
-+
- static void brcmf_usb_probe_phase2(struct device *dev, int ret,
-- const struct firmware *fw,
-- void *nvram, u32 nvlen)
-+ struct brcmf_fw_request *fwreq)
- {
- struct brcmf_bus *bus = dev_get_drvdata(dev);
- struct brcmf_usbdev_info *devinfo = bus->bus_priv.usb->devinfo;
-+ const struct firmware *fw;
-
- if (ret)
- goto error;
-
- brcmf_dbg(USB, "Start fw downloading\n");
-
-+ fw = fwreq->items[BRCMF_USB_FW_CODE].binary;
-+ kfree(fwreq);
-+
- ret = check_file(fw->data);
- if (ret < 0) {
- brcmf_err("invalid firmware\n");
-@@ -1200,6 +1205,7 @@ static int brcmf_usb_probe_cb(struct brc
- struct brcmf_bus *bus = NULL;
- struct brcmf_usbdev *bus_pub = NULL;
- struct device *dev = devinfo->dev;
-+ struct brcmf_fw_request *fwreq;
- int ret;
-
- brcmf_dbg(USB, "Enter\n");
-@@ -1250,11 +1256,22 @@ static int brcmf_usb_probe_cb(struct brc
- if (ret)
- goto fail;
-
-+ fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
-+ GFP_KERNEL);
-+ if (!fwreq) {
-+ ret = -ENOMEM;
-+ goto fail;
-+ }
-+
-+ fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
-+ fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-+ fwreq->n_items = 1;
-+
- /* request firmware here */
-- ret = brcmf_fw_get_firmwares(dev, 0, devinfo->fw_name, NULL,
-- brcmf_usb_probe_phase2);
-+ ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2);
- if (ret) {
- brcmf_err("firmware request failed: %d\n", ret);
-+ kfree(fwreq);
- goto fail;
- }
-
-@@ -1447,11 +1464,25 @@ static int brcmf_usb_reset_resume(struct
- {
- struct usb_device *usb = interface_to_usbdev(intf);
- struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
-+ struct brcmf_fw_request *fwreq;
-+ int ret;
-
- brcmf_dbg(USB, "Enter\n");
-
-- return brcmf_fw_get_firmwares(&usb->dev, 0, devinfo->fw_name, NULL,
-- brcmf_usb_probe_phase2);
-+ fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
-+ GFP_KERNEL);
-+ if (!fwreq)
-+ return -ENOMEM;
-+
-+ fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
-+ fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-+ fwreq->n_items = 1;
-+
-+ ret = brcmf_fw_get_firmwares(&usb->dev, fwreq, brcmf_usb_probe_phase2);
-+ if (ret < 0)
-+ kfree(fwreq);
-+
-+ return ret;
- }
-
- #define BRCMF_USB_DEVICE(dev_id) \
+++ /dev/null
-From 2baa3aaee27f137b8db9a9224d0fe9b281d28e34 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:27 +0100
-Subject: [PATCH] brcmfmac: introduce brcmf_fw_alloc_request() function
-
-The function brcmf_fw_alloc_request() takes a list of required files
-and allocated the struct brcmf_fw_request instance accordingly. The
-request can be modified by the caller before being passed to the
-brcmf_fw_request_firmwares() function.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/firmware.c | 58 ++++++++++++++++++++++
- .../broadcom/brcm80211/brcmfmac/firmware.h | 11 ++++
- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 58 ++++++++++++----------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 38 ++++++++------
- .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 42 +++++++++-------
- 5 files changed, 147 insertions(+), 60 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -688,3 +688,61 @@ int brcmf_fw_map_chip_to_name(u32 chip,
- return 0;
- }
-
-+struct brcmf_fw_request *
-+brcmf_fw_alloc_request(u32 chip, u32 chiprev,
-+ struct brcmf_firmware_mapping mapping_table[],
-+ u32 table_size, struct brcmf_fw_name *fwnames,
-+ u32 n_fwnames)
-+{
-+ struct brcmf_fw_request *fwreq;
-+ char chipname[12];
-+ const char *mp_path;
-+ u32 i, j;
-+ char end;
-+ size_t reqsz;
-+
-+ for (i = 0; i < table_size; i++) {
-+ if (mapping_table[i].chipid == chip &&
-+ mapping_table[i].revmask & BIT(chiprev))
-+ break;
-+ }
-+
-+ if (i == table_size) {
-+ brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev);
-+ return NULL;
-+ }
-+
-+ reqsz = sizeof(*fwreq) + n_fwnames * sizeof(struct brcmf_fw_item);
-+ fwreq = kzalloc(reqsz, GFP_KERNEL);
-+ if (!fwreq)
-+ return NULL;
-+
-+ brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname));
-+
-+ brcmf_info("using %s for chip %s\n",
-+ mapping_table[i].fw_base, chipname);
-+
-+ mp_path = brcmf_mp_global.firmware_path;
-+ end = mp_path[strlen(mp_path) - 1];
-+ fwreq->n_items = n_fwnames;
-+
-+ for (j = 0; j < n_fwnames; j++) {
-+ fwreq->items[j].path = fwnames[j].path;
-+ /* check if firmware path is provided by module parameter */
-+ if (brcmf_mp_global.firmware_path[0] != '\0') {
-+ strlcpy(fwnames[j].path, mp_path,
-+ BRCMF_FW_NAME_LEN);
-+
-+ if (end != '/') {
-+ strlcat(fwnames[j].path, "/",
-+ BRCMF_FW_NAME_LEN);
-+ }
-+ }
-+ brcmf_fw_get_full_name(fwnames[j].path,
-+ mapping_table[i].fw_base,
-+ fwnames[j].extension);
-+ fwreq->items[j].path = fwnames[j].path;
-+ }
-+
-+ return fwreq;
-+}
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-@@ -77,6 +77,17 @@ struct brcmf_fw_request {
- struct brcmf_fw_item items[0];
- };
-
-+struct brcmf_fw_name {
-+ const char *extension;
-+ char *path;
-+};
-+
-+struct brcmf_fw_request *
-+brcmf_fw_alloc_request(u32 chip, u32 chiprev,
-+ struct brcmf_firmware_mapping mapping_table[],
-+ u32 table_size, struct brcmf_fw_name *fwnames,
-+ u32 n_fwnames);
-+
- /*
- * Request firmware(s) asynchronously. When the asynchronous request
- * fails it will not use the callback, but call device_release_driver()
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -1735,6 +1735,31 @@ fail:
- device_release_driver(dev);
- }
-
-+static struct brcmf_fw_request *
-+brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo)
-+{
-+ struct brcmf_fw_request *fwreq;
-+ struct brcmf_fw_name fwnames[] = {
-+ { ".bin", devinfo->fw_name },
-+ { ".txt", devinfo->nvram_name },
-+ };
-+
-+ fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev,
-+ brcmf_pcie_fwnames,
-+ ARRAY_SIZE(brcmf_pcie_fwnames),
-+ fwnames, ARRAY_SIZE(fwnames));
-+ if (!fwreq)
-+ return NULL;
-+
-+ fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-+ fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
-+ fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
-+ fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus);
-+ fwreq->bus_nr = devinfo->pdev->bus->number;
-+
-+ return fwreq;
-+}
-+
- static int
- brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
- {
-@@ -1743,13 +1768,8 @@ 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;
-
-- 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);
-+ brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device);
-
- ret = -ENOMEM;
- devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
-@@ -1803,33 +1823,19 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
- bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
- dev_set_drvdata(&pdev->dev, bus);
-
-- ret = brcmf_fw_map_chip_to_name(devinfo->ci->chip, devinfo->ci->chiprev,
-- brcmf_pcie_fwnames,
-- ARRAY_SIZE(brcmf_pcie_fwnames),
-- devinfo->fw_name, devinfo->nvram_name);
-- if (ret)
-- goto fail_bus;
--
-- fwreq = kzalloc(sizeof(*fwreq) + 2 * sizeof(struct brcmf_fw_item),
-- GFP_KERNEL);
-+ fwreq = brcmf_pcie_prepare_fw_request(devinfo);
- if (!fwreq) {
- ret = -ENOMEM;
- goto fail_bus;
- }
-
-- fwreq->items[BRCMF_PCIE_FW_CODE].path = devinfo->fw_name;
-- fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-- fwreq->items[BRCMF_PCIE_FW_NVRAM].path = devinfo->nvram_name;
-- fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
-- fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
-- fwreq->n_items = 2;
-- fwreq->domain_nr = domain_nr;
-- fwreq->bus_nr = bus_nr;
- ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
-- if (ret == 0)
-- return 0;
-+ if (ret < 0) {
-+ kfree(fwreq);
-+ goto fail_bus;
-+ }
-+ return 0;
-
-- kfree(fwreq);
- fail_bus:
- kfree(bus->msgbuf);
- kfree(bus);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -4155,6 +4155,28 @@ fail:
- device_release_driver(dev);
- }
-
-+static struct brcmf_fw_request *
-+brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
-+{
-+ struct brcmf_fw_request *fwreq;
-+ struct brcmf_fw_name fwnames[] = {
-+ { ".bin", bus->sdiodev->fw_name },
-+ { ".txt", bus->sdiodev->nvram_name },
-+ };
-+
-+ fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev,
-+ brcmf_sdio_fwnames,
-+ ARRAY_SIZE(brcmf_sdio_fwnames),
-+ fwnames, ARRAY_SIZE(fwnames));
-+ if (!fwreq)
-+ return NULL;
-+
-+ fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-+ fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
-+
-+ return fwreq;
-+}
-+
- struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
- {
- int ret;
-@@ -4244,26 +4266,12 @@ struct brcmf_sdio *brcmf_sdio_probe(stru
-
- brcmf_dbg(INFO, "completed!!\n");
-
-- ret = brcmf_fw_map_chip_to_name(bus->ci->chip, bus->ci->chiprev,
-- brcmf_sdio_fwnames,
-- ARRAY_SIZE(brcmf_sdio_fwnames),
-- sdiodev->fw_name, sdiodev->nvram_name);
-- if (ret)
-- goto fail;
--
-- fwreq = kzalloc(sizeof(fwreq) + 2 * sizeof(struct brcmf_fw_item),
-- GFP_KERNEL);
-+ fwreq = brcmf_sdio_prepare_fw_request(bus);
- if (!fwreq) {
- ret = -ENOMEM;
- goto fail;
- }
-
-- fwreq->items[BRCMF_SDIO_FW_CODE].path = sdiodev->fw_name;
-- fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-- fwreq->items[BRCMF_SDIO_FW_NVRAM].path = sdiodev->nvram_name;
-- fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
-- fwreq->n_items = 2;
--
- ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq,
- brcmf_sdio_firmware_callback);
- if (ret != 0) {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -1200,6 +1200,27 @@ error:
- device_release_driver(dev);
- }
-
-+static struct brcmf_fw_request *
-+brcmf_usb_prepare_fw_request(struct brcmf_usbdev_info *devinfo)
-+{
-+ struct brcmf_fw_request *fwreq;
-+ struct brcmf_fw_name fwnames[] = {
-+ { ".bin", devinfo->fw_name },
-+ };
-+
-+ fwreq = brcmf_fw_alloc_request(devinfo->bus_pub.devid,
-+ devinfo->bus_pub.chiprev,
-+ brcmf_usb_fwnames,
-+ ARRAY_SIZE(brcmf_usb_fwnames),
-+ fwnames, ARRAY_SIZE(fwnames));
-+ if (!fwreq)
-+ return NULL;
-+
-+ fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-+
-+ return fwreq;
-+}
-+
- static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
- {
- struct brcmf_bus *bus = NULL;
-@@ -1249,24 +1270,12 @@ static int brcmf_usb_probe_cb(struct brc
- bus->chip = bus_pub->devid;
- bus->chiprev = bus_pub->chiprev;
-
-- ret = brcmf_fw_map_chip_to_name(bus_pub->devid, bus_pub->chiprev,
-- brcmf_usb_fwnames,
-- ARRAY_SIZE(brcmf_usb_fwnames),
-- devinfo->fw_name, NULL);
-- if (ret)
-- goto fail;
--
-- fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
-- GFP_KERNEL);
-+ fwreq = brcmf_usb_prepare_fw_request(devinfo);
- if (!fwreq) {
- ret = -ENOMEM;
- goto fail;
- }
-
-- fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
-- fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-- fwreq->n_items = 1;
--
- /* request firmware here */
- ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2);
- if (ret) {
-@@ -1469,15 +1478,10 @@ static int brcmf_usb_reset_resume(struct
-
- brcmf_dbg(USB, "Enter\n");
-
-- fwreq = kzalloc(sizeof(*fwreq) + sizeof(struct brcmf_fw_item),
-- GFP_KERNEL);
-+ fwreq = brcmf_usb_prepare_fw_request(devinfo);
- if (!fwreq)
- return -ENOMEM;
-
-- fwreq->items[BRCMF_USB_FW_CODE].path = devinfo->fw_name;
-- fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
-- fwreq->n_items = 1;
--
- ret = brcmf_fw_get_firmwares(&usb->dev, fwreq, brcmf_usb_probe_phase2);
- if (ret < 0)
- kfree(fwreq);
+++ /dev/null
-From bf7a7b37f6ef5090a2bae7e7ae23cd26b741cca4 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:28 +0100
-Subject: [PATCH] brcmfmac: add extension to .get_fwname() callbacks
-
-This changes the bus layer api by having the caller provide an
-extension. With this the callback can use brcmf_fw_alloc_request()
-to get the needed firmware name.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 6 +--
- .../wireless/broadcom/brcm80211/brcmfmac/common.c | 43 +++-------------------
- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 27 +++++++-------
- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 26 +++++++------
- .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 27 ++++++++------
- 5 files changed, 51 insertions(+), 78 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-@@ -88,7 +88,7 @@ struct brcmf_bus_ops {
- void (*wowl_config)(struct device *dev, bool enabled);
- size_t (*get_ramsize)(struct device *dev);
- int (*get_memdump)(struct device *dev, void *data, size_t len);
-- int (*get_fwname)(struct device *dev, uint chip, uint chiprev,
-+ int (*get_fwname)(struct device *dev, const char *ext,
- unsigned char *fw_name);
- };
-
-@@ -228,10 +228,10 @@ int brcmf_bus_get_memdump(struct brcmf_b
- }
-
- static inline
--int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev,
-+int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext,
- unsigned char *fw_name)
- {
-- return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name);
-+ return bus->ops->get_fwname(bus->dev, ext, fw_name);
- }
-
- /*
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -129,42 +129,9 @@ static int brcmf_c_download(struct brcmf
- return err;
- }
-
--static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name)
--{
-- struct brcmf_bus *bus = ifp->drvr->bus_if;
-- u8 fw_name[BRCMF_FW_NAME_LEN];
-- u8 *ptr;
-- size_t len;
-- s32 err;
--
-- memset(fw_name, 0, BRCMF_FW_NAME_LEN);
-- err = brcmf_bus_get_fwname(bus, bus->chip, bus->chiprev, fw_name);
-- if (err) {
-- brcmf_err("get firmware name failed (%d)\n", err);
-- goto done;
-- }
--
-- /* generate CLM blob file name */
-- ptr = strrchr(fw_name, '.');
-- if (!ptr) {
-- err = -ENOENT;
-- goto done;
-- }
--
-- len = ptr - fw_name + 1;
-- if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) {
-- err = -E2BIG;
-- } else {
-- strlcpy(clm_name, fw_name, len);
-- strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN);
-- }
--done:
-- return err;
--}
--
- static int brcmf_c_process_clm_blob(struct brcmf_if *ifp)
- {
-- struct device *dev = ifp->drvr->bus_if->dev;
-+ struct brcmf_bus *bus = ifp->drvr->bus_if;
- struct brcmf_dload_data_le *chunk_buf;
- const struct firmware *clm = NULL;
- u8 clm_name[BRCMF_FW_NAME_LEN];
-@@ -177,16 +144,16 @@ static int brcmf_c_process_clm_blob(stru
-
- brcmf_dbg(TRACE, "Enter\n");
-
-- memset(clm_name, 0, BRCMF_FW_NAME_LEN);
-- err = brcmf_c_get_clm_name(ifp, clm_name);
-+ memset(clm_name, 0, sizeof(clm_name));
-+ err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name);
- if (err) {
- brcmf_err("get CLM blob file name failed (%d)\n", err);
- return err;
- }
-
-- err = request_firmware(&clm, clm_name, dev);
-+ err = request_firmware(&clm, clm_name, bus->dev);
- if (err) {
-- brcmf_info("no clm_blob available(err=%d), device may have limited channels available\n",
-+ brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n",
- err);
- return 0;
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -1350,23 +1350,24 @@ static int brcmf_pcie_get_memdump(struct
- return 0;
- }
-
--static int brcmf_pcie_get_fwname(struct device *dev, u32 chip, u32 chiprev,
-- u8 *fw_name)
-+static
-+int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
- {
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-- struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
-- struct brcmf_pciedev_info *devinfo = buspub->devinfo;
-- int ret = 0;
-+ struct brcmf_fw_request *fwreq;
-+ struct brcmf_fw_name fwnames[] = {
-+ { ext, fw_name },
-+ };
-
-- if (devinfo->fw_name[0] != '\0')
-- strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
-- else
-- ret = brcmf_fw_map_chip_to_name(chip, chiprev,
-- brcmf_pcie_fwnames,
-- ARRAY_SIZE(brcmf_pcie_fwnames),
-- fw_name, NULL);
-+ fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
-+ brcmf_pcie_fwnames,
-+ ARRAY_SIZE(brcmf_pcie_fwnames),
-+ fwnames, ARRAY_SIZE(fwnames));
-+ if (!fwreq)
-+ return -ENOMEM;
-
-- return ret;
-+ kfree(fwreq);
-+ return 0;
- }
-
- static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -4000,22 +4000,24 @@ brcmf_sdio_watchdog(unsigned long data)
- }
- }
-
--static int brcmf_sdio_get_fwname(struct device *dev, u32 chip, u32 chiprev,
-- u8 *fw_name)
-+static
-+int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
- {
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-- int ret = 0;
-+ struct brcmf_fw_request *fwreq;
-+ struct brcmf_fw_name fwnames[] = {
-+ { ext, fw_name },
-+ };
-
-- if (sdiodev->fw_name[0] != '\0')
-- strlcpy(fw_name, sdiodev->fw_name, BRCMF_FW_NAME_LEN);
-- else
-- ret = brcmf_fw_map_chip_to_name(chip, chiprev,
-- brcmf_sdio_fwnames,
-- ARRAY_SIZE(brcmf_sdio_fwnames),
-- fw_name, NULL);
-+ fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev,
-+ brcmf_sdio_fwnames,
-+ ARRAY_SIZE(brcmf_sdio_fwnames),
-+ fwnames, ARRAY_SIZE(fwnames));
-+ if (!fwreq)
-+ return -ENOMEM;
-
-- return ret;
-+ kfree(fwreq);
-+ return 0;
- }
-
- static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -1128,21 +1128,24 @@ static void brcmf_usb_wowl_config(struct
- device_set_wakeup_enable(devinfo->dev, false);
- }
-
--static int brcmf_usb_get_fwname(struct device *dev, u32 chip, u32 chiprev,
-- u8 *fw_name)
-+static
-+int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name)
- {
-- struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
-- int ret = 0;
-+ struct brcmf_bus *bus = dev_get_drvdata(dev);
-+ struct brcmf_fw_request *fwreq;
-+ struct brcmf_fw_name fwnames[] = {
-+ { ext, fw_name },
-+ };
-
-- if (devinfo->fw_name[0] != '\0')
-- strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN);
-- else
-- ret = brcmf_fw_map_chip_to_name(chip, chiprev,
-- brcmf_usb_fwnames,
-- ARRAY_SIZE(brcmf_usb_fwnames),
-- fw_name, NULL);
-+ fwreq = brcmf_fw_alloc_request(bus->chip, bus->chiprev,
-+ brcmf_usb_fwnames,
-+ ARRAY_SIZE(brcmf_usb_fwnames),
-+ fwnames, ARRAY_SIZE(fwnames));
-+ if (!fwreq)
-+ return -ENOMEM;
-
-- return ret;
-+ kfree(fwreq);
-+ return 0;
- }
-
- static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
+++ /dev/null
-From 18c2b20e276e04476a3350b4a92c1dfad725d45d Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:29 +0100
-Subject: [PATCH] brcmfmac: get rid of brcmf_fw_map_chip_to_name()
-
-The function is no longer used so removing it.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/firmware.c | 53 ----------------------
- .../broadcom/brcm80211/brcmfmac/firmware.h | 4 --
- 2 files changed, 57 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -635,59 +635,6 @@ static void brcmf_fw_get_full_name(char
- strlcat(fw_name, extension, BRCMF_FW_NAME_LEN);
- }
-
--int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
-- struct brcmf_firmware_mapping mapping_table[],
-- u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
-- char nvram_name[BRCMF_FW_NAME_LEN])
--{
-- char chipname[12];
-- u32 i;
-- char end;
--
-- for (i = 0; i < table_size; i++) {
-- if (mapping_table[i].chipid == chip &&
-- mapping_table[i].revmask & BIT(chiprev))
-- break;
-- }
--
-- if (i == table_size) {
-- brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev);
-- return -ENODEV;
-- }
--
-- brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname));
--
-- /* check if firmware path is provided by module parameter */
-- if (brcmf_mp_global.firmware_path[0] != '\0') {
-- if (fw_name)
-- strlcpy(fw_name, brcmf_mp_global.firmware_path,
-- BRCMF_FW_NAME_LEN);
-- if (nvram_name)
-- strlcpy(nvram_name, brcmf_mp_global.firmware_path,
-- BRCMF_FW_NAME_LEN);
--
-- end = brcmf_mp_global.firmware_path[
-- strlen(brcmf_mp_global.firmware_path) - 1];
-- if (end != '/') {
-- if (fw_name)
-- strlcat(fw_name, "/", BRCMF_FW_NAME_LEN);
-- if (nvram_name)
-- strlcat(nvram_name, "/", BRCMF_FW_NAME_LEN);
-- }
-- }
--
-- brcmf_info("using %s for chip %s\n",
-- mapping_table[i].fw_base, chipname);
-- if (fw_name)
-- brcmf_fw_get_full_name(fw_name,
-- mapping_table[i].fw_base, ".bin");
-- if (nvram_name)
-- brcmf_fw_get_full_name(nvram_name,
-- mapping_table[i].fw_base, ".txt");
--
-- return 0;
--}
--
- struct brcmf_fw_request *
- brcmf_fw_alloc_request(u32 chip, u32 chiprev,
- struct brcmf_firmware_mapping mapping_table[],
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-@@ -46,10 +46,6 @@ MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw
- #define BRCMF_FW_ENTRY(chipid, mask, name) \
- { chipid, mask, BRCM_ ## name ## _FIRMWARE_BASENAME }
-
--int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
-- struct brcmf_firmware_mapping mapping_table[],
-- u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
-- char nvram_name[BRCMF_FW_NAME_LEN]);
- void brcmf_fw_nvram_free(void *nvram);
-
- enum brcmf_fw_type {
+++ /dev/null
-From bf291b7247e53f52a4236c0b55a5df046d6177df Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:30 +0100
-Subject: [PATCH] brcmfmac: get rid of brcmf_fw_get_full_name()
-
-The function was pretty minimal and now it is called only from one
-place so just get rid of it.
-
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 14 ++++----------
- 1 file changed, 4 insertions(+), 10 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -628,13 +628,6 @@ int brcmf_fw_get_firmwares(struct device
- return 0;
- }
-
--static void brcmf_fw_get_full_name(char fw_name[BRCMF_FW_NAME_LEN],
-- const char *fw_base, const char *extension)
--{
-- strlcat(fw_name, fw_base, BRCMF_FW_NAME_LEN);
-- strlcat(fw_name, extension, BRCMF_FW_NAME_LEN);
--}
--
- struct brcmf_fw_request *
- brcmf_fw_alloc_request(u32 chip, u32 chiprev,
- struct brcmf_firmware_mapping mapping_table[],
-@@ -685,9 +678,10 @@ brcmf_fw_alloc_request(u32 chip, u32 chi
- BRCMF_FW_NAME_LEN);
- }
- }
-- brcmf_fw_get_full_name(fwnames[j].path,
-- mapping_table[i].fw_base,
-- fwnames[j].extension);
-+ strlcat(fwnames[j].path, mapping_table[i].fw_base,
-+ BRCMF_FW_NAME_LEN);
-+ strlcat(fwnames[j].path, fwnames[j].extension,
-+ BRCMF_FW_NAME_LEN);
- fwreq->items[j].path = fwnames[j].path;
- }
-
+++ /dev/null
-From 48eaee3f272a5bfe6986d07c51f6975d3c2f74d1 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 22 Mar 2018 21:28:31 +0100
-Subject: [PATCH] brcmfmac: add kerneldoc for struct brcmf_bus::msgbuf
-
-This field did not have kerneldoc description so adding it now.
-
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-@@ -140,6 +140,7 @@ struct brcmf_bus_stats {
- * @always_use_fws_queue: bus wants use queue also when fwsignal is inactive.
- * @wowl_supported: is wowl supported by bus driver.
- * @chiprev: revision of the dongle chip.
-+ * @msgbuf: msgbuf protocol parameters provided by bus layer.
- */
- struct brcmf_bus {
- union {
+++ /dev/null
-From 0b5c0305e57ca940713bcb2b202fd2b412c62f31 Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Tue, 3 Apr 2018 10:18:15 +0200
-Subject: [PATCH] brcmfmac: fix firmware request processing if nvram load fails
-
-When nvram loading fails a double free occurred. Fix this and reorg the
-code a little.
-
-Fixes: d09ae51a4b67 ("brcmfmac: pass struct in brcmf_fw_get_firmwares()")
-Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/firmware.c | 36 ++++++++++++----------
- 1 file changed, 20 insertions(+), 16 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -459,7 +459,7 @@ static void brcmf_fw_free_request(struct
- kfree(req);
- }
-
--static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
-+static int brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
- {
- struct brcmf_fw *fwctx = ctx;
- struct brcmf_fw_item *cur;
-@@ -498,13 +498,10 @@ static void brcmf_fw_request_nvram_done(
- brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length);
- cur->nv_data.data = nvram;
- cur->nv_data.len = nvram_length;
-- return;
-+ return 0;
-
- fail:
-- brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
-- fwctx->done(fwctx->dev, -ENOENT, NULL);
-- brcmf_fw_free_request(fwctx->req);
-- kfree(fwctx);
-+ return -ENOENT;
- }
-
- static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async)
-@@ -553,20 +550,27 @@ static void brcmf_fw_request_done(const
- brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path,
- fw ? "" : "not ");
-
-- if (fw) {
-- if (cur->type == BRCMF_FW_TYPE_BINARY)
-- cur->binary = fw;
-- else if (cur->type == BRCMF_FW_TYPE_NVRAM)
-- brcmf_fw_request_nvram_done(fw, fwctx);
-- else
-- release_firmware(fw);
-- } else if (cur->type == BRCMF_FW_TYPE_NVRAM) {
-- brcmf_fw_request_nvram_done(NULL, fwctx);
-- } else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) {
-+ if (!fw)
- ret = -ENOENT;
-+
-+ switch (cur->type) {
-+ case BRCMF_FW_TYPE_NVRAM:
-+ ret = brcmf_fw_request_nvram_done(fw, fwctx);
-+ break;
-+ case BRCMF_FW_TYPE_BINARY:
-+ cur->binary = fw;
-+ break;
-+ default:
-+ /* something fishy here so bail out early */
-+ brcmf_err("unknown fw type: %d\n", cur->type);
-+ release_firmware(fw);
-+ ret = -EINVAL;
- goto fail;
- }
-
-+ if (ret < 0 && !(cur->flags & BRCMF_FW_REQF_OPTIONAL))
-+ goto fail;
-+
- do {
- if (++fwctx->curpos == fwctx->req->n_items) {
- ret = 0;
+++ /dev/null
-From 1f589e2510d5df1192dca7c089103a2cbd028101 Mon Sep 17 00:00:00 2001
-From: Dan Haab <dhaab@luxul.com>
-Date: Tue, 3 Apr 2018 10:21:56 +0200
-Subject: [PATCH] brcmfmac: add support for BCM4366E chipset
-
-BCM4366E is a wireless chipset with a BCM43664 ChipCommon. It's
-supported by the same firmware as 4366c0.
-
-Signed-off-by: Dan Haab <dan.haab@luxul.com>
-[arend: rebase patch and remove unnecessary definition]
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 1 +
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 1 +
- drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
-@@ -689,6 +689,7 @@ static u32 brcmf_chip_tcm_rambase(struct
- case BRCM_CC_43525_CHIP_ID:
- case BRCM_CC_4365_CHIP_ID:
- case BRCM_CC_4366_CHIP_ID:
-+ case BRCM_CC_43664_CHIP_ID:
- return 0x200000;
- case CY_CC_4373_CHIP_ID:
- return 0x160000;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -75,6 +75,7 @@ static struct brcmf_firmware_mapping brc
- BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C),
- BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B),
- BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C),
-+ BRCMF_FW_ENTRY(BRCM_CC_43664_CHIP_ID, 0xFFFFFFF0, 4366C),
- BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
- };
-
---- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
-@@ -57,6 +57,7 @@
- #define BRCM_CC_43602_CHIP_ID 43602
- #define BRCM_CC_4365_CHIP_ID 0x4365
- #define BRCM_CC_4366_CHIP_ID 0x4366
-+#define BRCM_CC_43664_CHIP_ID 43664
- #define BRCM_CC_4371_CHIP_ID 0x4371
- #define CY_CC_4373_CHIP_ID 0x4373
-
+++ /dev/null
-From cb746e47837ad0f35c8ae28e9aacc8eb07916d2a Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 26 Apr 2018 12:16:47 +0200
-Subject: [PATCH] brcmfmac: check p2pdev mac address uniqueness
-
-The mac address for p2pdev must be different from the primary interface
-due to firmware requirement. Add an explicit check for this requirement
-if user-space provides a mac address.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
-@@ -2073,6 +2073,13 @@ static struct wireless_dev *brcmf_p2p_cr
- }
-
- pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
-+
-+ /* firmware requires unique mac address for p2pdev interface */
-+ if (addr && ether_addr_equal(addr, pri_ifp->mac_addr)) {
-+ brcmf_err("discovery vif must be different from primary interface\n");
-+ return ERR_PTR(-EINVAL);
-+ }
-+
- brcmf_p2p_generate_bss_mac(p2p, addr);
- brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
-
+++ /dev/null
-From 7742fce4c007141617dab9bcb90034b3c0fe2347 Mon Sep 17 00:00:00 2001
-From: Franky Lin <franky.lin@broadcom.com>
-Date: Thu, 26 Apr 2018 12:18:35 +0200
-Subject: [PATCH] brcmfmac: reports boottime_ns while informing bss
-
-Provides a timestamp in bss information so user space can see when the
-bss info was updated. Since tsf is not available from the dongle events
-boottime is reported instead.
-
-Reported-by: Dmitry Shmidt <dimitrysh@google.com>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 26 +++++++++++-----------
- 1 file changed, 13 insertions(+), 13 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2728,7 +2728,6 @@ static s32 brcmf_inform_single_bss(struc
- struct brcmf_bss_info_le *bi)
- {
- struct wiphy *wiphy = cfg_to_wiphy(cfg);
-- struct ieee80211_channel *notify_channel;
- struct cfg80211_bss *bss;
- struct ieee80211_supported_band *band;
- struct brcmu_chan ch;
-@@ -2738,7 +2737,7 @@ static s32 brcmf_inform_single_bss(struc
- u16 notify_interval;
- u8 *notify_ie;
- size_t notify_ielen;
-- s32 notify_signal;
-+ struct cfg80211_inform_bss bss_data = { 0 };
-
- if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
- brcmf_err("Bss info is larger than buffer. Discarding\n");
-@@ -2758,27 +2757,28 @@ static s32 brcmf_inform_single_bss(struc
- band = wiphy->bands[NL80211_BAND_5GHZ];
-
- freq = ieee80211_channel_to_frequency(channel, band->band);
-- notify_channel = ieee80211_get_channel(wiphy, freq);
-+ bss_data.chan = ieee80211_get_channel(wiphy, freq);
-+ bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20;
-+ bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime());
-
- notify_capability = le16_to_cpu(bi->capability);
- notify_interval = le16_to_cpu(bi->beacon_period);
- notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
- notify_ielen = le32_to_cpu(bi->ie_length);
-- notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
-+ bss_data.signal = (s16)le16_to_cpu(bi->RSSI) * 100;
-
- brcmf_dbg(CONN, "bssid: %pM\n", bi->BSSID);
- brcmf_dbg(CONN, "Channel: %d(%d)\n", channel, freq);
- brcmf_dbg(CONN, "Capability: %X\n", notify_capability);
- brcmf_dbg(CONN, "Beacon interval: %d\n", notify_interval);
-- brcmf_dbg(CONN, "Signal: %d\n", notify_signal);
-+ brcmf_dbg(CONN, "Signal: %d\n", bss_data.signal);
-
-- bss = cfg80211_inform_bss(wiphy, notify_channel,
-- CFG80211_BSS_FTYPE_UNKNOWN,
-- (const u8 *)bi->BSSID,
-- 0, notify_capability,
-- notify_interval, notify_ie,
-- notify_ielen, notify_signal,
-- GFP_KERNEL);
-+ bss = cfg80211_inform_bss_data(wiphy, &bss_data,
-+ CFG80211_BSS_FTYPE_UNKNOWN,
-+ (const u8 *)bi->BSSID,
-+ 0, notify_capability,
-+ notify_interval, notify_ie,
-+ notify_ielen, GFP_KERNEL);
-
- if (!bss)
- return -ENOMEM;
+++ /dev/null
-From aed14219067ab96e5eeb7730e9bceed10d9be989 Mon Sep 17 00:00:00 2001
-From: Franky Lin <franky.lin@broadcom.com>
-Date: Thu, 26 Apr 2018 12:16:48 +0200
-Subject: [PATCH] brcmfmac: use nl80211_band directly to get ieee80211 channel
-
-The enum nl80211_band used to retrieve wiphy->bands is the same as
-wiphy->bands->band which is checked by wiphy_register(). So it can be used
-directly as parameter of ieee80211_channel_to_frequency().
-
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2729,7 +2729,7 @@ static s32 brcmf_inform_single_bss(struc
- {
- struct wiphy *wiphy = cfg_to_wiphy(cfg);
- struct cfg80211_bss *bss;
-- struct ieee80211_supported_band *band;
-+ enum nl80211_band band;
- struct brcmu_chan ch;
- u16 channel;
- u32 freq;
-@@ -2752,11 +2752,11 @@ static s32 brcmf_inform_single_bss(struc
- channel = bi->ctl_ch;
-
- if (channel <= CH_MAX_2G_CHANNEL)
-- band = wiphy->bands[NL80211_BAND_2GHZ];
-+ band = NL80211_BAND_2GHZ;
- else
-- band = wiphy->bands[NL80211_BAND_5GHZ];
-+ band = NL80211_BAND_5GHZ;
-
-- freq = ieee80211_channel_to_frequency(channel, band->band);
-+ freq = ieee80211_channel_to_frequency(channel, band);
- bss_data.chan = ieee80211_get_channel(wiphy, freq);
- bss_data.scan_width = NL80211_BSS_CHAN_WIDTH_20;
- bss_data.boottime_ns = ktime_to_ns(ktime_get_boottime());
+++ /dev/null
-From ff68c9f9c06d1fd437c8f90fc05ca28c47f7d85e Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Thu, 26 Apr 2018 12:16:49 +0200
-Subject: [PATCH] brcmfmac: constify firmware mapping tables
-
-The information in the firmware mapping does not need to be modified
-so it can be static const.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c | 2 +-
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h | 2 +-
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 2 +-
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 2 +-
- 5 files changed, 5 insertions(+), 5 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -634,7 +634,7 @@ int brcmf_fw_get_firmwares(struct device
-
- struct brcmf_fw_request *
- brcmf_fw_alloc_request(u32 chip, u32 chiprev,
-- struct brcmf_firmware_mapping mapping_table[],
-+ const struct brcmf_firmware_mapping mapping_table[],
- u32 table_size, struct brcmf_fw_name *fwnames,
- u32 n_fwnames)
- {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
-@@ -80,7 +80,7 @@ struct brcmf_fw_name {
-
- struct brcmf_fw_request *
- brcmf_fw_alloc_request(u32 chip, u32 chiprev,
-- struct brcmf_firmware_mapping mapping_table[],
-+ const struct brcmf_firmware_mapping mapping_table[],
- u32 table_size, struct brcmf_fw_name *fwnames,
- u32 n_fwnames);
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -59,7 +59,7 @@ BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie"
- BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie");
- BRCMF_FW_DEF(4371, "brcmfmac4371-pcie");
-
--static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
-+static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
- BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
- BRCMF_FW_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C),
- BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C),
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -619,7 +619,7 @@ BRCMF_FW_DEF(4354, "brcmfmac4354-sdio");
- BRCMF_FW_DEF(4356, "brcmfmac4356-sdio");
- BRCMF_FW_DEF(4373, "brcmfmac4373-sdio");
-
--static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
-+static const struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
- BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
- BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
- BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
-@@ -52,7 +52,7 @@ BRCMF_FW_DEF(43242A, "brcmfmac43242a");
- BRCMF_FW_DEF(43569, "brcmfmac43569");
- BRCMF_FW_DEF(4373, "brcmfmac4373");
-
--static struct brcmf_firmware_mapping brcmf_usb_fwnames[] = {
-+static const struct brcmf_firmware_mapping brcmf_usb_fwnames[] = {
- BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
- BRCMF_FW_ENTRY(BRCM_CC_43235_CHIP_ID, 0x00000008, 43236B),
- BRCMF_FW_ENTRY(BRCM_CC_43236_CHIP_ID, 0x00000008, 43236B),
+++ /dev/null
-From 84ad327d18debe19b8d509059b61db445d048b02 Mon Sep 17 00:00:00 2001
-From: Franky Lin <franky.lin@broadcom.com>
-Date: Thu, 26 Apr 2018 12:16:50 +0200
-Subject: [PATCH] brcmfmac: add hostready indication
-
-A hostready signal is introduced to inform firmware through mailbox
-doorbell1 when common ring initialized or D3 exited.
-
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 14 ++++++++++++--
- 1 file changed, 12 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -105,7 +105,8 @@ static const struct brcmf_firmware_mappi
- #define BRCMF_PCIE_PCIE2REG_MAILBOXMASK 0x4C
- #define BRCMF_PCIE_PCIE2REG_CONFIGADDR 0x120
- #define BRCMF_PCIE_PCIE2REG_CONFIGDATA 0x124
--#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX 0x140
-+#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0 0x140
-+#define BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1 0x144
-
- #define BRCMF_PCIE2_INTA 0x01
- #define BRCMF_PCIE2_INTB 0x02
-@@ -140,6 +141,7 @@ static const struct brcmf_firmware_mappi
- #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_SHARED_HOSTRDY_DB1 0x10000000
-
- #define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000
- #define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000
-@@ -782,6 +784,12 @@ static void brcmf_pcie_intr_enable(struc
- BRCMF_PCIE_MB_INT_FN0_1);
- }
-
-+static void brcmf_pcie_hostready(struct brcmf_pciedev_info *devinfo)
-+{
-+ if (devinfo->shared.flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1)
-+ brcmf_pcie_write_reg32(devinfo,
-+ BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_1, 1);
-+}
-
- static irqreturn_t brcmf_pcie_quick_check_isr(int irq, void *arg)
- {
-@@ -924,7 +932,7 @@ static int brcmf_pcie_ring_mb_ring_bell(
-
- brcmf_dbg(PCIE, "RING !\n");
- /* Any arbitrary value will do, lets use 1 */
-- brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX, 1);
-+ brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_H2D_MAILBOX_0, 1);
-
- return 0;
- }
-@@ -1728,6 +1736,7 @@ static void brcmf_pcie_setup(struct devi
- init_waitqueue_head(&devinfo->mbdata_resp_wait);
-
- brcmf_pcie_intr_enable(devinfo);
-+ brcmf_pcie_hostready(devinfo);
- if (brcmf_attach(&devinfo->pdev->dev, devinfo->settings) == 0)
- return;
-
-@@ -1950,6 +1959,7 @@ static int brcmf_pcie_pm_leave_D3(struct
- brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
- brcmf_bus_change_state(bus, BRCMF_BUS_UP);
- brcmf_pcie_intr_enable(devinfo);
-+ brcmf_pcie_hostready(devinfo);
- return 0;
- }
-
+++ /dev/null
-From f56324baf329bc9362a52ad77a4a1a0f3356d1bc Mon Sep 17 00:00:00 2001
-From: Franky Lin <franky.lin@broadcom.com>
-Date: Thu, 26 Apr 2018 12:16:51 +0200
-Subject: [PATCH] brcmfmac: coarse support for PCIe shared structure rev7
-
-Revision 7 of PCIe dongle interface increases the item size of tx and rx
-complete rings to accommodate extra payload for new feature. This patch
-simply bump up the size of these two rings without adding the support
-for utilizing the new space. This makes brcmfmac compatible with rev7
-firmware.
-
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | 6 ++++--
- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 23 ++++++++++++++++++----
- 2 files changed, 23 insertions(+), 6 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
-@@ -27,8 +27,10 @@
- #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE 40
- #define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE 32
- #define BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE 24
--#define BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE 16
--#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE 32
-+#define BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE_PRE_V7 16
-+#define BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE 24
-+#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE_PRE_V7 32
-+#define BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE 40
- #define BRCMF_H2D_TXFLOWRING_ITEMSIZE 48
-
- struct msgbuf_buf_addr {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -136,8 +136,9 @@ static const struct brcmf_firmware_mappi
- BRCMF_PCIE_MB_INT_D2H3_DB0 | \
- BRCMF_PCIE_MB_INT_D2H3_DB1)
-
-+#define BRCMF_PCIE_SHARED_VERSION_7 7
- #define BRCMF_PCIE_MIN_SHARED_VERSION 5
--#define BRCMF_PCIE_MAX_SHARED_VERSION 6
-+#define BRCMF_PCIE_MAX_SHARED_VERSION BRCMF_PCIE_SHARED_VERSION_7
- #define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF
- #define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000
- #define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000
-@@ -318,6 +319,14 @@ static const u32 brcmf_ring_max_item[BRC
- BRCMF_D2H_MSGRING_RX_COMPLETE_MAX_ITEM
- };
-
-+static const u32 brcmf_ring_itemsize_pre_v7[BRCMF_NROF_COMMON_MSGRINGS] = {
-+ BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,
-+ BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,
-+ BRCMF_D2H_MSGRING_CONTROL_COMPLETE_ITEMSIZE,
-+ BRCMF_D2H_MSGRING_TX_COMPLETE_ITEMSIZE_PRE_V7,
-+ BRCMF_D2H_MSGRING_RX_COMPLETE_ITEMSIZE_PRE_V7
-+};
-+
- static const u32 brcmf_ring_itemsize[BRCMF_NROF_COMMON_MSGRINGS] = {
- BRCMF_H2D_MSGRING_CONTROL_SUBMIT_ITEMSIZE,
- BRCMF_H2D_MSGRING_RXPOST_SUBMIT_ITEMSIZE,
-@@ -1007,8 +1016,14 @@ brcmf_pcie_alloc_dma_and_ring(struct brc
- struct brcmf_pcie_ringbuf *ring;
- u32 size;
- u32 addr;
-+ const u32 *ring_itemsize_array;
-+
-+ if (devinfo->shared.version < BRCMF_PCIE_SHARED_VERSION_7)
-+ ring_itemsize_array = brcmf_ring_itemsize_pre_v7;
-+ else
-+ ring_itemsize_array = brcmf_ring_itemsize;
-
-- size = brcmf_ring_max_item[ring_id] * brcmf_ring_itemsize[ring_id];
-+ size = brcmf_ring_max_item[ring_id] * ring_itemsize_array[ring_id];
- dma_buf = brcmf_pcie_init_dmabuffer_for_device(devinfo, size,
- tcm_ring_phys_addr + BRCMF_RING_MEM_BASE_ADDR_OFFSET,
- &dma_handle);
-@@ -1018,7 +1033,7 @@ brcmf_pcie_alloc_dma_and_ring(struct brc
- addr = tcm_ring_phys_addr + BRCMF_RING_MAX_ITEM_OFFSET;
- brcmf_pcie_write_tcm16(devinfo, addr, brcmf_ring_max_item[ring_id]);
- addr = tcm_ring_phys_addr + BRCMF_RING_LEN_ITEMS_OFFSET;
-- brcmf_pcie_write_tcm16(devinfo, addr, brcmf_ring_itemsize[ring_id]);
-+ brcmf_pcie_write_tcm16(devinfo, addr, ring_itemsize_array[ring_id]);
-
- ring = kzalloc(sizeof(*ring), GFP_KERNEL);
- if (!ring) {
-@@ -1027,7 +1042,7 @@ brcmf_pcie_alloc_dma_and_ring(struct brc
- return NULL;
- }
- brcmf_commonring_config(&ring->commonring, brcmf_ring_max_item[ring_id],
-- brcmf_ring_itemsize[ring_id], dma_buf);
-+ ring_itemsize_array[ring_id], dma_buf);
- ring->dma_handle = dma_handle;
- ring->devinfo = devinfo;
- brcmf_commonring_register_cb(&ring->commonring,
+++ /dev/null
-From 9c4a121e82634aa000a702c98cd6f05b27d6e186 Mon Sep 17 00:00:00 2001
-From: Sean Lanigan <sean@lano.id.au>
-Date: Fri, 4 May 2018 16:48:23 +1000
-Subject: [PATCH] brcmfmac: Add support for bcm43364 wireless chipset
-
-Add support for the BCM43364 chipset via an SDIO interface, as used in
-e.g. the Murata 1FX module.
-
-The BCM43364 uses the same firmware as the BCM43430 (which is already
-included), the only difference is the omission of Bluetooth.
-
-However, the SDIO_ID for the BCM43364 is 02D0:A9A4, giving it a MODALIAS
-of sdio:c00v02D0dA9A4, which doesn't get recognised and hence doesn't
-load the brcmfmac module. Adding the 'A9A4' ID in the appropriate place
-triggers the brcmfmac driver to load, and then correctly use the
-firmware file 'brcmfmac43430-sdio.bin'.
-
-Signed-off-by: Sean Lanigan <sean@lano.id.au>
-Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 1 +
- include/linux/mmc/sdio_ids.h | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -963,6 +963,7 @@ static const struct sdio_device_id brcmf
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43340),
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341),
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362),
-+ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43364),
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339),
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339),
- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430),
---- a/include/linux/mmc/sdio_ids.h
-+++ b/include/linux/mmc/sdio_ids.h
-@@ -34,6 +34,7 @@
- #define SDIO_DEVICE_ID_BROADCOM_4335_4339 0x4335
- #define SDIO_DEVICE_ID_BROADCOM_4339 0x4339
- #define SDIO_DEVICE_ID_BROADCOM_43362 0xa962
-+#define SDIO_DEVICE_ID_BROADCOM_43364 0xa9a4
- #define SDIO_DEVICE_ID_BROADCOM_43430 0xa9a6
- #define SDIO_DEVICE_ID_BROADCOM_4345 0x4345
- #define SDIO_DEVICE_ID_BROADCOM_43455 0xa9bf
+++ /dev/null
-From 1204aa17f3b4f63e67ac9b7c9afa9496485969c5 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 10 May 2018 15:21:39 +0200
-Subject: [PATCH] brcmfmac: set WIPHY_FLAG_HAVE_AP_SME flag
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-brcmfmac is a FullMAC driver and it implements/uses cfg80211 interface
-for stations management. At the same time it doesn't receive or pass up
-management frames.
-
-This flag indicates that authenticator doesn't have to subscribe to or
-handle management frames. Some authenticators (e.g. hostapd) were
-working with brcmfmac thanks to some extra assumptions. This commit
-clears up the situation.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -6513,6 +6513,7 @@ static int brcmf_setup_wiphy(struct wiph
-
- wiphy->flags |= WIPHY_FLAG_NETNS_OK |
- WIPHY_FLAG_PS_ON_BY_DEFAULT |
-+ WIPHY_FLAG_HAVE_AP_SME |
- WIPHY_FLAG_OFFCHAN_TX |
- WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS))
+++ /dev/null
-From 763ece85f45a6b93268e25a0abf02922f911dab4 Mon Sep 17 00:00:00 2001
-From: Franky Lin <franky.lin@broadcom.com>
-Date: Tue, 15 May 2018 11:14:44 +0200
-Subject: [PATCH] brcmfmac: fix initialization of struct cfg80211_inform_bss
- variable
-
-This patch fixes a sparse warning "Using plain integer as NULL pointer"
-about cfg80211_inform_bss structure initialization.
-
-Reported-by: kbuild test robot <lkp@intel.com>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2737,7 +2737,7 @@ static s32 brcmf_inform_single_bss(struc
- u16 notify_interval;
- u8 *notify_ie;
- size_t notify_ielen;
-- struct cfg80211_inform_bss bss_data = { 0 };
-+ struct cfg80211_inform_bss bss_data = {};
-
- if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
- brcmf_err("Bss info is larger than buffer. Discarding\n");
+++ /dev/null
-From 88001968245c42c26416476bf0ef960442371605 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Mon, 14 May 2018 08:48:20 +0200
-Subject: [PATCH] brcmfmac: add debugfs entry for reading firmware capabilities
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This allows reading all capabilities as reported by a firmware. They are
-printed using native (raw) names, just like developers like it the most.
-It's how firmware reports support for various features, e.g. supported
-modes, supported standards, power saving details, max BSS-es.
-
-Access to all that info is useful for trying new firmwares, comparing
-them and debugging features AKA bugs.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/feature.c | 36 ++++++++++++++++++++++
- 1 file changed, 36 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-@@ -165,6 +165,41 @@ static void brcmf_feat_firmware_capabili
- }
- }
-
-+/**
-+ * brcmf_feat_fwcap_debugfs_read() - expose firmware capabilities to debugfs.
-+ *
-+ * @seq: sequence for debugfs entry.
-+ * @data: raw data pointer.
-+ */
-+static int brcmf_feat_fwcap_debugfs_read(struct seq_file *seq, void *data)
-+{
-+ struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
-+ struct brcmf_if *ifp = brcmf_get_ifp(bus_if->drvr, 0);
-+ char caps[MAX_CAPS_BUFFER_SIZE + 1] = { };
-+ char *tmp;
-+ int err;
-+
-+ err = brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
-+ if (err) {
-+ brcmf_err("could not get firmware cap (%d)\n", err);
-+ return err;
-+ }
-+
-+ /* Put every capability in a new line */
-+ for (tmp = caps; *tmp; tmp++) {
-+ if (*tmp == ' ')
-+ *tmp = '\n';
-+ }
-+
-+ /* Usually there is a space at the end of capabilities string */
-+ seq_printf(seq, "%s", caps);
-+ /* So make sure we don't print two line breaks */
-+ if (tmp > caps && *(tmp - 1) != '\n')
-+ seq_printf(seq, "\n");
-+
-+ return 0;
-+}
-+
- void brcmf_feat_attach(struct brcmf_pub *drvr)
- {
- struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
-@@ -233,6 +268,7 @@ void brcmf_feat_attach(struct brcmf_pub
- void brcmf_feat_debugfs_create(struct brcmf_pub *drvr)
- {
- brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read);
-+ brcmf_debugfs_add_entry(drvr, "fwcap", brcmf_feat_fwcap_debugfs_read);
- }
-
- bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id)
+++ /dev/null
-From f8793c26fe586659d6da3fa277e63961a69d314b Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 16 May 2018 14:11:58 +0200
-Subject: [PATCH] brcmfmac: move ALLFFMAC variable in flowring module
-
-The only user of ALLFFMAC is the flowring module so no need to
-expose it in a header file.
-
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c | 2 --
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h | 2 --
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c | 2 ++
- 3 files changed, 2 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -36,8 +36,6 @@ MODULE_AUTHOR("Broadcom Corporation");
- MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver.");
- MODULE_LICENSE("Dual BSD/GPL");
-
--const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
--
- #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
- #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
-@@ -19,8 +19,6 @@
- #include <linux/platform_data/brcmfmac.h>
- #include "fwil_types.h"
-
--extern const u8 ALLFFMAC[ETH_ALEN];
--
- #define BRCMF_FW_ALTPATH_LEN 256
-
- /* Definitions for the module global and device specific settings are defined
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
-@@ -46,6 +46,8 @@ static const u8 brcmf_flowring_prio2fifo
- 3
- };
-
-+static const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-+
-
- static bool
- brcmf_flowring_is_tdls_mac(struct brcmf_flowring *flow, u8 mac[ETH_ALEN])
+++ /dev/null
-From 8e072168f75ebce85b96cbcefea2b10ddbd5913f Mon Sep 17 00:00:00 2001
-From: Arend Van Spriel <arend.vanspriel@broadcom.com>
-Date: Wed, 16 May 2018 14:11:59 +0200
-Subject: [PATCH] brcmfmac: add support for sysfs initiated coredump
-
-The driver already supports device coredump initiated by firmware
-event. Since commit 3c47d19ff4dc ("drivers: base: add coredump driver
-ops") it is also possible to initiate it from user-space through
-sysfs. This patch adds support for SDIO and PCIe devices.
-
-[rafal@milecki.pl: use LINUX_VERSION_CODE]
-Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
-Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
-Reviewed-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 1 +
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 2 ++
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 8 ++++++++
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 1 +
- 4 files changed, 12 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
-@@ -1165,6 +1165,9 @@ static struct sdio_driver brcmf_sdmmc_dr
- #ifdef CONFIG_PM_SLEEP
- .pm = &brcmf_sdio_pm_ops,
- #endif /* CONFIG_PM_SLEEP */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
-+ .coredump = brcmf_dev_coredump,
-+#endif
- },
- };
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
-@@ -250,6 +250,8 @@ int brcmf_attach(struct device *dev, str
- void brcmf_detach(struct device *dev);
- /* Indication from bus module that dongle should be reset */
- void brcmf_dev_reset(struct device *dev);
-+/* Request from bus module to initiate a coredump */
-+void brcmf_dev_coredump(struct device *dev);
-
- /* Configure the "global" bus state used by upper layers */
- void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1201,6 +1201,14 @@ void brcmf_dev_reset(struct device *dev)
- brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
- }
-
-+void brcmf_dev_coredump(struct device *dev)
-+{
-+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-+
-+ if (brcmf_debug_create_memdump(bus_if, NULL, 0) < 0)
-+ brcmf_dbg(TRACE, "failed to create coredump\n");
-+}
-+
- void brcmf_detach(struct device *dev)
- {
- s32 i;
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -2044,6 +2044,9 @@ static struct pci_driver brcmf_pciedrvr
- #ifdef CONFIG_PM
- .driver.pm = &brcmf_pciedrvr_pm,
- #endif
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
-+ .driver.coredump = brcmf_dev_coredump,
-+#endif
- };
-
-
+++ /dev/null
-From d2af9b566554e01f9ad67b330ce569dbc130e5d3 Mon Sep 17 00:00:00 2001
-From: Franky Lin <franky.lin@broadcom.com>
-Date: Wed, 16 May 2018 14:12:01 +0200
-Subject: [PATCH] brcmfmac: validate user provided data for memdump before
- copying
-
-In patch "brcmfmac: add support for sysfs initiated coredump", a new
-scenario of brcmf_debug_create_memdump was added in which the user of
-the function might not necessarily provide prefix data. Hence the
-function should not assume the data is always valid and should perform a
-check before copying.
-
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
-@@ -40,7 +40,8 @@ int brcmf_debug_create_memdump(struct br
- if (!dump)
- return -ENOMEM;
-
-- memcpy(dump, data, len);
-+ if (data && len > 0)
-+ memcpy(dump, data, len);
- err = brcmf_bus_get_memdump(bus, dump + len, ramsize);
- if (err) {
- vfree(dump);
+++ /dev/null
-From 8a3ab2f38f1669e3be6433a1f6b82a077b38c4c7 Mon Sep 17 00:00:00 2001
-From: Franky Lin <franky.lin@broadcom.com>
-Date: Wed, 16 May 2018 14:12:02 +0200
-Subject: [PATCH] brcmfmac: trigger memory dump upon firmware halt signal
-
-PCIe dongle firmware signals a halt/trap through mailbox interrupt.
-Trigger a memory dump upon receiving such signal could help to provide
-useful information for issue debug.
-
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -182,6 +182,7 @@ static const struct brcmf_firmware_mappi
- #define BRCMF_D2H_DEV_D3_ACK 0x00000001
- #define BRCMF_D2H_DEV_DS_ENTER_REQ 0x00000002
- #define BRCMF_D2H_DEV_DS_EXIT_NOTE 0x00000004
-+#define BRCMF_D2H_DEV_FWHALT 0x10000000
-
- #define BRCMF_H2D_HOST_D3_INFORM 0x00000001
- #define BRCMF_H2D_HOST_DS_ACK 0x00000002
-@@ -717,6 +718,10 @@ static void brcmf_pcie_handle_mb_data(st
- devinfo->mbdata_completed = true;
- wake_up(&devinfo->mbdata_resp_wait);
- }
-+ if (dtoh_mb_data & BRCMF_D2H_DEV_FWHALT) {
-+ brcmf_dbg(PCIE, "D2H_MB_DATA: FW HALT\n");
-+ brcmf_dev_coredump(&devinfo->pdev->dev);
-+ }
- }
-
-
+++ /dev/null
-From b8248236e92790ac635caeb4156e46ea2417e037 Mon Sep 17 00:00:00 2001
-From: Franky Lin <franky.lin@broadcom.com>
-Date: Wed, 16 May 2018 14:12:03 +0200
-Subject: [PATCH] brcmfmac: trigger memory dump on SDIO firmware halt message
-
-Attempt to dump dongle memory for debug upon receiving firmware halt
-message through dongle to host mail box interrupt.
-
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Franky Lin <franky.lin@broadcom.com>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -1072,8 +1072,10 @@ static u32 brcmf_sdio_hostmail(struct br
- bus->sdcnt.f1regdata += 2;
-
- /* dongle indicates the firmware has halted/crashed */
-- if (hmb_data & HMB_DATA_FWHALT)
-+ if (hmb_data & HMB_DATA_FWHALT) {
- brcmf_err("mailbox indicates firmware halted\n");
-+ brcmf_dev_coredump(&sdiod->func1->dev);
-+ }
-
- /* Dongle recomposed rx frames, accept them again */
- if (hmb_data & HMB_DATA_NAKHANDLED) {
+++ /dev/null
-From 373c83a801f15b1e3d02d855fad89112bd4ccbe0 Mon Sep 17 00:00:00 2001
-From: Michael Trimarchi <michael@amarulasolutions.com>
-Date: Wed, 30 May 2018 11:06:34 +0200
-Subject: [PATCH] brcmfmac: stop watchdog before detach and free everything
-
-Using built-in in kernel image without a firmware in filesystem
-or in the kernel image can lead to a kernel NULL pointer deference.
-Watchdog need to be stopped in brcmf_sdio_remove
-
-The system is going down NOW!
-[ 1348.110759] Unable to handle kernel NULL pointer dereference at virtual address 000002f8
-Sent SIGTERM to all processes
-[ 1348.121412] Mem abort info:
-[ 1348.126962] ESR = 0x96000004
-[ 1348.130023] Exception class = DABT (current EL), IL = 32 bits
-[ 1348.135948] SET = 0, FnV = 0
-[ 1348.138997] EA = 0, S1PTW = 0
-[ 1348.142154] Data abort info:
-[ 1348.145045] ISV = 0, ISS = 0x00000004
-[ 1348.148884] CM = 0, WnR = 0
-[ 1348.151861] user pgtable: 4k pages, 48-bit VAs, pgdp = (____ptrval____)
-[ 1348.158475] [00000000000002f8] pgd=0000000000000000
-[ 1348.163364] Internal error: Oops: 96000004 [#1] PREEMPT SMP
-[ 1348.168927] Modules linked in: ipv6
-[ 1348.172421] CPU: 3 PID: 1421 Comm: brcmf_wdog/mmc0 Not tainted 4.17.0-rc5-next-20180517 #18
-[ 1348.180757] Hardware name: Amarula A64-Relic (DT)
-[ 1348.185455] pstate: 60000005 (nZCv daif -PAN -UAO)
-[ 1348.190251] pc : brcmf_sdiod_freezer_count+0x0/0x20
-[ 1348.195124] lr : brcmf_sdio_watchdog_thread+0x64/0x290
-[ 1348.200253] sp : ffff00000b85be30
-[ 1348.203561] x29: ffff00000b85be30 x28: 0000000000000000
-[ 1348.208868] x27: ffff00000b6cb918 x26: ffff80003b990638
-[ 1348.214176] x25: ffff0000087b1a20 x24: ffff80003b94f800
-[ 1348.219483] x23: ffff000008e620c8 x22: ffff000008f0b660
-[ 1348.224790] x21: ffff000008c6a858 x20: 00000000fffffe00
-[ 1348.230097] x19: ffff80003b94f800 x18: 0000000000000001
-[ 1348.235404] x17: 0000ffffab2e8a74 x16: ffff0000080d7de8
-[ 1348.240711] x15: 0000000000000000 x14: 0000000000000400
-[ 1348.246018] x13: 0000000000000400 x12: 0000000000000001
-[ 1348.251324] x11: 00000000000002c4 x10: 0000000000000a10
-[ 1348.256631] x9 : ffff00000b85bc40 x8 : ffff80003be11870
-[ 1348.261937] x7 : ffff80003dfc7308 x6 : 000000078ff08b55
-[ 1348.267243] x5 : 00000139e1058400 x4 : 0000000000000000
-[ 1348.272550] x3 : dead000000000100 x2 : 958f2788d6618100
-[ 1348.277856] x1 : 00000000fffffe00 x0 : 0000000000000000
-
-Signed-off-by: Michael Trimarchi <michael@amarulasolutions.com>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Tested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
-@@ -4297,6 +4297,13 @@ void brcmf_sdio_remove(struct brcmf_sdio
- brcmf_dbg(TRACE, "Enter\n");
-
- if (bus) {
-+ /* Stop watchdog task */
-+ if (bus->watchdog_tsk) {
-+ send_sig(SIGTERM, bus->watchdog_tsk, 1);
-+ kthread_stop(bus->watchdog_tsk);
-+ bus->watchdog_tsk = NULL;
-+ }
-+
- /* De-register interrupt handler */
- brcmf_sdiod_intr_unregister(bus->sdiodev);
-
+++ /dev/null
-From 299b6365a3b7cf7f5ea1c945a420e9ee4841d6f7 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Sun, 22 Jul 2018 23:46:25 +0200
-Subject: [PATCH] brcmfmac: fix regression in parsing NVRAM for multiple
- devices
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-NVRAM is designed to work with Broadcom's SDK Linux kernel which fakes
-PCI domain 0 for all internal MMIO devices. Since official Linux kernel
-uses platform devices for that purpose there is a mismatch in numbering
-PCI domains.
-
-There used to be a fix for that problem but it was accidentally dropped
-during the last firmware loading rework. That resulted in brcmfmac not
-being able to extract device specific NVRAM content and all kind of
-calibration problems.
-
-Reported-by: Aditya Xavier <adityaxavier@gmail.com>
-Fixes: 2baa3aaee27f ("brcmfmac: introduce brcmf_fw_alloc_request() function")
-Cc: stable@vger.kernel.org # v4.17+
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
-@@ -1785,7 +1785,8 @@ brcmf_pcie_prepare_fw_request(struct brc
- fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY;
- fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM;
- fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL;
-- fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus);
-+ /* NVRAM reserves PCI domain 0 for Broadcom's SDK faked bus */
-+ fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus) + 1;
- fwreq->bus_nr = devinfo->pdev->bus->number;
-
- return fwreq;
+++ /dev/null
-From 01f69dfafdbe7deff58b58053bc3a4a75c6a570c Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Sun, 24 Jun 2018 21:44:35 +0200
-Subject: [PATCH] brcmfmac: detect firmware support for monitor interface
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Many/most of firmwares support creating monitor interface but only the
-most recent ones explicitly /announce/ it using a "monitor" entry in the
-list of capabilities.
-
-Check for that entry and store internally info about monitor mode
-support using a new feature flag. Once we sort out all details of
-handling monitor interface it will be used when reporting available
-interfaces to the cfg80211.
-
-Later some fallback detecion method may be added for older firmwares.
-For now just stick to the "monitor" capability which should be 100%
-reliable.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 1 +
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h | 4 +++-
- 2 files changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-@@ -48,6 +48,7 @@ static const struct brcmf_feat_fwcap brc
- { BRCMF_FEAT_MBSS, "mbss" },
- { BRCMF_FEAT_MCHAN, "mchan" },
- { BRCMF_FEAT_P2P, "p2p" },
-+ { BRCMF_FEAT_MONITOR, "monitor" },
- };
-
- #ifdef DEBUG
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
-@@ -33,6 +33,7 @@
- * MFP: 802.11w Management Frame Protection.
- * GSCAN: enhanced scan offload feature.
- * FWSUP: Firmware supplicant.
-+ * MONITOR: firmware can pass monitor packets to host.
- */
- #define BRCMF_FEAT_LIST \
- BRCMF_FEAT_DEF(MBSS) \
-@@ -48,7 +49,8 @@
- BRCMF_FEAT_DEF(WOWL_ARP_ND) \
- BRCMF_FEAT_DEF(MFP) \
- BRCMF_FEAT_DEF(GSCAN) \
-- BRCMF_FEAT_DEF(FWSUP)
-+ BRCMF_FEAT_DEF(FWSUP) \
-+ BRCMF_FEAT_DEF(MONITOR)
-
- /*
- * Quirks:
+++ /dev/null
-From e63410ac65e0ead2040bbd3927c116889edf87e4 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Sun, 24 Jun 2018 21:44:36 +0200
-Subject: [PATCH] brcmfmac: detect firmware support for radiotap monitor frames
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Depending on used build-time options some firmwares may already include
-radiotap header in passed monitor frames. Add a new feature flag to
-store info about it. It's needed for proper handling of received frames
-before passing them up.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 1 +
- drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h | 4 +++-
- 2 files changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-@@ -49,6 +49,7 @@ static const struct brcmf_feat_fwcap brc
- { BRCMF_FEAT_MCHAN, "mchan" },
- { BRCMF_FEAT_P2P, "p2p" },
- { BRCMF_FEAT_MONITOR, "monitor" },
-+ { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
- };
-
- #ifdef DEBUG
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
-@@ -34,6 +34,7 @@
- * GSCAN: enhanced scan offload feature.
- * FWSUP: Firmware supplicant.
- * MONITOR: firmware can pass monitor packets to host.
-+ * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
- */
- #define BRCMF_FEAT_LIST \
- BRCMF_FEAT_DEF(MBSS) \
-@@ -50,7 +51,8 @@
- BRCMF_FEAT_DEF(MFP) \
- BRCMF_FEAT_DEF(GSCAN) \
- BRCMF_FEAT_DEF(FWSUP) \
-- BRCMF_FEAT_DEF(MONITOR)
-+ BRCMF_FEAT_DEF(MONITOR) \
-+ BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP)
-
- /*
- * Quirks:
+++ /dev/null
-From a8d7631858aff156b72f807ee7cc062048e63836 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Sun, 24 Jun 2018 21:44:37 +0200
-Subject: [PATCH] brcmfmac: handle msgbuf packets marked with monitor mode flag
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-New Broadcom firmwares mark monitor mode packets using a newly defined
-bit in the flags field. Use it to filter them out and pass to the
-monitor interface. These defines were found in bcmmsgbuf.h from SDK.
-
-As not every firmware generates radiotap header this commit introduces
-BRCMF_FEAT_MONITOR_FMT_RADIOTAP flag. It has to be has based on firmware
-capabilities. If not present brcmf_netif_mon_rx() will assume packet is
-a raw 802.11 frame and will prepend it with an empty radiotap header.
-
-This new code is limited to the msgbuf protocol at this point. Adding
-support for SDIO/USB devices will require some extra work (possibly a
-new firmware release).
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 25 ++++++++++++++++++++++
- .../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 ++
- .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 18 ++++++++++++++++
- 3 files changed, 45 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -21,6 +21,7 @@
- #include <net/cfg80211.h>
- #include <net/rtnetlink.h>
- #include <net/addrconf.h>
-+#include <net/ieee80211_radiotap.h>
- #include <net/ipv6.h>
- #include <brcmu_utils.h>
- #include <brcmu_wifi.h>
-@@ -404,6 +405,30 @@ void brcmf_netif_rx(struct brcmf_if *ifp
- netif_rx_ni(skb);
- }
-
-+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
-+{
-+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {
-+ /* Do nothing */
-+ } else {
-+ struct ieee80211_radiotap_header *radiotap;
-+
-+ /* TODO: use RX status to fill some radiotap data */
-+ radiotap = skb_push(skb, sizeof(*radiotap));
-+ memset(radiotap, 0, sizeof(*radiotap));
-+ radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
-+
-+ /* TODO: 4 bytes with receive status? */
-+ skb->len -= 4;
-+ }
-+
-+ skb->dev = ifp->ndev;
-+ skb_reset_mac_header(skb);
-+ skb->pkt_type = PACKET_OTHERHOST;
-+ skb->protocol = htons(ETH_P_802_2);
-+
-+ brcmf_netif_rx(ifp, skb);
-+}
-+
- static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
- struct brcmf_if **ifp)
- {
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
-@@ -121,6 +121,7 @@ struct brcmf_pub {
-
- struct brcmf_if *iflist[BRCMF_MAX_IFS];
- s32 if2bss[BRCMF_MAX_IFS];
-+ struct brcmf_if *mon_if;
-
- struct mutex proto_block;
- unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
-@@ -216,6 +217,7 @@ void brcmf_txflowblock_if(struct brcmf_i
- enum brcmf_netif_stop_reason reason, bool state);
- 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);
-+void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);
- void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
- int __init brcmf_core_init(void);
- void __exit brcmf_core_exit(void);
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
-@@ -69,6 +69,8 @@
- #define BRCMF_MSGBUF_MAX_EVENTBUF_POST 8
-
- #define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3 0x01
-+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11 0x02
-+#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK 0x07
- #define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT 5
-
- #define BRCMF_MSGBUF_TX_FLUSH_CNT1 32
-@@ -1128,6 +1130,7 @@ brcmf_msgbuf_process_rx_complete(struct
- struct sk_buff *skb;
- u16 data_offset;
- u16 buflen;
-+ u16 flags;
- u32 idx;
- struct brcmf_if *ifp;
-
-@@ -1137,6 +1140,7 @@ brcmf_msgbuf_process_rx_complete(struct
- data_offset = le16_to_cpu(rx_complete->data_offset);
- buflen = le16_to_cpu(rx_complete->data_len);
- idx = le32_to_cpu(rx_complete->msg.request_id);
-+ flags = le16_to_cpu(rx_complete->flags);
-
- skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
- msgbuf->rx_pktids, idx);
-@@ -1150,6 +1154,20 @@ brcmf_msgbuf_process_rx_complete(struct
-
- skb_trim(skb, buflen);
-
-+ if ((flags & BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK) ==
-+ BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11) {
-+ ifp = msgbuf->drvr->mon_if;
-+
-+ if (!ifp) {
-+ brcmf_err("Received unexpected monitor pkt\n");
-+ brcmu_pkt_buf_free_skb(skb);
-+ return;
-+ }
-+
-+ brcmf_netif_mon_rx(ifp, skb);
-+ return;
-+ }
-+
- ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
- if (!ifp || !ifp->ndev) {
- brcmf_err("Received pkt for invalid ifidx %d\n",
+++ /dev/null
-From 4b4a8d808c58fc0defc32a26b2fea35d66692c45 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 28 Jun 2018 08:16:13 +0200
-Subject: [PATCH] brcmfmac: define more bits for the flags of struct
- brcmf_sta_info_le
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-That struct is passed by a firmware when querying for STA info. Flags
-are used to indicate what info could be obtained.
-
-These new defines may allow passing more info to the cfg80211 in the
-future. They had been obtained from Broadcom's SDK file wlioctl_defs.h
-used by DD-WRT.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../broadcom/brcm80211/brcmfmac/fwil_types.h | 29 ++++++++++++++++++----
- 1 file changed, 24 insertions(+), 5 deletions(-)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
-@@ -32,11 +32,30 @@
- #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
- #define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
-
--#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 */
-+#define BRCMF_STA_BRCM 0x00000001 /* Running a Broadcom driver */
-+#define BRCMF_STA_WME 0x00000002 /* WMM association */
-+#define BRCMF_STA_NONERP 0x00000004 /* No ERP */
-+#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
-+#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
-+#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
-+#define BRCMF_STA_WDS 0x00000040 /* Wireless Distribution System */
-+#define BRCMF_STA_WDS_LINKUP 0x00000080 /* WDS traffic/probes flowing properly */
-+#define BRCMF_STA_PS 0x00000100 /* STA is in power save mode from AP's viewpoint */
-+#define BRCMF_STA_APSD_BE 0x00000200 /* APSD delv/trigger for AC_BE is default enabled */
-+#define BRCMF_STA_APSD_BK 0x00000400 /* APSD delv/trigger for AC_BK is default enabled */
-+#define BRCMF_STA_APSD_VI 0x00000800 /* APSD delv/trigger for AC_VI is default enabled */
-+#define BRCMF_STA_APSD_VO 0x00001000 /* APSD delv/trigger for AC_VO is default enabled */
-+#define BRCMF_STA_N_CAP 0x00002000 /* STA 802.11n capable */
-+#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
-+#define BRCMF_STA_AMPDU_CAP 0x00008000 /* STA AMPDU capable */
-+#define BRCMF_STA_AMSDU_CAP 0x00010000 /* STA AMSDU capable */
-+#define BRCMF_STA_MIMO_PS 0x00020000 /* mimo ps mode is enabled */
-+#define BRCMF_STA_MIMO_RTS 0x00040000 /* send rts in mimo ps mode */
-+#define BRCMF_STA_RIFS_CAP 0x00080000 /* rifs enabled */
-+#define BRCMF_STA_VHT_CAP 0x00100000 /* STA VHT(11ac) capable */
-+#define BRCMF_STA_WPS 0x00200000 /* WPS state */
-+#define BRCMF_STA_DWDS_CAP 0x01000000 /* DWDS CAP */
-+#define BRCMF_STA_DWDS 0x02000000 /* DWDS active */
-
- /* size of brcmf_scan_params not including variable length array */
- #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
+++ /dev/null
-From 07b1ae46874949252625c96f309f96ca0f337020 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 28 Jun 2018 12:36:23 +0200
-Subject: [PATCH] brcmfmac: update STA info struct to the v5
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-That struct is used when querying firmware for the STA. It seem is has
-been changing during the time. Luckily its format seems to be backward
-compatible starting with v2 (the only breakage was v1 -> v2).
-
-The version that was supported by brcmfmac so far was v4. It was what
-43602a1 and 4366b1 firmwares (7.35.177.56 and 10.10.69.3309 accordingly)
-were using. It also seems to be used by early 4366c0 firmwares
-(10.10.69.6908 and 10.10.69.69017).
-
-The problem appears when switching to the 10.10.122.20 firmware. It uses
-v5 and instead of falling back to v4 when submitted buffer isn't big
-enough it fallbacks to the v3.
-
-To receive all v4 specific info with the newest firmware we have to
-submit a struct (buffer) that matches v5.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
-@@ -174,6 +174,8 @@
- #define BRCMF_MFP_CAPABLE 1
- #define BRCMF_MFP_REQUIRED 2
-
-+#define BRCMF_VHT_CAP_MCS_MAP_NSS_MAX 8
-+
- /* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each
- * ioctl. It is relatively small because firmware has small maximum size input
- * playload restriction for ioctls.
-@@ -550,6 +552,8 @@ struct brcmf_sta_info_le {
- /* w/hi bit set if basic */
- __le32 in; /* seconds elapsed since associated */
- __le32 listen_interval_inms; /* Min Listen interval in ms for STA */
-+
-+ /* Fields valid for ver >= 3 */
- __le32 tx_pkts; /* # of packets transmitted */
- __le32 tx_failures; /* # of packets failed */
- __le32 rx_ucast_pkts; /* # of unicast packets received */
-@@ -558,6 +562,8 @@ struct brcmf_sta_info_le {
- __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 */
-+
-+ /* Fields valid for ver >= 4 */
- __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 */
-@@ -594,6 +600,14 @@ struct brcmf_sta_info_le {
- */
- __le32 rx_pkts_retried; /* # rx with retry bit set */
- __le32 tx_rate_fallback; /* lowest fallback TX rate */
-+
-+ /* Fields valid for ver >= 5 */
-+ struct {
-+ __le32 count; /* # rates in this set */
-+ u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */
-+ u8 mcs[BRCMF_MCSSET_LEN]; /* supported mcs index bit map */
-+ __le16 vht_mcs[BRCMF_VHT_CAP_MCS_MAP_NSS_MAX]; /* supported mcs index bit map per nss */
-+ } rateset_adv;
- };
-
- struct brcmf_chanspec_list {
+++ /dev/null
-From 1e591c56a65fbbcd5754a4210a0ef0402d5e5f33 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Mon, 9 Jul 2018 06:55:43 +0200
-Subject: [PATCH] brcmfmac: specify some features per firmware version
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Some features supported by firmware aren't advertised and there is no
-way for a driver to query them. This includes e.g. monitor mode details.
-
-Most firmwares support monitor interface but only the latest ones
-/announce/ it with a "monitor" flag in the "cap" iovar. There isn't any
-reliable detection method for older firmwares (BRCMF_C_MONITOR was tried
-but "it only indicates the core part of the stack supports").
-
-Similarly support for tagging monitor frames and building radiotap
-headers can't be reliably detected for all firmwares.
-
-This commit adds table that allows mapping features to firmware version.
-It adds mappings for 43602a1 and 4366b1 firmwares from
-linux-firmware.git. Both were confirmed to be passing monitor frames.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Arend van Spriel <arend.vanspriel@broadcom.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- .../wireless/broadcom/brcm80211/brcmfmac/feature.c | 38 ++++++++++++++++++++++
- 1 file changed, 38 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
-@@ -93,6 +93,42 @@ static int brcmf_feat_debugfs_read(struc
- }
- #endif /* DEBUG */
-
-+struct brcmf_feat_fwfeat {
-+ const char * const fwid;
-+ u32 feat_flags;
-+};
-+
-+static const struct brcmf_feat_fwfeat brcmf_feat_fwfeat_map[] = {
-+ /* brcmfmac43602-pcie.ap.bin from linux-firmware.git commit ea1178515b88 */
-+ { "01-6cb8e269", BIT(BRCMF_FEAT_MONITOR) },
-+ /* brcmfmac4366b-pcie.bin from linux-firmware.git commit 52442afee990 */
-+ { "01-c47a91a4", BIT(BRCMF_FEAT_MONITOR) },
-+};
-+
-+static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv)
-+{
-+ const struct brcmf_feat_fwfeat *e;
-+ u32 feat_flags = 0;
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(brcmf_feat_fwfeat_map); i++) {
-+ e = &brcmf_feat_fwfeat_map[i];
-+ if (!strcmp(e->fwid, drv->fwver)) {
-+ feat_flags = e->feat_flags;
-+ break;
-+ }
-+ }
-+
-+ if (!feat_flags)
-+ return;
-+
-+ for (i = 0; i < BRCMF_FEAT_LAST; i++)
-+ if (feat_flags & BIT(i))
-+ brcmf_dbg(INFO, "enabling firmware feature: %s\n",
-+ brcmf_feat_names[i]);
-+ drv->feat_flags |= feat_flags;
-+}
-+
- /**
- * brcmf_feat_iovar_int_get() - determine feature through iovar query.
- *
-@@ -253,6 +289,8 @@ void brcmf_feat_attach(struct brcmf_pub
- }
- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
-
-+ brcmf_feat_firmware_overrides(drvr);
-+
- /* set chip related quirks */
- switch (drvr->bus_if->chip) {
- case BRCM_CC_43236_CHIP_ID:
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 9 Jul 2016 15:25:24 +0200
-Subject: [PATCH] ath9k_hw: reset AHB-WMAC interface on AR91xx
-
-Should fix a few stability issues
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1394,8 +1394,12 @@ static bool ath9k_hw_set_reset(struct at
- if (!AR_SREV_9100(ah))
- REG_WRITE(ah, AR_RC, 0);
-
-- if (AR_SREV_9100(ah))
-+ if (AR_SREV_9100(ah)) {
-+ /* Reset the AHB-WMAC interface */
-+ if (ah->external_reset)
-+ ah->external_reset();
- udelay(50);
-+ }
-
- return true;
- }
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 9 Jul 2016 15:26:44 +0200
-Subject: [PATCH] ath9k_hw: issue external reset for QCA955x
-
-The RTC interface on the SoC needs to be reset along with the rest of
-the WMAC.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1271,39 +1271,56 @@ void ath9k_hw_get_delta_slope_vals(struc
- *coef_exponent = coef_exp - 16;
- }
-
--/* AR9330 WAR:
-- * call external reset function to reset WMAC if:
-- * - doing a cold reset
-- * - we have pending frames in the TX queues.
-- */
--static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
-+static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type)
- {
-- int i, npend = 0;
-+ int i;
-
-- for (i = 0; i < AR_NUM_QCU; i++) {
-- npend = ath9k_hw_numtxpending(ah, i);
-- if (npend)
-- break;
-- }
--
-- if (ah->external_reset &&
-- (npend || type == ATH9K_RESET_COLD)) {
-- int reset_err = 0;
--
-- ath_dbg(ath9k_hw_common(ah), RESET,
-- "reset MAC via external reset\n");
--
-- reset_err = ah->external_reset();
-- if (reset_err) {
-- ath_err(ath9k_hw_common(ah),
-- "External reset failed, err=%d\n",
-- reset_err);
-- return false;
-+ if (type == ATH9K_RESET_COLD)
-+ return true;
-+
-+ if (AR_SREV_9550(ah))
-+ return true;
-+
-+ /* AR9330 WAR:
-+ * call external reset function to reset WMAC if:
-+ * - doing a cold reset
-+ * - we have pending frames in the TX queues.
-+ */
-+ if (AR_SREV_9330(ah)) {
-+ for (i = 0; i < AR_NUM_QCU; i++) {
-+ if (ath9k_hw_numtxpending(ah, i))
-+ return true;
- }
-+ }
-+
-+ return false;
-+}
-+
-+static bool ath9k_hw_external_reset(struct ath_hw *ah, int type)
-+{
-+ int err;
-+
-+ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type))
-+ return true;
-+
-+ ath_dbg(ath9k_hw_common(ah), RESET,
-+ "reset MAC via external reset\n");
-
-- REG_WRITE(ah, AR_RTC_RESET, 1);
-+ err = ah->external_reset();
-+ if (err) {
-+ ath_err(ath9k_hw_common(ah),
-+ "External reset failed, err=%d\n", err);
-+ return false;
- }
-
-+ if (AR_SREV_9550(ah)) {
-+ REG_WRITE(ah, AR_RTC_RESET, 0);
-+ udelay(10);
-+ }
-+
-+ REG_WRITE(ah, AR_RTC_RESET, 1);
-+ udelay(10);
-+
- return true;
- }
-
-@@ -1356,24 +1373,24 @@ static bool ath9k_hw_set_reset(struct at
- rst_flags |= AR_RTC_RC_MAC_COLD;
- }
-
-- if (AR_SREV_9330(ah)) {
-- if (!ath9k_hw_ar9330_reset_war(ah, type))
-- return false;
-- }
--
- if (ath9k_hw_mci_is_enabled(ah))
- ar9003_mci_check_gpm_offset(ah);
-
- /* DMA HALT added to resolve ar9300 and ar9580 bus error during
-- * RTC_RC reg read
-+ * RTC_RC reg read. Also needed for AR9550 external reset
- */
-- if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
-+ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
- REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
- ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
- 20 * AH_WAIT_TIMEOUT);
-- REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
- }
-
-+ if (!AR_SREV_9100(ah))
-+ ath9k_hw_external_reset(ah, type);
-+
-+ if (AR_SREV_9300(ah) || AR_SREV_9580(ah))
-+ REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
-+
- REG_WRITE(ah, AR_RTC_RC, rst_flags);
-
- REGWRITE_BUFFER_FLUSH(ah);
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 11 Jul 2016 12:07:40 +0200
-Subject: [PATCH] ath9k_hw: set spectral scan enable bit on trigger for
- AR9003+
-
-AR9002 code and QCA AR9003+ code do the same.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -1800,6 +1800,8 @@ static void ar9003_hw_spectral_scan_conf
-
- static void ar9003_hw_spectral_scan_trigger(struct ath_hw *ah)
- {
-+ REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
-+ AR_PHY_SPECTRAL_SCAN_ENABLE);
- /* Activate spectral scan */
- REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
- AR_PHY_SPECTRAL_SCAN_ACTIVE);
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 27 Dec 2016 23:16:23 +0100
-Subject: [PATCH] ath9k: don't run periodic and nf calibation at the same
- time
-
-The checks already prevents periodic cal from being started while noise
-floor calibration runs. It is missing checks for the other way around.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
-@@ -676,10 +676,10 @@ static int ar9002_hw_calibrate(struct at
- return 0;
-
- ah->cal_list_curr = currCal = currCal->calNext;
-- if (currCal->calState == CAL_WAITING) {
-+ if (currCal->calState == CAL_WAITING)
- ath9k_hw_reset_calibration(ah, currCal);
-- return 0;
-- }
-+
-+ return 0;
- }
-
- /* Do NF cal only at longer intervals */
+++ /dev/null
-From: Felix Fietkau <nbd@openwrt.org>
-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. Don't use rx_clear in TX99 mode.
-
-Cc: stable@vger.kernel.org
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
-Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
----
-
---- a/drivers/net/wireless/ath/ath9k/mac.c
-+++ b/drivers/net/wireless/ath/ath9k/mac.c
-@@ -678,13 +678,18 @@ 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);
-+ u32 reg = AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT;
-+
-+ if (!IS_ENABLED(CPTCFG_ATH9K_TX99))
-+ reg |= AR_DIAG_FORCE_RX_CLEAR;
-+ REG_SET_BIT(ah, AR_DIAG_SW, reg);
-
- ath9k_hw_disable_mib_counters(ah);
- }
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 14 May 2016 14:51:02 +0200
-Subject: [PATCH] Revert "ath9k: interpret requested txpower in EIRP
- domain"
-
-This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411.
----
-
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2935,7 +2935,8 @@ void ath9k_hw_apply_txpower(struct ath_h
- {
- struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
- struct ieee80211_channel *channel;
-- int chan_pwr, new_pwr;
-+ int chan_pwr, new_pwr, max_gain;
-+ int ant_gain, ant_reduction = 0;
-
- if (!chan)
- return;
-@@ -2943,10 +2944,15 @@ void ath9k_hw_apply_txpower(struct ath_h
- channel = chan->chan;
- chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
- new_pwr = min_t(int, chan_pwr, reg->power_limit);
-+ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
-+
-+ ant_gain = get_antenna_gain(ah, chan);
-+ if (ant_gain > max_gain)
-+ ant_reduction = ant_gain - max_gain;
-
- ah->eep_ops->set_txpower(ah, chan,
- ath9k_regd_get_ctl(reg, chan),
-- get_antenna_gain(ah, chan), new_pwr, test);
-+ ant_reduction, new_pwr, test);
- }
-
- void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
+++ /dev/null
-From: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-Date: Fri, 19 Feb 2016 11:01:49 +0100
-Subject: [PATCH] mac80211: add hdrlen to ieee80211_tx_data
-
-Add hdrlen to ieee80211_tx_data and use this
-when wep/ccmd/tkip. This is preparation for
-aligned4 code.
-
-Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
----
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -177,6 +177,7 @@ struct ieee80211_tx_data {
- struct ieee80211_tx_rate rate;
-
- unsigned int flags;
-+ unsigned int hdrlen;
- };
-
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -921,7 +921,7 @@ ieee80211_tx_h_fragment(struct ieee80211
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr = (void *)skb->data;
- int frag_threshold = tx->local->hw.wiphy->frag_threshold;
-- int hdrlen;
-+ int hdrlen = tx->hdrlen;
- int fragnum;
-
- /* no matter what happens, tx->skb moves to tx->skbs */
-@@ -942,8 +942,6 @@ ieee80211_tx_h_fragment(struct ieee80211
- if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
- return TX_DROP;
-
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
--
- /* internal error, why isn't DONTFRAG set? */
- if (WARN_ON(skb->len + FCS_LEN <= frag_threshold))
- return TX_DROP;
-@@ -1175,6 +1173,8 @@ ieee80211_tx_prepare(struct ieee80211_su
-
- hdr = (struct ieee80211_hdr *) skb->data;
-
-+ tx->hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+
- if (likely(sta)) {
- if (!IS_ERR(sta))
- tx->sta = sta;
-@@ -3468,6 +3468,7 @@ begin:
- tx.local = local;
- tx.skb = skb;
- tx.sdata = vif_to_sdata(info->control.vif);
-+ tx.hdrlen = ieee80211_padded_hdrlen(hw, hdr->frame_control);
-
- if (txq->sta)
- tx.sta = container_of(txq->sta, struct sta_info, sta);
-@@ -3796,6 +3797,7 @@ ieee80211_build_data_template(struct iee
- hdr = (void *)skb->data;
- tx.sta = sta_info_get(sdata, hdr->addr1);
- tx.skb = skb;
-+ tx.hdrlen = ieee80211_padded_hdrlen(&tx.local->hw, hdr->frame_control);
-
- if (ieee80211_tx_h_select_key(&tx) != TX_CONTINUE) {
- rcu_read_unlock();
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -1232,6 +1232,7 @@ void ieee80211_send_auth(struct ieee8021
- struct ieee80211_local *local = sdata->local;
- struct sk_buff *skb;
- struct ieee80211_mgmt *mgmt;
-+ unsigned int hdrlen;
- int err;
-
- /* 24 + 6 = header + auth_algo + auth_transaction + status_code */
-@@ -1255,8 +1256,10 @@ void ieee80211_send_auth(struct ieee8021
- skb_put_data(skb, extra, extra_len);
-
- if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
-+ hdrlen = ieee80211_hdrlen(mgmt->frame_control);
- mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-- err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx);
-+ err = ieee80211_wep_encrypt(local, skb, hdrlen, key,
-+ key_len, key_idx);
- WARN_ON(err);
- }
-
---- a/net/mac80211/wep.c
-+++ b/net/mac80211/wep.c
-@@ -89,11 +89,11 @@ static void ieee80211_wep_get_iv(struct
-
- static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
- struct sk_buff *skb,
-+ unsigned int hdrlen,
- int keylen, int keyidx)
- {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-- unsigned int hdrlen;
- u8 *newhdr;
-
- hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
-@@ -101,7 +101,6 @@ static u8 *ieee80211_wep_add_iv(struct i
- if (WARN_ON(skb_headroom(skb) < IEEE80211_WEP_IV_LEN))
- return NULL;
-
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
- newhdr = skb_push(skb, IEEE80211_WEP_IV_LEN);
- memmove(newhdr, newhdr + IEEE80211_WEP_IV_LEN, hdrlen);
-
-@@ -160,6 +159,7 @@ int ieee80211_wep_encrypt_data(struct cr
- */
- int ieee80211_wep_encrypt(struct ieee80211_local *local,
- struct sk_buff *skb,
-+ unsigned int hdrlen,
- const u8 *key, int keylen, int keyidx)
- {
- u8 *iv;
-@@ -169,7 +169,7 @@ int ieee80211_wep_encrypt(struct ieee802
- if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN))
- return -1;
-
-- iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx);
-+ iv = ieee80211_wep_add_iv(local, skb, hdrlen, keylen, keyidx);
- if (!iv)
- return -1;
-
-@@ -307,13 +307,14 @@ static int wep_encrypt_skb(struct ieee80
- struct ieee80211_key_conf *hw_key = info->control.hw_key;
-
- if (!hw_key) {
-- if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
-+ if (ieee80211_wep_encrypt(tx->local, skb, tx->hdrlen,
-+ tx->key->conf.key,
- tx->key->conf.keylen,
- tx->key->conf.keyidx))
- return -1;
- } else if ((hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
- (hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
-- if (!ieee80211_wep_add_iv(tx->local, skb,
-+ if (!ieee80211_wep_add_iv(tx->local, skb, tx->hdrlen,
- tx->key->conf.keylen,
- tx->key->conf.keyidx))
- return -1;
---- a/net/mac80211/wep.h
-+++ b/net/mac80211/wep.h
-@@ -22,6 +22,7 @@ int ieee80211_wep_encrypt_data(struct cr
- size_t klen, u8 *data, size_t data_len);
- int ieee80211_wep_encrypt(struct ieee80211_local *local,
- struct sk_buff *skb,
-+ unsigned int hdrlen,
- const u8 *key, int keylen, int keyidx);
- int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
- size_t klen, u8 *data, size_t data_len);
---- a/net/mac80211/wpa.c
-+++ b/net/mac80211/wpa.c
-@@ -44,7 +44,7 @@ ieee80211_tx_h_michael_mic_add(struct ie
- skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control))
- return TX_CONTINUE;
-
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ hdrlen = tx->hdrlen;
- if (skb->len < hdrlen)
- return TX_DROP;
-
-@@ -187,7 +187,6 @@ mic_fail_no_key:
-
- static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
- {
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct ieee80211_key *key = tx->key;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- unsigned int hdrlen;
-@@ -202,7 +201,7 @@ static int tkip_encrypt_skb(struct ieee8
- return 0;
- }
-
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ hdrlen = tx->hdrlen;
- len = skb->len - hdrlen;
-
- if (info->control.hw_key)
-@@ -420,7 +419,7 @@ static int ccmp_encrypt_skb(struct ieee8
- return 0;
- }
-
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ hdrlen = tx->hdrlen;
- len = skb->len - hdrlen;
-
- if (info->control.hw_key)
-@@ -653,7 +652,7 @@ static int gcmp_encrypt_skb(struct ieee8
- return 0;
- }
-
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ hdrlen = tx->hdrlen;
- len = skb->len - hdrlen;
-
- if (info->control.hw_key)
-@@ -793,7 +792,6 @@ static ieee80211_tx_result
- ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
- struct sk_buff *skb)
- {
-- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_key *key = tx->key;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- int hdrlen;
-@@ -809,8 +807,7 @@ ieee80211_crypto_cs_encrypt(struct ieee8
- pskb_expand_head(skb, iv_len, 0, GFP_ATOMIC)))
- return TX_DROP;
-
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
--
-+ hdrlen = tx->hdrlen;
- pos = skb_push(skb, iv_len);
- memmove(pos, pos + iv_len, hdrlen);
-
+++ /dev/null
-From: Janusz Dziedzic <janusz.dziedzic@tieto.com>
-Date: Fri, 19 Feb 2016 11:01:50 +0100
-Subject: [PATCH] mac80211: add NEED_ALIGNED4_SKBS hw flag
-
-HW/driver should set NEED_ALIGNED4_SKBS flag in case
-require aligned skbs to four-byte boundaries.
-This affect only TX direction.
-
-Padding is added after ieee80211_hdr, before IV/LLC.
-
-Before we have to do memmove(hdrlen) twice in the
-dirver. Once before we pass this to HW and next
-in tx completion (to be sure monitor will report
-this tx frame correctly).
-
-With this patch we can skip this memmove() and save CPU.
-
-Currently this was tested with ath9k, both hw/sw crypt for
-wep/tkip/ccmp.
-
-Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
----
-
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -2059,6 +2059,9 @@ struct ieee80211_txq {
- * @IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA: Hardware supports buffer STA on
- * TDLS links.
- *
-+ * @IEEE80211_HW_NEEDS_ALIGNED4_SKBS: Driver need aligned skbs to four-byte.
-+ * Padding will be added after ieee80211_hdr, before IV/LLC.
-+ *
- * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
- */
- enum ieee80211_hw_flags {
-@@ -2102,6 +2105,7 @@ enum ieee80211_hw_flags {
- IEEE80211_HW_REPORTS_LOW_ACK,
- IEEE80211_HW_SUPPORTS_TX_FRAG,
- IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA,
-+ IEEE80211_HW_NEEDS_ALIGNED4_SKBS,
-
- /* keep last, obviously */
- NUM_IEEE80211_HW_FLAGS
---- a/net/mac80211/debugfs.c
-+++ b/net/mac80211/debugfs.c
-@@ -212,6 +212,7 @@ static const char *hw_flag_names[] = {
- FLAG(REPORTS_LOW_ACK),
- FLAG(SUPPORTS_TX_FRAG),
- FLAG(SUPPORTS_TDLS_BUFFER_STA),
-+ FLAG(NEEDS_ALIGNED4_SKBS),
- #undef FLAG
- };
-
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1548,6 +1548,29 @@ ieee80211_vif_get_num_mcast_if(struct ie
- return -1;
- }
-
-+static inline unsigned int
-+ieee80211_hdr_padsize(struct ieee80211_hw *hw, unsigned int hdrlen)
-+{
-+ /*
-+ * While hdrlen is already aligned to two-byte boundaries,
-+ * simple check with & 2 will return correct padsize.
-+ */
-+ if (ieee80211_hw_check(hw, NEEDS_ALIGNED4_SKBS))
-+ return hdrlen & 2;
-+ return 0;
-+}
-+
-+static inline unsigned int
-+ieee80211_padded_hdrlen(struct ieee80211_hw *hw, __le16 fc)
-+{
-+ unsigned int hdrlen;
-+
-+ hdrlen = ieee80211_hdrlen(fc);
-+ hdrlen += ieee80211_hdr_padsize(hw, hdrlen);
-+
-+ return hdrlen;
-+}
-+
- u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
- struct ieee80211_rx_status *status,
- unsigned int mpdu_len,
---- a/net/mac80211/sta_info.h
-+++ b/net/mac80211/sta_info.h
-@@ -300,7 +300,7 @@ struct ieee80211_fast_tx {
- u8 hdr_len;
- u8 sa_offs, da_offs, pn_offs;
- u8 band;
-- u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
-+ u8 hdr[30 + 2 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
- sizeof(rfc1042_header)] __aligned(2);
-
- struct rcu_head rcu_head;
---- a/net/mac80211/status.c
-+++ b/net/mac80211/status.c
-@@ -642,9 +642,22 @@ void ieee80211_tx_monitor(struct ieee802
- struct sk_buff *skb2;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_sub_if_data *sdata;
-+ struct ieee80211_hdr *hdr = (void *)skb->data;
- struct net_device *prev_dev = NULL;
-+ unsigned int hdrlen, padsize;
- int rtap_len;
-
-+ /* Remove padding if was added */
-+ if (ieee80211_hw_check(&local->hw, NEEDS_ALIGNED4_SKBS)) {
-+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ padsize = ieee80211_hdr_padsize(&local->hw, hdrlen);
-+
-+ if (padsize && skb->len > hdrlen + padsize) {
-+ memmove(skb->data + padsize, skb->data, hdrlen);
-+ skb_pull(skb, padsize);
-+ }
-+ }
-+
- /* send frame to monitor interfaces now */
- rtap_len = ieee80211_tx_radiotap_len(info);
- if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
---- a/net/mac80211/tkip.c
-+++ b/net/mac80211/tkip.c
-@@ -201,10 +201,12 @@ void ieee80211_get_tkip_p2k(struct ieee8
- {
- struct ieee80211_key *key = (struct ieee80211_key *)
- container_of(keyconf, struct ieee80211_key, conf);
-+ struct ieee80211_hw *hw = &key->local->hw;
- const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
- struct tkip_ctx *ctx = &key->u.tkip.tx;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-- const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
-+ const u8 *data = (u8 *)hdr + ieee80211_padded_hdrlen(hw,
-+ hdr->frame_control);
- u32 iv32 = get_unaligned_le32(&data[4]);
- u16 iv16 = data[2] | (data[0] << 8);
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -1172,8 +1172,7 @@ ieee80211_tx_prepare(struct ieee80211_su
- info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
-
- hdr = (struct ieee80211_hdr *) skb->data;
--
-- tx->hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ tx->hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control);
-
- if (likely(sta)) {
- if (!IS_ERR(sta))
-@@ -2184,7 +2183,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
- goto fail;
-
- hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
-- hdrlen = ieee80211_hdrlen(hdr->frame_control);
-+ hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control);
-
- if (skb->len < len_rthdr + hdrlen)
- goto fail;
-@@ -2402,7 +2401,7 @@ static struct sk_buff *ieee80211_build_h
- struct ieee80211_chanctx_conf *chanctx_conf;
- struct ieee80211_sub_if_data *ap_sdata;
- enum nl80211_band band;
-- int ret;
-+ int padsize, ret;
-
- if (IS_ERR(sta))
- sta = NULL;
-@@ -2622,6 +2621,9 @@ static struct sk_buff *ieee80211_build_h
- hdrlen += 2;
- }
-
-+ /* Check aligned4 skb required */
-+ padsize = ieee80211_hdr_padsize(&sdata->local->hw, hdrlen);
-+
- /*
- * Drop unicast frames to unauthorised stations unless they are
- * EAPOL frames from the local station.
-@@ -2702,6 +2704,7 @@ static struct sk_buff *ieee80211_build_h
-
- skb_pull(skb, skip_header_bytes);
- head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
-+ head_need += padsize;
-
- /*
- * So we need to modify the skb header and hence need a copy of
-@@ -2734,6 +2737,9 @@ static struct sk_buff *ieee80211_build_h
- memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
- #endif
-
-+ if (padsize)
-+ memset(skb_push(skb, padsize), 0, padsize);
-+
- if (ieee80211_is_data_qos(fc)) {
- __le16 *qos_control;
-
-@@ -2909,6 +2915,9 @@ void ieee80211_check_fast_xmit(struct st
- fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
- }
-
-+ /* Check aligned4 skb required */
-+ build.hdr_len += ieee80211_hdr_padsize(&local->hw, build.hdr_len);
-+
- /* We store the key here so there's no point in using rcu_dereference()
- * but that's fine because the code that changes the pointers will call
- * this function after doing so. For a single CPU that would be enough,
-@@ -3495,7 +3504,7 @@ begin:
-
- if (tx.key &&
- (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
-- pn_offs = ieee80211_hdrlen(hdr->frame_control);
-+ pn_offs = tx.hdrlen;
-
- ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs,
- tx.key, skb);
---- a/net/mac80211/util.c
-+++ b/net/mac80211/util.c
-@@ -1230,6 +1230,7 @@ void ieee80211_send_auth(struct ieee8021
- u32 tx_flags)
- {
- struct ieee80211_local *local = sdata->local;
-+ struct ieee80211_hw *hw = &local->hw;
- struct sk_buff *skb;
- struct ieee80211_mgmt *mgmt;
- unsigned int hdrlen;
-@@ -1256,7 +1257,7 @@ void ieee80211_send_auth(struct ieee8021
- skb_put_data(skb, extra, extra_len);
-
- if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
-- hdrlen = ieee80211_hdrlen(mgmt->frame_control);
-+ hdrlen = ieee80211_padded_hdrlen(hw, mgmt->frame_control);
- mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
- err = ieee80211_wep_encrypt(local, skb, hdrlen, key,
- key_len, key_idx);
+++ /dev/null
-From: Chaitanya T K <chaitanya.mgit@gmail.com>
-Date: Mon, 27 Jun 2016 15:23:26 +0530
-Subject: [PATCH] mac80211: minstrel: Enable STBC and LDPC for VHT Rates
-
-If peer support reception of STBC and LDPC, enable them for better
-performance.
-
-Signed-off-by: Chaitanya TK <chaitanya.mgit@gmail.com>
----
-
---- a/include/linux/ieee80211.h
-+++ b/include/linux/ieee80211.h
-@@ -1556,6 +1556,7 @@ struct ieee80211_vht_operation {
- #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
- #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
- #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700
-+#define IEEE80211_VHT_CAP_RXSTBC_SHIFT 8
- #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
- #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
- #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -1130,7 +1130,7 @@ minstrel_ht_update_caps(void *priv, stru
- struct minstrel_ht_sta_priv *msp = priv_sta;
- struct minstrel_ht_sta *mi = &msp->ht;
- struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
-- u16 sta_cap = sta->ht_cap.cap;
-+ u16 ht_cap = sta->ht_cap.cap;
- struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
- struct sta_info *sinfo = container_of(sta, struct sta_info, sta);
- int use_vht;
-@@ -1138,6 +1138,7 @@ minstrel_ht_update_caps(void *priv, stru
- int ack_dur;
- int stbc;
- int i;
-+ bool ldpc = false;
-
- /* fall back to the old minstrel for legacy stations */
- if (!sta->ht_cap.ht_supported)
-@@ -1175,16 +1176,24 @@ minstrel_ht_update_caps(void *priv, stru
- }
- mi->sample_tries = 4;
-
-- /* TODO tx_flags for vht - ATM the RC API is not fine-grained enough */
- if (!use_vht) {
-- stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>
-+ stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >>
- IEEE80211_HT_CAP_RX_STBC_SHIFT;
-- mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
-
-- if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)
-- mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
-+ if (ht_cap & IEEE80211_HT_CAP_LDPC_CODING)
-+ ldpc = true;
-+ } else {
-+ stbc = (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) >>
-+ IEEE80211_VHT_CAP_RXSTBC_SHIFT;
-+
-+ if (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)
-+ ldpc = true;
- }
-
-+ mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
-+ if (ldpc)
-+ mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
-+
- for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
- u32 gflags = minstrel_mcs_groups[i].flags;
- int bw, nss;
-@@ -1197,10 +1206,10 @@ minstrel_ht_update_caps(void *priv, stru
-
- if (gflags & IEEE80211_TX_RC_SHORT_GI) {
- if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
-- if (!(sta_cap & IEEE80211_HT_CAP_SGI_40))
-+ if (!(ht_cap & IEEE80211_HT_CAP_SGI_40))
- continue;
- } else {
-- if (!(sta_cap & IEEE80211_HT_CAP_SGI_20))
-+ if (!(ht_cap & IEEE80211_HT_CAP_SGI_20))
- continue;
- }
- }
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 28 Aug 2016 13:13:01 +0200
-Subject: [PATCH] ath9k: fix moredata bit in PS buffered frame release
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -1659,6 +1659,22 @@ void ath_tx_aggr_wakeup(struct ath_softc
- }
- }
-
-+
-+static void
-+ath9k_set_moredata(struct ath_softc *sc, struct ath_buf *bf, bool val)
-+{
-+ struct ieee80211_hdr *hdr;
-+ u16 mask = cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-+ u16 mask_val = mask * val;
-+
-+ hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
-+ if ((hdr->frame_control & mask) != mask_val) {
-+ hdr->frame_control = (hdr->frame_control & ~mask) | mask_val;
-+ dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
-+ sizeof(*hdr), DMA_TO_DEVICE);
-+ }
-+}
-+
- void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
- struct ieee80211_sta *sta,
- u16 tids, int nframes,
-@@ -1689,6 +1705,7 @@ void ath9k_release_buffered_frames(struc
- if (!bf)
- break;
-
-+ ath9k_set_moredata(sc, bf, true);
- list_add_tail(&bf->list, &bf_q);
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
- if (bf_isampdu(bf)) {
-@@ -1712,6 +1729,9 @@ void ath9k_release_buffered_frames(struc
- if (list_empty(&bf_q))
- return;
-
-+ if (!more_data)
-+ ath9k_set_moredata(sc, bf_tail, false);
-+
- info = IEEE80211_SKB_CB(bf_tail->bf_mpdu);
- info->flags |= IEEE80211_TX_STATUS_EOSP;
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 28 Aug 2016 13:13:42 +0200
-Subject: [PATCH] ath9k: clear potentially stale EOSP status bit in
- intermediate queues
-
-Prevents spurious ieee80211_sta_eosp calls.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -969,7 +969,8 @@ ath_tx_get_tid_subframe(struct ath_softc
- bf->bf_lastbf = bf;
-
- tx_info = IEEE80211_SKB_CB(skb);
-- tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
-+ tx_info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
-+ IEEE80211_TX_STATUS_EOSP);
-
- /*
- * No aggregation session is running, but there may be frames
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 28 Aug 2016 13:23:27 +0200
-Subject: [PATCH] ath9k: report tx status on EOSP
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -86,7 +86,8 @@ static void ath_tx_status(struct ieee802
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_sta *sta = info->status.status_driver_data[0];
-
-- if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
-+ if (info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
-+ IEEE80211_TX_STATUS_EOSP)) {
- ieee80211_tx_status(hw, skb);
- return;
- }
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Tue, 30 Aug 2016 12:44:08 +0200
-Subject: [PATCH] ath9k: fix block-ack window tracking issues
-
-Ensure that a buffer gets tracked as part of the block-ack window as
-soon as it's dequeued from the tid for the first time. Ensure that
-double calls to ath_tx_addto_baw (e.g. on retransmission) don't cause
-any issues.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -62,7 +62,7 @@ static void ath_tx_rc_status(struct ath_
- struct ath_tx_status *ts, int nframes, int nbad,
- int txok);
- static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
-- int seqno);
-+ struct ath_buf *bf);
- static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
- struct ath_txq *txq,
- struct ath_atx_tid *tid,
-@@ -296,7 +296,7 @@ static void ath_tx_flush_tid(struct ath_
- }
-
- if (fi->baw_tracked) {
-- ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
-+ ath_tx_update_baw(sc, tid, bf);
- sendbar = true;
- }
-
-@@ -312,10 +312,15 @@ static void ath_tx_flush_tid(struct ath_
- }
-
- static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
-- int seqno)
-+ struct ath_buf *bf)
- {
-+ struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
-+ u16 seqno = bf->bf_state.seqno;
- int index, cindex;
-
-+ if (!fi->baw_tracked)
-+ return;
-+
- index = ATH_BA_INDEX(tid->seq_start, seqno);
- cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
-
-@@ -336,6 +341,9 @@ static void ath_tx_addto_baw(struct ath_
- u16 seqno = bf->bf_state.seqno;
- int index, cindex;
-
-+ if (fi->baw_tracked)
-+ return;
-+
- index = ATH_BA_INDEX(tid->seq_start, seqno);
- cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
- __set_bit(cindex, tid->tx_buf);
-@@ -612,7 +620,7 @@ static void ath_tx_complete_aggr(struct
- * complete the acked-ones/xretried ones; update
- * block-ack window
- */
-- ath_tx_update_baw(sc, tid, seqno);
-+ ath_tx_update_baw(sc, tid, bf);
-
- if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
- memcpy(tx_info->control.rates, rates, sizeof(rates));
-@@ -642,7 +650,7 @@ static void ath_tx_complete_aggr(struct
- * run out of tx buf.
- */
- if (!tbf) {
-- ath_tx_update_baw(sc, tid, seqno);
-+ ath_tx_update_baw(sc, tid, bf);
-
- ath_tx_complete_buf(sc, bf, txq,
- &bf_head, NULL, ts,
-@@ -1011,11 +1019,14 @@ ath_tx_get_tid_subframe(struct ath_softc
-
- INIT_LIST_HEAD(&bf_head);
- list_add(&bf->list, &bf_head);
-- ath_tx_update_baw(sc, tid, seqno);
-+ ath_tx_update_baw(sc, tid, bf);
- ath_tx_complete_buf(sc, bf, txq, &bf_head, NULL, &ts, 0);
- continue;
- }
-
-+ if (bf_isampdu(bf))
-+ ath_tx_addto_baw(sc, tid, bf);
-+
- return bf;
- }
-
-@@ -1073,8 +1084,6 @@ ath_tx_form_aggr(struct ath_softc *sc, s
- bf->bf_next = NULL;
-
- /* link buffers of this frame to the aggregate */
-- if (!fi->baw_tracked)
-- ath_tx_addto_baw(sc, tid, bf);
- bf->bf_state.ndelim = ndelim;
-
- list_add_tail(&bf->list, bf_q);
-@@ -1710,10 +1719,8 @@ void ath9k_release_buffered_frames(struc
- ath9k_set_moredata(sc, bf, true);
- list_add_tail(&bf->list, &bf_q);
- ath_set_rates(tid->an->vif, tid->an->sta, bf);
-- if (bf_isampdu(bf)) {
-- ath_tx_addto_baw(sc, tid, bf);
-+ if (bf_isampdu(bf))
- bf->bf_state.bf_type &= ~BUF_AGGR;
-- }
- if (bf_tail)
- bf_tail->bf_next = bf;
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 22 Mar 2017 20:37:04 +0100
-Subject: [PATCH] ath9k_hw: fix channel maximum power level test
-
-The tx power applied by set_txpower is limited by the CTL (conformance
-test limit) entries in the EEPROM. These can change based on the user
-configured regulatory domain.
-Depending on the EEPROM data this can cause the tx power to become too
-limited, if the original regdomain CTLs impose lowr limits than the CTLs
-of the user configured regdomain.
-
-To fix this issue, set the initial channel limits without any CTL
-restrictions and only apply the CTL at run time when setting the channel
-and the real tx power.
-
-Cc: stable@vger.kernel.org
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2937,10 +2937,14 @@ void ath9k_hw_apply_txpower(struct ath_h
- struct ieee80211_channel *channel;
- int chan_pwr, new_pwr, max_gain;
- int ant_gain, ant_reduction = 0;
-+ u16 ctl = NO_CTL;
-
- if (!chan)
- return;
-
-+ if (!test)
-+ ctl = ath9k_regd_get_ctl(reg, chan);
-+
- channel = chan->chan;
- chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
- new_pwr = min_t(int, chan_pwr, reg->power_limit);
-@@ -2950,9 +2954,7 @@ void ath9k_hw_apply_txpower(struct ath_h
- if (ant_gain > max_gain)
- ant_reduction = ant_gain - max_gain;
-
-- ah->eep_ops->set_txpower(ah, chan,
-- ath9k_regd_get_ctl(reg, chan),
-- ant_reduction, new_pwr, test);
-+ ah->eep_ops->set_txpower(ah, chan, ctl, ant_reduction, new_pwr, test);
- }
-
- void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Wed, 19 Jul 2017 08:49:31 +0200
-Subject: [PATCH] ath9k: adjust tx power reduction for US regulatory
- domain
-
-FCC regulatory rules allow for up to 3 dBi antenna gain. Account for
-this in the EEPROM based tx power reduction code.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -2954,6 +2954,10 @@ void ath9k_hw_apply_txpower(struct ath_h
- if (ant_gain > max_gain)
- ant_reduction = ant_gain - max_gain;
-
-+ /* FCC allows maximum antenna gain of 3 dBi */
-+ if (reg->region == NL80211_DFS_FCC)
-+ ant_reduction = max_t(int, ant_reduction - 6, 0);
-+
- ah->eep_ops->set_txpower(ah, chan, ctl, ant_reduction, new_pwr, test);
- }
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sun, 23 Jul 2017 14:58:22 +0200
-Subject: [PATCH] ath9k: fix more-data flag for buffered multicast
- packets
-
-The flag needs to be cleared for the last packet in the list, not the
-first one. Fixes some issues with multicast packet loss for powersave
-clients connected to an ath9k AP.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -2436,7 +2436,6 @@ void ath_tx_cabq(struct ieee80211_hw *hw
- .txq = sc->beacon.cabq
- };
- struct ath_tx_info info = {};
-- struct ieee80211_hdr *hdr;
- struct ath_buf *bf_tail = NULL;
- struct ath_buf *bf;
- LIST_HEAD(bf_q);
-@@ -2480,15 +2479,10 @@ void ath_tx_cabq(struct ieee80211_hw *hw
- if (list_empty(&bf_q))
- return;
-
-- bf = list_first_entry(&bf_q, struct ath_buf, list);
-- hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
--
-- if (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) {
-- hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-- dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
-- sizeof(*hdr), DMA_TO_DEVICE);
-- }
-+ bf = list_last_entry(&bf_q, struct ath_buf, list);
-+ ath9k_set_moredata(sc, bf, false);
-
-+ bf = list_first_entry(&bf_q, struct ath_buf, list);
- ath_txq_lock(sc, txctl.txq);
- ath_tx_fill_desc(sc, bf, txctl.txq, 0);
- ath_tx_txqaddbuf(sc, txctl.txq, &bf_q, false);
+++ /dev/null
-From: dave taht <dave@taht.net>
-Date: Wed, 5 Oct 2016 20:09:15 -0700
-Subject: [PATCH] Revert "ath10k: disable wake_tx_queue for older
- devices"
-
-This reverts commit 4ca1807815aa6801aaced7fdefa9edacc2521767
-in the hope that we've fixed all the performance problems now.
----
-
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -8319,15 +8319,6 @@ int ath10k_mac_register(struct ath10k *a
- ath10k_warn(ar, "failed to initialise DFS pattern detector\n");
- }
-
-- /* Current wake_tx_queue implementation imposes a significant
-- * performance penalty in some setups. The tx scheduling code needs
-- * more work anyway so disable the wake_tx_queue unless firmware
-- * supports the pull-push mechanism.
-- */
-- if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
-- ar->running_fw->fw_file.fw_features))
-- ar->ops->wake_tx_queue = NULL;
--
- ret = ath10k_mac_init_rd(ar);
- if (ret) {
- ath10k_err(ar, "failed to derive regdom: %d\n", ret);
+++ /dev/null
-From: Christian Lamparter <chunkeey@gmail.com>
-Date: Wed, 1 Nov 2017 21:01:57 +0100
-Subject: [PATCH] ath10k: fix recent bandwidth conversion bug
-
-The commit "cfg80211: make RATE_INFO_BW_20 the default" changed
-the index of RATE_INFO_BW_20, but the updates to ath10k missed
-the special bandwidth calculation case in
-ath10k_update_per_peer_tx_stats().
-
-Fixes: 842be75c77cb ("cfg80211: make RATE_INFO_BW_20 the default")
-Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
-Patchwork-Id: 10037035
-Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
----
-
---- a/drivers/net/wireless/ath/ath10k/htt_rx.c
-+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
-@@ -592,6 +592,9 @@ struct amsdu_subframe_hdr {
-
- #define GROUP_ID_IS_SU_MIMO(x) ((x) == 0 || (x) == 63)
-
-+static const u8 ath10k_bw_to_mac80211[] = { RATE_INFO_BW_20, RATE_INFO_BW_40,
-+ RATE_INFO_BW_80, RATE_INFO_BW_160 };
-+
- static void ath10k_htt_rx_h_rates(struct ath10k *ar,
- struct ieee80211_rx_status *status,
- struct htt_rx_desc *rxd)
-@@ -694,23 +697,7 @@ static void ath10k_htt_rx_h_rates(struct
- if (sgi)
- status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-
-- switch (bw) {
-- /* 20MHZ */
-- case 0:
-- break;
-- /* 40MHZ */
-- case 1:
-- status->bw = RATE_INFO_BW_40;
-- break;
-- /* 80MHZ */
-- case 2:
-- status->bw = RATE_INFO_BW_80;
-- break;
-- case 3:
-- status->bw = RATE_INFO_BW_160;
-- break;
-- }
--
-+ status->bw = ath10k_bw_to_mac80211[bw];
- status->encoding = RX_ENC_VHT;
- break;
- default:
-@@ -2297,7 +2284,7 @@ ath10k_update_per_peer_tx_stats(struct a
- arsta->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
-
- arsta->txrate.nss = txrate.nss;
-- arsta->txrate.bw = txrate.bw + RATE_INFO_BW_20;
-+ arsta->txrate.bw = ath10k_bw_to_mac80211[txrate.bw];
- }
-
- static void ath10k_htt_fetch_peer_stats(struct ath10k *ar,
+++ /dev/null
-From: Johannes Berg <johannes.berg@intel.com>
-Date: Tue, 30 Jan 2018 13:17:38 +0100
-Subject: [PATCH] cfg80211: use only 1Mbps for basic rates in mesh
-
-Mesh used to use the mandatory rates as basic rates, but we got
-the calculation of mandatory rates wrong until some time ago.
-Fix this this broke interoperability with older versions since
-now more basic rates are required, and thus the MBSS isn't the
-same and the network stops working.
-
-Fix this by simply using only 1Mbps as the basic rate in 2.4GHz.
-Since the changed mandatory rates only affected 2.4GHz, this is
-all we need to make it work again.
-
-Reported-and-tested-by: Matthias Schiffer <mschiffer@universe-factory.net>
-Fixes: 1bd773c077de ("wireless: set correct mandatory rate flags")
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
- net/wireless/mesh.c | 25 ++++++++++++++++++++++---
- 1 file changed, 22 insertions(+), 3 deletions(-)
-
---- a/net/wireless/mesh.c
-+++ b/net/wireless/mesh.c
-@@ -169,9 +169,28 @@ int __cfg80211_join_mesh(struct cfg80211
- enum nl80211_bss_scan_width scan_width;
- struct ieee80211_supported_band *sband =
- rdev->wiphy.bands[setup->chandef.chan->band];
-- scan_width = cfg80211_chandef_to_scan_width(&setup->chandef);
-- setup->basic_rates = ieee80211_mandatory_rates(sband,
-- scan_width);
-+
-+ if (setup->chandef.chan->band == NL80211_BAND_2GHZ) {
-+ int i;
-+
-+ /*
-+ * Older versions selected the mandatory rates for
-+ * 2.4 GHz as well, but were broken in that only
-+ * 1 Mbps was regarded as a mandatory rate. Keep
-+ * using just 1 Mbps as the default basic rate for
-+ * mesh to be interoperable with older versions.
-+ */
-+ for (i = 0; i < sband->n_bitrates; i++) {
-+ if (sband->bitrates[i].bitrate == 10) {
-+ setup->basic_rates = BIT(i);
-+ break;
-+ }
-+ }
-+ } else {
-+ scan_width = cfg80211_chandef_to_scan_width(&setup->chandef);
-+ setup->basic_rates = ieee80211_mandatory_rates(sband,
-+ scan_width);
-+ }
- }
-
- err = cfg80211_chandef_dfs_required(&rdev->wiphy,
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 10 Feb 2018 12:41:51 +0100
-Subject: [PATCH] mac80211: minstrel: remove unnecessary debugfs cleanup
- code
-
-debugfs entries are cleaned up by debugfs_remove_recursive already.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel.c
-+++ b/net/mac80211/rc80211_minstrel.c
-@@ -689,8 +689,8 @@ minstrel_alloc(struct ieee80211_hw *hw,
-
- #ifdef CPTCFG_MAC80211_DEBUGFS
- mp->fixed_rate_idx = (u32) -1;
-- mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx",
-- S_IRUGO | S_IWUGO, debugfsdir, &mp->fixed_rate_idx);
-+ debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
-+ &mp->fixed_rate_idx);
- #endif
-
- minstrel_init_cck_rates(mp);
-@@ -701,9 +701,6 @@ minstrel_alloc(struct ieee80211_hw *hw,
- static void
- minstrel_free(void *priv)
- {
--#ifdef CPTCFG_MAC80211_DEBUGFS
-- debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate);
--#endif
- kfree(priv);
- }
-
-@@ -735,7 +732,6 @@ const struct rate_control_ops mac80211_m
- .free_sta = minstrel_free_sta,
- #ifdef CPTCFG_MAC80211_DEBUGFS
- .add_sta_debugfs = minstrel_add_sta_debugfs,
-- .remove_sta_debugfs = minstrel_remove_sta_debugfs,
- #endif
- .get_expected_throughput = minstrel_get_expected_throughput,
- };
---- a/net/mac80211/rc80211_minstrel.h
-+++ b/net/mac80211/rc80211_minstrel.h
-@@ -109,11 +109,6 @@ struct minstrel_sta_info {
-
- /* sampling table */
- u8 *sample_table;
--
--#ifdef CPTCFG_MAC80211_DEBUGFS
-- struct dentry *dbg_stats;
-- struct dentry *dbg_stats_csv;
--#endif
- };
-
- struct minstrel_priv {
-@@ -137,7 +132,6 @@ struct minstrel_priv {
- * - setting will be applied on next update
- */
- u32 fixed_rate_idx;
-- struct dentry *dbg_fixed_rate;
- #endif
- };
-
-@@ -156,7 +150,6 @@ minstrel_get_ewmsd10(struct minstrel_rat
-
- extern const struct rate_control_ops mac80211_minstrel;
- void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
--void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
-
- /* Recalculate success probabilities and counters for a given rate using EWMA */
- void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
---- a/net/mac80211/rc80211_minstrel_debugfs.c
-+++ b/net/mac80211/rc80211_minstrel_debugfs.c
-@@ -214,19 +214,7 @@ minstrel_add_sta_debugfs(void *priv, voi
- {
- struct minstrel_sta_info *mi = priv_sta;
-
-- mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi,
-- &minstrel_stat_fops);
--
-- mi->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO, dir,
-- mi, &minstrel_stat_csv_fops);
--}
--
--void
--minstrel_remove_sta_debugfs(void *priv, void *priv_sta)
--{
-- struct minstrel_sta_info *mi = priv_sta;
--
-- debugfs_remove(mi->dbg_stats);
--
-- debugfs_remove(mi->dbg_stats_csv);
-+ debugfs_create_file("rc_stats", S_IRUGO, dir, mi, &minstrel_stat_fops);
-+ debugfs_create_file("rc_stats_csv", S_IRUGO, dir, mi,
-+ &minstrel_stat_csv_fops);
- }
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -1393,7 +1393,6 @@ static const struct rate_control_ops mac
- .free = minstrel_ht_free,
- #ifdef CPTCFG_MAC80211_DEBUGFS
- .add_sta_debugfs = minstrel_ht_add_sta_debugfs,
-- .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
- #endif
- .get_expected_throughput = minstrel_ht_get_expected_throughput,
- };
---- a/net/mac80211/rc80211_minstrel_ht.h
-+++ b/net/mac80211/rc80211_minstrel_ht.h
-@@ -110,17 +110,12 @@ struct minstrel_ht_sta_priv {
- struct minstrel_ht_sta ht;
- struct minstrel_sta_info legacy;
- };
--#ifdef CPTCFG_MAC80211_DEBUGFS
-- struct dentry *dbg_stats;
-- struct dentry *dbg_stats_csv;
--#endif
- void *ratelist;
- void *sample_table;
- bool is_ht;
- };
-
- void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
--void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
- int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
- int prob_ewma);
-
---- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
-+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
-@@ -303,17 +303,8 @@ minstrel_ht_add_sta_debugfs(void *priv,
- {
- struct minstrel_ht_sta_priv *msp = priv_sta;
-
-- msp->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, msp,
-- &minstrel_ht_stat_fops);
-- msp->dbg_stats_csv = debugfs_create_file("rc_stats_csv", S_IRUGO,
-- dir, msp, &minstrel_ht_stat_csv_fops);
--}
--
--void
--minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta)
--{
-- struct minstrel_ht_sta_priv *msp = priv_sta;
--
-- debugfs_remove(msp->dbg_stats);
-- debugfs_remove(msp->dbg_stats_csv);
-+ debugfs_create_file("rc_stats", S_IRUGO, dir, msp,
-+ &minstrel_ht_stat_fops);
-+ debugfs_create_file("rc_stats_csv", S_IRUGO, dir, msp,
-+ &minstrel_ht_stat_csv_fops);
- }
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 10 Feb 2018 12:43:30 +0100
-Subject: [PATCH] mac80211: minstrel: merge with minstrel_ht, always enable
- VHT support
-
-Legacy-only devices are not very common and the overhead of the extra
-code for HT and VHT rates is not big enough to justify all those extra
-lines of code to make it optional.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/Kconfig
-+++ b/net/mac80211/Kconfig
-@@ -25,20 +25,6 @@ config MAC80211_RC_MINSTREL
- ---help---
- This option enables the 'minstrel' TX rate control algorithm
-
--config MAC80211_RC_MINSTREL_HT
-- bool "Minstrel 802.11n support" if EXPERT
-- depends on MAC80211_RC_MINSTREL
-- default y
-- ---help---
-- This option enables the 'minstrel_ht' TX rate control algorithm
--
--config MAC80211_RC_MINSTREL_VHT
-- bool "Minstrel 802.11ac support" if EXPERT
-- depends on MAC80211_RC_MINSTREL_HT
-- default n
-- ---help---
-- This option enables VHT in the 'minstrel_ht' TX rate control algorithm
--
- choice
- prompt "Default rate control algorithm"
- depends on MAC80211_HAS_RC
-@@ -60,8 +46,7 @@ endchoice
-
- config MAC80211_RC_DEFAULT
- string
-- default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT
-- default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
-+ default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL
- default ""
-
- endif
---- a/net/mac80211/Makefile
-+++ b/net/mac80211/Makefile
-@@ -50,13 +50,14 @@ mac80211-$(CONFIG_PM) += pm.o
-
- CFLAGS_trace.o := -I$(src)
-
--rc80211_minstrel-y := rc80211_minstrel.o
--rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o
-+rc80211_minstrel-y := \
-+ rc80211_minstrel.o \
-+ rc80211_minstrel_ht.o
-
--rc80211_minstrel_ht-y := rc80211_minstrel_ht.o
--rc80211_minstrel_ht-$(CPTCFG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o
-+rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += \
-+ rc80211_minstrel_debugfs.o \
-+ rc80211_minstrel_ht_debugfs.o
-
- mac80211-$(CPTCFG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
--mac80211-$(CPTCFG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y)
-
- ccflags-y += -DDEBUG
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -1252,18 +1252,12 @@ static int __init ieee80211_init(void)
- if (ret)
- return ret;
-
-- ret = rc80211_minstrel_ht_init();
-- if (ret)
-- goto err_minstrel;
--
- ret = ieee80211_iface_init();
- if (ret)
- goto err_netdev;
-
- return 0;
- err_netdev:
-- rc80211_minstrel_ht_exit();
-- err_minstrel:
- rc80211_minstrel_exit();
-
- return ret;
-@@ -1271,7 +1265,6 @@ static int __init ieee80211_init(void)
-
- static void __exit ieee80211_exit(void)
- {
-- rc80211_minstrel_ht_exit();
- rc80211_minstrel_exit();
-
- ieee80211s_stop();
---- a/net/mac80211/rate.h
-+++ b/net/mac80211/rate.h
-@@ -95,18 +95,5 @@ static inline void rc80211_minstrel_exit
- }
- #endif
-
--#ifdef CPTCFG_MAC80211_RC_MINSTREL_HT
--int rc80211_minstrel_ht_init(void);
--void rc80211_minstrel_ht_exit(void);
--#else
--static inline int rc80211_minstrel_ht_init(void)
--{
-- return 0;
--}
--static inline void rc80211_minstrel_ht_exit(void)
--{
--}
--#endif
--
-
- #endif /* IEEE80211_RATE_H */
---- a/net/mac80211/rc80211_minstrel.c
-+++ b/net/mac80211/rc80211_minstrel.c
-@@ -572,138 +572,6 @@ minstrel_rate_init(void *priv, struct ie
- minstrel_update_rates(mp, mi);
- }
-
--static void *
--minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
--{
-- struct ieee80211_supported_band *sband;
-- struct minstrel_sta_info *mi;
-- struct minstrel_priv *mp = priv;
-- struct ieee80211_hw *hw = mp->hw;
-- int max_rates = 0;
-- int i;
--
-- mi = kzalloc(sizeof(struct minstrel_sta_info), gfp);
-- if (!mi)
-- return NULL;
--
-- for (i = 0; i < NUM_NL80211_BANDS; i++) {
-- sband = hw->wiphy->bands[i];
-- if (sband && sband->n_bitrates > max_rates)
-- max_rates = sband->n_bitrates;
-- }
--
-- mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp);
-- if (!mi->r)
-- goto error;
--
-- mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp);
-- if (!mi->sample_table)
-- goto error1;
--
-- mi->last_stats_update = jiffies;
-- return mi;
--
--error1:
-- kfree(mi->r);
--error:
-- kfree(mi);
-- return NULL;
--}
--
--static void
--minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta)
--{
-- struct minstrel_sta_info *mi = priv_sta;
--
-- kfree(mi->sample_table);
-- kfree(mi->r);
-- kfree(mi);
--}
--
--static void
--minstrel_init_cck_rates(struct minstrel_priv *mp)
--{
-- static const int bitrates[4] = { 10, 20, 55, 110 };
-- struct ieee80211_supported_band *sband;
-- u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
-- int i, j;
--
-- sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ];
-- if (!sband)
-- return;
--
-- for (i = 0, j = 0; i < sband->n_bitrates; i++) {
-- struct ieee80211_rate *rate = &sband->bitrates[i];
--
-- if (rate->flags & IEEE80211_RATE_ERP_G)
-- continue;
--
-- if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
-- continue;
--
-- for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
-- if (rate->bitrate != bitrates[j])
-- continue;
--
-- mp->cck_rates[j] = i;
-- break;
-- }
-- }
--}
--
--static void *
--minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
--{
-- struct minstrel_priv *mp;
--
-- mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
-- if (!mp)
-- return NULL;
--
-- /* contention window settings
-- * Just an approximation. Using the per-queue values would complicate
-- * the calculations and is probably unnecessary */
-- mp->cw_min = 15;
-- mp->cw_max = 1023;
--
-- /* number of packets (in %) to use for sampling other rates
-- * sample less often for non-mrr packets, because the overhead
-- * is much higher than with mrr */
-- mp->lookaround_rate = 5;
-- mp->lookaround_rate_mrr = 10;
--
-- /* maximum time that the hw is allowed to stay in one MRR segment */
-- mp->segment_size = 6000;
--
-- if (hw->max_rate_tries > 0)
-- mp->max_retry = hw->max_rate_tries;
-- else
-- /* safe default, does not necessarily have to match hw properties */
-- mp->max_retry = 7;
--
-- if (hw->max_rates >= 4)
-- mp->has_mrr = true;
--
-- mp->hw = hw;
-- mp->update_interval = 100;
--
--#ifdef CPTCFG_MAC80211_DEBUGFS
-- mp->fixed_rate_idx = (u32) -1;
-- debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
-- &mp->fixed_rate_idx);
--#endif
--
-- minstrel_init_cck_rates(mp);
--
-- return mp;
--}
--
--static void
--minstrel_free(void *priv)
--{
-- kfree(priv);
--}
--
- static u32 minstrel_get_expected_throughput(void *priv_sta)
- {
- struct minstrel_sta_info *mi = priv_sta;
-@@ -722,29 +590,8 @@ static u32 minstrel_get_expected_through
- }
-
- const struct rate_control_ops mac80211_minstrel = {
-- .name = "minstrel",
- .tx_status_ext = minstrel_tx_status,
- .get_rate = minstrel_get_rate,
- .rate_init = minstrel_rate_init,
-- .alloc = minstrel_alloc,
-- .free = minstrel_free,
-- .alloc_sta = minstrel_alloc_sta,
-- .free_sta = minstrel_free_sta,
--#ifdef CPTCFG_MAC80211_DEBUGFS
-- .add_sta_debugfs = minstrel_add_sta_debugfs,
--#endif
- .get_expected_throughput = minstrel_get_expected_throughput,
- };
--
--int __init
--rc80211_minstrel_init(void)
--{
-- return ieee80211_rate_control_register(&mac80211_minstrel);
--}
--
--void
--rc80211_minstrel_exit(void)
--{
-- ieee80211_rate_control_unregister(&mac80211_minstrel);
--}
--
---- a/net/mac80211/rc80211_minstrel.h
-+++ b/net/mac80211/rc80211_minstrel.h
-@@ -158,7 +158,5 @@ int minstrel_get_tp_avg(struct minstrel_
- /* debugfs */
- int minstrel_stats_open(struct inode *inode, struct file *file);
- int minstrel_stats_csv_open(struct inode *inode, struct file *file);
--ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos);
--int minstrel_stats_release(struct inode *inode, struct file *file);
-
- #endif
---- a/net/mac80211/rc80211_minstrel_debugfs.c
-+++ b/net/mac80211/rc80211_minstrel_debugfs.c
-@@ -54,22 +54,6 @@
- #include <net/mac80211.h>
- #include "rc80211_minstrel.h"
-
--ssize_t
--minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
--{
-- struct minstrel_debugfs_info *ms;
--
-- ms = file->private_data;
-- return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
--}
--
--int
--minstrel_stats_release(struct inode *inode, struct file *file)
--{
-- kfree(file->private_data);
-- return 0;
--}
--
- int
- minstrel_stats_open(struct inode *inode, struct file *file)
- {
-@@ -135,14 +119,6 @@ minstrel_stats_open(struct inode *inode,
- return 0;
- }
-
--static const struct file_operations minstrel_stat_fops = {
-- .owner = THIS_MODULE,
-- .open = minstrel_stats_open,
-- .read = minstrel_stats_read,
-- .release = minstrel_stats_release,
-- .llseek = default_llseek,
--};
--
- int
- minstrel_stats_csv_open(struct inode *inode, struct file *file)
- {
-@@ -200,21 +176,3 @@ minstrel_stats_csv_open(struct inode *in
-
- return 0;
- }
--
--static const struct file_operations minstrel_stat_csv_fops = {
-- .owner = THIS_MODULE,
-- .open = minstrel_stats_csv_open,
-- .read = minstrel_stats_read,
-- .release = minstrel_stats_release,
-- .llseek = default_llseek,
--};
--
--void
--minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
--{
-- struct minstrel_sta_info *mi = priv_sta;
--
-- debugfs_create_file("rc_stats", S_IRUGO, dir, mi, &minstrel_stat_fops);
-- debugfs_create_file("rc_stats_csv", S_IRUGO, dir, mi,
-- &minstrel_stat_csv_fops);
--}
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -137,12 +137,10 @@
- } \
- }
-
--#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
- static bool minstrel_vht_only = true;
- module_param(minstrel_vht_only, bool, 0644);
- MODULE_PARM_DESC(minstrel_vht_only,
- "Use only VHT rates when VHT is supported by sta.");
--#endif
-
- /*
- * To enable sufficiently targeted rate sampling, MCS rates are divided into
-@@ -171,7 +169,6 @@ const struct mcs_group minstrel_mcs_grou
-
- CCK_GROUP,
-
--#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
- VHT_GROUP(1, 0, BW_20),
- VHT_GROUP(2, 0, BW_20),
- VHT_GROUP(3, 0, BW_20),
-@@ -195,7 +192,6 @@ const struct mcs_group minstrel_mcs_grou
- VHT_GROUP(1, 1, BW_80),
- VHT_GROUP(2, 1, BW_80),
- VHT_GROUP(3, 1, BW_80),
--#endif
- };
-
- static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
-@@ -1146,12 +1142,10 @@ minstrel_ht_update_caps(void *priv, stru
-
- BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB);
-
--#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
- if (vht_cap->vht_supported)
- use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0);
- else
--#endif
-- use_vht = 0;
-+ use_vht = 0;
-
- msp->is_ht = true;
- memset(mi, 0, sizeof(*mi));
-@@ -1226,10 +1220,9 @@ minstrel_ht_update_caps(void *priv, stru
-
- /* HT rate */
- if (gflags & IEEE80211_TX_RC_MCS) {
--#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
- if (use_vht && minstrel_vht_only)
- continue;
--#endif
-+
- mi->supported[i] = mcs->rx_mask[nss - 1];
- if (mi->supported[i])
- n_supported++;
-@@ -1349,16 +1342,88 @@ minstrel_ht_free_sta(void *priv, struct
- kfree(msp);
- }
-
-+static void
-+minstrel_ht_init_cck_rates(struct minstrel_priv *mp)
-+{
-+ static const int bitrates[4] = { 10, 20, 55, 110 };
-+ struct ieee80211_supported_band *sband;
-+ u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
-+ int i, j;
-+
-+ sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ];
-+ if (!sband)
-+ return;
-+
-+ for (i = 0, j = 0; i < sband->n_bitrates; i++) {
-+ struct ieee80211_rate *rate = &sband->bitrates[i];
-+
-+ if (rate->flags & IEEE80211_RATE_ERP_G)
-+ continue;
-+
-+ if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
-+ continue;
-+
-+ for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
-+ if (rate->bitrate != bitrates[j])
-+ continue;
-+
-+ mp->cck_rates[j] = i;
-+ break;
-+ }
-+ }
-+}
-+
- static void *
- minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
- {
-- return mac80211_minstrel.alloc(hw, debugfsdir);
-+ struct minstrel_priv *mp;
-+
-+ mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
-+ if (!mp)
-+ return NULL;
-+
-+ /* contention window settings
-+ * Just an approximation. Using the per-queue values would complicate
-+ * the calculations and is probably unnecessary */
-+ mp->cw_min = 15;
-+ mp->cw_max = 1023;
-+
-+ /* number of packets (in %) to use for sampling other rates
-+ * sample less often for non-mrr packets, because the overhead
-+ * is much higher than with mrr */
-+ mp->lookaround_rate = 5;
-+ mp->lookaround_rate_mrr = 10;
-+
-+ /* maximum time that the hw is allowed to stay in one MRR segment */
-+ mp->segment_size = 6000;
-+
-+ if (hw->max_rate_tries > 0)
-+ mp->max_retry = hw->max_rate_tries;
-+ else
-+ /* safe default, does not necessarily have to match hw properties */
-+ mp->max_retry = 7;
-+
-+ if (hw->max_rates >= 4)
-+ mp->has_mrr = true;
-+
-+ mp->hw = hw;
-+ mp->update_interval = 100;
-+
-+#ifdef CPTCFG_MAC80211_DEBUGFS
-+ mp->fixed_rate_idx = (u32) -1;
-+ debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
-+ &mp->fixed_rate_idx);
-+#endif
-+
-+ minstrel_ht_init_cck_rates(mp);
-+
-+ return mp;
- }
-
- static void
- minstrel_ht_free(void *priv)
- {
-- mac80211_minstrel.free(priv);
-+ kfree(priv);
- }
-
- static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
-@@ -1417,14 +1482,14 @@ static void __init init_sample_table(voi
- }
-
- int __init
--rc80211_minstrel_ht_init(void)
-+rc80211_minstrel_init(void)
- {
- init_sample_table();
- return ieee80211_rate_control_register(&mac80211_minstrel_ht);
- }
-
- void
--rc80211_minstrel_ht_exit(void)
-+rc80211_minstrel_exit(void)
- {
- ieee80211_rate_control_unregister(&mac80211_minstrel_ht);
- }
---- a/net/mac80211/rc80211_minstrel_ht.h
-+++ b/net/mac80211/rc80211_minstrel_ht.h
-@@ -15,11 +15,7 @@
- */
- #define MINSTREL_MAX_STREAMS 3
- #define MINSTREL_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */
--#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
- #define MINSTREL_VHT_STREAM_GROUPS 6 /* BW(=3) * SGI(=2) */
--#else
--#define MINSTREL_VHT_STREAM_GROUPS 0
--#endif
-
- #define MINSTREL_HT_GROUPS_NB (MINSTREL_MAX_STREAMS * \
- MINSTREL_HT_STREAM_GROUPS)
-@@ -34,11 +30,7 @@
- #define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB)
- #define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1)
-
--#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
- #define MCS_GROUP_RATES 10
--#else
--#define MCS_GROUP_RATES 8
--#endif
-
- struct mcs_group {
- u32 flags;
---- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
-+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
-@@ -15,6 +15,22 @@
- #include "rc80211_minstrel.h"
- #include "rc80211_minstrel_ht.h"
-
-+static ssize_t
-+minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
-+{
-+ struct minstrel_debugfs_info *ms;
-+
-+ ms = file->private_data;
-+ return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
-+}
-+
-+static int
-+minstrel_stats_release(struct inode *inode, struct file *file)
-+{
-+ kfree(file->private_data);
-+ return 0;
-+}
-+
- static char *
- minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
- {
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 10 Feb 2018 12:45:47 +0100
-Subject: [PATCH] mac80211: minstrel: reduce minstrel_mcs_groups size
-
-By storing a shift value for all duration values of a group, we can
-reduce precision by a neglegible amount to make it fit into a u16 value.
-This improves cache footprint and reduces size:
-
-Before:
- text data bss dec hex filename
- 10024 116 0 10140 279c rc80211_minstrel_ht.o
-
-After:
- text data bss dec hex filename
- 9368 116 0 9484 250c rc80211_minstrel_ht.o
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -52,22 +52,23 @@
- _streams - 1
-
- /* MCS rate information for an MCS group */
--#define MCS_GROUP(_streams, _sgi, _ht40) \
-+#define MCS_GROUP(_streams, _sgi, _ht40, _s) \
- [GROUP_IDX(_streams, _sgi, _ht40)] = { \
- .streams = _streams, \
-+ .shift = _s, \
- .flags = \
- IEEE80211_TX_RC_MCS | \
- (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
- (_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
- .duration = { \
-- MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26), \
-- MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52), \
-- MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78), \
-- MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104), \
-- MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156), \
-- MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208), \
-- MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234), \
-- MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) \
-+ MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s, \
-+ MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s, \
-+ MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s, \
-+ MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s, \
-+ MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s, \
-+ MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s, \
-+ MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s, \
-+ MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s \
- } \
- }
-
-@@ -80,9 +81,10 @@
- #define BW2VBPS(_bw, r3, r2, r1) \
- (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
-
--#define VHT_GROUP(_streams, _sgi, _bw) \
-+#define VHT_GROUP(_streams, _sgi, _bw, _s) \
- [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \
- .streams = _streams, \
-+ .shift = _s, \
- .flags = \
- IEEE80211_TX_RC_VHT_MCS | \
- (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
-@@ -90,25 +92,25 @@
- _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
- .duration = { \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 117, 54, 26)), \
-+ BW2VBPS(_bw, 117, 54, 26)) >> _s, \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 234, 108, 52)), \
-+ BW2VBPS(_bw, 234, 108, 52)) >> _s, \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 351, 162, 78)), \
-+ BW2VBPS(_bw, 351, 162, 78)) >> _s, \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 468, 216, 104)), \
-+ BW2VBPS(_bw, 468, 216, 104)) >> _s, \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 702, 324, 156)), \
-+ BW2VBPS(_bw, 702, 324, 156)) >> _s, \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 936, 432, 208)), \
-+ BW2VBPS(_bw, 936, 432, 208)) >> _s, \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 1053, 486, 234)), \
-+ BW2VBPS(_bw, 1053, 486, 234)) >> _s, \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 1170, 540, 260)), \
-+ BW2VBPS(_bw, 1170, 540, 260)) >> _s, \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 1404, 648, 312)), \
-+ BW2VBPS(_bw, 1404, 648, 312)) >> _s, \
- MCS_DURATION(_streams, _sgi, \
-- BW2VBPS(_bw, 1560, 720, 346)) \
-+ BW2VBPS(_bw, 1560, 720, 346)) >> _s \
- } \
- }
-
-@@ -121,19 +123,20 @@
- (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \
- CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE))
-
--#define CCK_DURATION_LIST(_short) \
-- CCK_ACK_DURATION(10, _short), \
-- CCK_ACK_DURATION(20, _short), \
-- CCK_ACK_DURATION(55, _short), \
-- CCK_ACK_DURATION(110, _short)
-+#define CCK_DURATION_LIST(_short, _s) \
-+ CCK_ACK_DURATION(10, _short) >> _s, \
-+ CCK_ACK_DURATION(20, _short) >> _s, \
-+ CCK_ACK_DURATION(55, _short) >> _s, \
-+ CCK_ACK_DURATION(110, _short) >> _s
-
--#define CCK_GROUP \
-+#define CCK_GROUP(_s) \
- [MINSTREL_CCK_GROUP] = { \
- .streams = 0, \
- .flags = 0, \
-+ .shift = _s, \
- .duration = { \
-- CCK_DURATION_LIST(false), \
-- CCK_DURATION_LIST(true) \
-+ CCK_DURATION_LIST(false, _s), \
-+ CCK_DURATION_LIST(true, _s) \
- } \
- }
-
-@@ -151,47 +154,47 @@ MODULE_PARM_DESC(minstrel_vht_only,
- * BW -> SGI -> #streams
- */
- const struct mcs_group minstrel_mcs_groups[] = {
-- MCS_GROUP(1, 0, BW_20),
-- MCS_GROUP(2, 0, BW_20),
-- MCS_GROUP(3, 0, BW_20),
--
-- MCS_GROUP(1, 1, BW_20),
-- MCS_GROUP(2, 1, BW_20),
-- MCS_GROUP(3, 1, BW_20),
--
-- MCS_GROUP(1, 0, BW_40),
-- MCS_GROUP(2, 0, BW_40),
-- MCS_GROUP(3, 0, BW_40),
--
-- MCS_GROUP(1, 1, BW_40),
-- MCS_GROUP(2, 1, BW_40),
-- MCS_GROUP(3, 1, BW_40),
--
-- CCK_GROUP,
--
-- VHT_GROUP(1, 0, BW_20),
-- VHT_GROUP(2, 0, BW_20),
-- VHT_GROUP(3, 0, BW_20),
--
-- VHT_GROUP(1, 1, BW_20),
-- VHT_GROUP(2, 1, BW_20),
-- VHT_GROUP(3, 1, BW_20),
--
-- VHT_GROUP(1, 0, BW_40),
-- VHT_GROUP(2, 0, BW_40),
-- VHT_GROUP(3, 0, BW_40),
--
-- VHT_GROUP(1, 1, BW_40),
-- VHT_GROUP(2, 1, BW_40),
-- VHT_GROUP(3, 1, BW_40),
--
-- VHT_GROUP(1, 0, BW_80),
-- VHT_GROUP(2, 0, BW_80),
-- VHT_GROUP(3, 0, BW_80),
--
-- VHT_GROUP(1, 1, BW_80),
-- VHT_GROUP(2, 1, BW_80),
-- VHT_GROUP(3, 1, BW_80),
-+ MCS_GROUP(1, 0, BW_20, 5),
-+ MCS_GROUP(2, 0, BW_20, 4),
-+ MCS_GROUP(3, 0, BW_20, 4),
-+
-+ MCS_GROUP(1, 1, BW_20, 5),
-+ MCS_GROUP(2, 1, BW_20, 4),
-+ MCS_GROUP(3, 1, BW_20, 4),
-+
-+ MCS_GROUP(1, 0, BW_40, 4),
-+ MCS_GROUP(2, 0, BW_40, 4),
-+ MCS_GROUP(3, 0, BW_40, 4),
-+
-+ MCS_GROUP(1, 1, BW_40, 4),
-+ MCS_GROUP(2, 1, BW_40, 4),
-+ MCS_GROUP(3, 1, BW_40, 4),
-+
-+ CCK_GROUP(8),
-+
-+ VHT_GROUP(1, 0, BW_20, 5),
-+ VHT_GROUP(2, 0, BW_20, 4),
-+ VHT_GROUP(3, 0, BW_20, 4),
-+
-+ VHT_GROUP(1, 1, BW_20, 5),
-+ VHT_GROUP(2, 1, BW_20, 4),
-+ VHT_GROUP(3, 1, BW_20, 4),
-+
-+ VHT_GROUP(1, 0, BW_40, 4),
-+ VHT_GROUP(2, 0, BW_40, 4),
-+ VHT_GROUP(3, 0, BW_40, 4),
-+
-+ VHT_GROUP(1, 1, BW_40, 4),
-+ VHT_GROUP(2, 1, BW_40, 4),
-+ VHT_GROUP(3, 1, BW_40, 4),
-+
-+ VHT_GROUP(1, 0, BW_80, 4),
-+ VHT_GROUP(2, 0, BW_80, 4),
-+ VHT_GROUP(3, 0, BW_80, 4),
-+
-+ VHT_GROUP(1, 1, BW_80, 4),
-+ VHT_GROUP(2, 1, BW_80, 4),
-+ VHT_GROUP(3, 1, BW_80, 4),
- };
-
- static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
-@@ -307,7 +310,8 @@ minstrel_ht_get_tp_avg(struct minstrel_h
- if (group != MINSTREL_CCK_GROUP)
- nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
-
-- nsecs += minstrel_mcs_groups[group].duration[rate];
-+ nsecs += minstrel_mcs_groups[group].duration[rate] <<
-+ minstrel_mcs_groups[group].shift;
-
- /*
- * For the throughput calculation, limit the probability value to 90% to
-@@ -755,12 +759,19 @@ minstrel_ht_tx_status(void *priv, struct
- minstrel_ht_update_rates(mp, mi);
- }
-
-+static inline int
-+minstrel_get_duration(int index)
-+{
-+ const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
-+ unsigned int duration = group->duration[index % MCS_GROUP_RATES];
-+ return duration << group->shift;
-+}
-+
- static void
- minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
- int index)
- {
- struct minstrel_rate_stats *mrs;
-- const struct mcs_group *group;
- unsigned int tx_time, tx_time_rtscts, tx_time_data;
- unsigned int cw = mp->cw_min;
- unsigned int ctime = 0;
-@@ -779,8 +790,7 @@ minstrel_calc_retransmit(struct minstrel
- mrs->retry_count_rtscts = 2;
- mrs->retry_updated = true;
-
-- group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
-- tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;
-+ tx_time_data = minstrel_get_duration(index) * ampdu_len / 1000;
-
- /* Contention time for first 2 tries */
- ctime = (t_slot * cw) >> 1;
-@@ -874,20 +884,24 @@ minstrel_ht_get_max_amsdu_len(struct min
- int group = mi->max_prob_rate / MCS_GROUP_RATES;
- const struct mcs_group *g = &minstrel_mcs_groups[group];
- int rate = mi->max_prob_rate % MCS_GROUP_RATES;
-+ unsigned int duration;
-
- /* Disable A-MSDU if max_prob_rate is bad */
- if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))
- return 1;
-
-+ duration = g->duration[rate];
-+ duration <<= g->shift;
-+
- /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */
-- if (g->duration[rate] > MCS_DURATION(1, 0, 52))
-+ if (duration > MCS_DURATION(1, 0, 52))
- return 500;
-
- /*
- * If the rate is slower than single-stream MCS4, limit A-MSDU to usual
- * data packet size
- */
-- if (g->duration[rate] > MCS_DURATION(1, 0, 104))
-+ if (duration > MCS_DURATION(1, 0, 104))
- return 1600;
-
- /*
-@@ -895,7 +909,7 @@ minstrel_ht_get_max_amsdu_len(struct min
- * rate success probability is less than 75%, limit A-MSDU to twice the usual
- * data packet size
- */
-- if (g->duration[rate] > MCS_DURATION(1, 0, 260) ||
-+ if (duration > MCS_DURATION(1, 0, 260) ||
- (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <
- MINSTREL_FRAC(75, 100)))
- return 3200;
-@@ -942,13 +956,6 @@ minstrel_ht_update_rates(struct minstrel
- rate_control_set_rates(mp->hw, mi->sta, rates);
- }
-
--static inline int
--minstrel_get_duration(int index)
--{
-- const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
-- return group->duration[index % MCS_GROUP_RATES];
--}
--
- static int
- minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
- {
---- a/net/mac80211/rc80211_minstrel_ht.h
-+++ b/net/mac80211/rc80211_minstrel_ht.h
-@@ -33,9 +33,10 @@
- #define MCS_GROUP_RATES 10
-
- struct mcs_group {
-- u32 flags;
-- unsigned int streams;
-- unsigned int duration[MCS_GROUP_RATES];
-+ u16 flags;
-+ u8 streams;
-+ u8 shift;
-+ u16 duration[MCS_GROUP_RATES];
- };
-
- extern const struct mcs_group minstrel_mcs_groups[];
---- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
-+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
-@@ -58,6 +58,7 @@ minstrel_ht_stats_dump(struct minstrel_h
- static const int bitrates[4] = { 10, 20, 55, 110 };
- int idx = i * MCS_GROUP_RATES + j;
- unsigned int prob_ewmsd;
-+ unsigned int duration;
-
- if (!(mi->supported[i] & BIT(j)))
- continue;
-@@ -95,7 +96,9 @@ minstrel_ht_stats_dump(struct minstrel_h
- p += sprintf(p, " %3u ", idx);
-
- /* tx_time[rate(i)] in usec */
-- tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
-+ duration = mg->duration[j];
-+ duration <<= mg->shift;
-+ tx_time = DIV_ROUND_CLOSEST(duration, 1000);
- p += sprintf(p, "%6u ", tx_time);
-
- tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
-@@ -204,6 +207,7 @@ minstrel_ht_stats_csv_dump(struct minstr
- static const int bitrates[4] = { 10, 20, 55, 110 };
- int idx = i * MCS_GROUP_RATES + j;
- unsigned int prob_ewmsd;
-+ unsigned int duration;
-
- if (!(mi->supported[i] & BIT(j)))
- continue;
-@@ -238,7 +242,10 @@ minstrel_ht_stats_csv_dump(struct minstr
- }
-
- p += sprintf(p, "%u,", idx);
-- tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
-+
-+ duration = mg->duration[j];
-+ duration <<= mg->shift;
-+ tx_time = DIV_ROUND_CLOSEST(duration, 1000);
- p += sprintf(p, "%u,", tx_time);
-
- tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 10 Feb 2018 13:43:07 +0100
-Subject: [PATCH] mac80211: minstrel: fix using short preamble CCK rates on
- HT clients
-
-mi->supported[MINSTREL_CCK_GROUP] needs to be updated
-
-Fixes: 782dda00ab8e ("mac80211: minstrel_ht: move short preamble check out of get_rate")
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -1135,7 +1135,6 @@ minstrel_ht_update_caps(void *priv, stru
- struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
- u16 ht_cap = sta->ht_cap.cap;
- struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
-- struct sta_info *sinfo = container_of(sta, struct sta_info, sta);
- int use_vht;
- int n_supported = 0;
- int ack_dur;
-@@ -1267,8 +1266,7 @@ minstrel_ht_update_caps(void *priv, stru
- if (!n_supported)
- goto use_legacy;
-
-- if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE))
-- mi->cck_supported_short |= mi->cck_supported_short << 4;
-+ mi->supported[MINSTREL_CCK_GROUP] |= mi->cck_supported_short << 4;
-
- /* create an initial rate table with the lowest supported rates */
- minstrel_ht_update_stats(mp, mi);
+++ /dev/null
-From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
-Date: Fri, 2 Feb 2018 11:36:45 +0100
-Subject: [PATCH] ath9k: Protect queue draining by rcu_read_lock()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When ath9k was switched over to use the mac80211 intermediate queues,
-node cleanup now drains the mac80211 queues. However, this call path is
-not protected by rcu_read_lock() as it was previously entirely internal
-to the driver which uses its own locking.
-
-This leads to a possible rcu_dereference() without holding
-rcu_read_lock(); but only if a station is cleaned up while having
-packets queued on the TXQ. Fix this by adding the rcu_read_lock() to the
-caller in ath9k.
-
-Fixes: 50f08edf9809 ("ath9k: Switch to using mac80211 intermediate software queues.")
-Cc: stable@vger.kernel.org
-Reported-by: Ben Greear <greearb@candelatech.com>
-Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
----
-
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -2915,6 +2915,8 @@ void ath_tx_node_cleanup(struct ath_soft
- struct ath_txq *txq;
- int tidno;
-
-+ rcu_read_lock();
-+
- for (tidno = 0; tidno < IEEE80211_NUM_TIDS; tidno++) {
- tid = ath_node_to_tid(an, tidno);
- txq = tid->txq;
-@@ -2932,6 +2934,8 @@ void ath_tx_node_cleanup(struct ath_soft
- if (!an->sta)
- break; /* just one multicast ath_atx_tid */
- }
-+
-+ rcu_read_unlock();
- }
-
- #ifdef CPTCFG_ATH9K_TX99
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 1 Mar 2018 13:27:54 +0100
-Subject: [PATCH] mac80211: minstrel: fix CCK rate group streams value
-
-Fixes a harmless underflow issue when CCK rates are actively being used
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -131,7 +131,7 @@
-
- #define CCK_GROUP(_s) \
- [MINSTREL_CCK_GROUP] = { \
-- .streams = 0, \
-+ .streams = 1, \
- .flags = 0, \
- .shift = _s, \
- .duration = { \
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 1 Mar 2018 13:28:48 +0100
-Subject: [PATCH] mac80211: minstrel: fix sampling/reporting of CCK rates
- in HT mode
-
-Long/short preamble selection cannot be sampled separately, since it
-depends on the BSS state. Because of that, sampling attempts to
-currently not used preamble modes are not counted in the statistics,
-which leads to CCK rates being sampled too often.
-
-Fix statistics accounting for long/short preamble by increasing the
-index where necessary.
-Fix excessive CCK rate sampling by dropping unsupported sample attempts.
-
-This improves throughput on 2.4 GHz channels
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -281,7 +281,8 @@ minstrel_ht_get_stats(struct minstrel_pr
- break;
-
- /* short preamble */
-- if (!(mi->supported[group] & BIT(idx)))
-+ if ((mi->supported[group] & BIT(idx + 4)) &&
-+ (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
- idx += 4;
- }
- return &mi->groups[group].rates[idx];
-@@ -1080,18 +1081,23 @@ minstrel_ht_get_rate(void *priv, struct
- return;
-
- sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
-+ sample_idx %= MCS_GROUP_RATES;
-+
-+ if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP] &&
-+ (sample_idx >= 4) != txrc->short_preamble)
-+ return;
-+
- info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
- rate->count = 1;
-
-- if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
-+ if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP]) {
- int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
- rate->idx = mp->cck_rates[idx];
- } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) {
- ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES,
- sample_group->streams);
- } else {
-- rate->idx = sample_idx % MCS_GROUP_RATES +
-- (sample_group->streams - 1) * 8;
-+ rate->idx = sample_idx + (sample_group->streams - 1) * 8;
- }
-
- rate->flags = sample_group->flags;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 3 Mar 2018 18:48:58 +0100
-Subject: [PATCH] mac80211: minstrel: do not sample rates 3 times slower than
- max_prob_rate
-
-These rates are highly unlikely to be used quickly, even if the link
-deteriorates rapidly. This improves throughput in cases where CCK rates
-are not reliable enough to be skipped entirely during sampling.
-Sampling these rates regularly can cost a lot of airtime.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -1004,10 +1004,13 @@ minstrel_get_sample_rate(struct minstrel
- return -1;
-
- /*
-- * Do not sample if the probability is already higher than 95%
-- * to avoid wasting airtime.
-+ * Do not sample if the probability is already higher than 95%,
-+ * or if the rate is 3 times slower than the current max probability
-+ * rate, to avoid wasting airtime.
- */
-- if (mrs->prob_ewma > MINSTREL_FRAC(95, 100))
-+ sample_dur = minstrel_get_duration(sample_idx);
-+ if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
-+ minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur)
- return -1;
-
- /*
-@@ -1017,7 +1020,6 @@ minstrel_get_sample_rate(struct minstrel
-
- cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 /
- MCS_GROUP_RATES].streams;
-- sample_dur = minstrel_get_duration(sample_idx);
- if (sample_dur >= minstrel_get_duration(tp_rate2) &&
- (cur_max_tp_streams - 1 <
- minstrel_mcs_groups[sample_group].streams ||
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Thu, 8 Mar 2018 21:00:56 +0100
-Subject: [PATCH] mac80211: fix memory accounting with A-MSDU aggregation
-
-fq uses skb->truesize for memory usage tracking. Increments/decrements
-are done on enqueue/dequeue.
-When A-MSDU aggregation is performed on tx side, the packet is
-aggregated with the last packet in the queue belonging to the same flow.
-There are multiple bugs here:
-- The truesize field of the aggregated packet isn't updated, so memory
-usage is underestimated
-- fq->memory_usage isn't adjusted.
-
-Because of the combination of both bugs, this only causes tx issues in
-rare cases, mainly when the A-MSDU head needs to be reallocated.
-
-Fix this by adjusting both truesize of the A-MSDU head and adding the
-truesize delta to fq->memory_usage.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/net/mac80211/tx.c
-+++ b/net/mac80211/tx.c
-@@ -3171,6 +3171,7 @@ static bool ieee80211_amsdu_aggregate(st
- u8 max_subframes = sta->sta.max_amsdu_subframes;
- int max_frags = local->hw.max_tx_fragments;
- int max_amsdu_len = sta->sta.max_amsdu_len;
-+ int orig_truesize;
- __be16 len;
- void *data;
- bool ret = false;
-@@ -3201,12 +3202,13 @@ static bool ieee80211_amsdu_aggregate(st
- flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func);
- head = skb_peek_tail(&flow->queue);
- if (!head)
-- goto out;
-+ goto unlock;
-
-+ orig_truesize = head->truesize;
- orig_len = head->len;
-
- if (skb->len + head->len > max_amsdu_len)
-- goto out;
-+ goto unlock;
-
- if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head))
- goto out;
-@@ -3249,6 +3251,9 @@ static bool ieee80211_amsdu_aggregate(st
- fq_recalc_backlog(fq, tin, flow);
-
- out:
-+ fq->memory_usage += head->truesize - orig_truesize;
-+
-+unlock:
- spin_unlock_bh(&fq->lock);
-
- return ret;
+++ /dev/null
-From 4f717a2589be649afddbbd3ac58b67ebfa7426f7 Mon Sep 17 00:00:00 2001
-From: Sven Eckelmann <sven@narfation.org>
-Date: Wed, 6 Jun 2018 10:18:31 +0200
-Subject: [PATCH v2] cfg80211: initialize sinfo in cfg80211_get_station
-
-Most of the implementations behind cfg80211_get_station will not initialize
-sinfo to zero before manipulating it. For example, the member "filled",
-which indicates the filled in parts of this struct, is often only modified
-by enabling certain bits in the bitfield while keeping the remaining bits
-in their original state. A caller without a preinitialized sinfo.filled can
-then no longer decide which parts of sinfo were filled in by
-cfg80211_get_station (or actually the underlying implementations).
-
-cfg80211_get_station must therefore take care that sinfo is initialized to
-zero. Otherwise, the caller may tries to read information which was not
-filled in and which must therefore also be considered uninitialized. In
-batadv_v_elp_get_throughput's case, an invalid "random" expected throughput
-may be stored for this neighbor and thus the B.A.T.M.A.N V algorithm may
-switch to non-optimal neighbors for certain destinations.
-
-Fixes: 7406353d43c8 ("cfg80211: implement cfg80211_get_station cfg80211 API")
-Reported-by: Thomas Lauer <holminateur@gmail.com>
-Reported-by: Marcel Schmidt <ff.z-casparistrasse@mailbox.org>
-Cc: b.a.t.m.a.n@lists.open-mesh.org
-Signed-off-by: Sven Eckelmann <sven@narfation.org>
-
-Forwarded: https://patchwork.kernel.org/patch/10449857/
----
- net/wireless/util.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/net/wireless/util.c
-+++ b/net/wireless/util.c
-@@ -1749,6 +1749,8 @@ int cfg80211_get_station(struct net_devi
- if (!rdev->ops->get_station)
- return -EOPNOTSUPP;
-
-+ memset(sinfo, 0, sizeof(*sinfo));
-+
- return rdev_get_station(rdev, dev, mac_addr, sinfo);
- }
- EXPORT_SYMBOL(cfg80211_get_station);
+++ /dev/null
-From 8ed05ed06fca0136cf4546e804318f57ef823348 Mon Sep 17 00:00:00 2001
-From: Manikanta Pubbisetty <mpubbise@qti.qualcomm.com>
-Date: Mon, 6 Nov 2017 13:39:32 +0530
-Subject: [PATCH] ath10k: handle tdls peer events
-
-Handle tdls peer events from the target. TDLS events for the peer
-could be discover, teardown, etc. As of now, adding the logic to
-handle tdls teardown events alone.
-
-Teardown due to peer traffic indication(PTR) timeout is one such
-teardown event from the target.
-
-Tested this change on QCA9888 with 10.4-3.5.1-00018 fw version.
-
-Signed-off-by: Manikanta Pubbisetty <mpubbise@qti.qualcomm.com>
-Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
----
- drivers/net/wireless/ath/ath10k/wmi.c | 72 +++++++++++++++++++++++++++++++++++
- 1 file changed, 72 insertions(+)
-
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -29,6 +29,7 @@
- #include "p2p.h"
- #include "hw.h"
- #include "hif.h"
-+#include "txrx.h"
-
- #define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9
- #define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ)
-@@ -4456,6 +4457,74 @@ void ath10k_wmi_event_pdev_tpc_config(st
- __le32_to_cpu(ev->rate_max));
- }
-
-+static void
-+ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb)
-+{
-+ struct wmi_tdls_peer_event *ev;
-+ struct ath10k_peer *peer;
-+ struct ath10k_vif *arvif;
-+ int vdev_id;
-+ int peer_status;
-+ int peer_reason;
-+ u8 reason;
-+
-+ if (skb->len < sizeof(*ev)) {
-+ ath10k_err(ar, "received tdls peer event with invalid size (%d bytes)\n",
-+ skb->len);
-+ return;
-+ }
-+
-+ ev = (struct wmi_tdls_peer_event *)skb->data;
-+ vdev_id = __le32_to_cpu(ev->vdev_id);
-+ peer_status = __le32_to_cpu(ev->peer_status);
-+ peer_reason = __le32_to_cpu(ev->peer_reason);
-+
-+ spin_lock_bh(&ar->data_lock);
-+ peer = ath10k_peer_find(ar, vdev_id, ev->peer_macaddr.addr);
-+ spin_unlock_bh(&ar->data_lock);
-+
-+ if (!peer) {
-+ ath10k_warn(ar, "failed to find peer entry for %pM\n",
-+ ev->peer_macaddr.addr);
-+ return;
-+ }
-+
-+ switch (peer_status) {
-+ case WMI_TDLS_SHOULD_TEARDOWN:
-+ switch (peer_reason) {
-+ case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
-+ case WMI_TDLS_TEARDOWN_REASON_NO_RESPONSE:
-+ case WMI_TDLS_TEARDOWN_REASON_RSSI:
-+ reason = WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE;
-+ break;
-+ default:
-+ reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
-+ break;
-+ }
-+
-+ arvif = ath10k_get_arvif(ar, vdev_id);
-+ if (!arvif) {
-+ ath10k_warn(ar, "received tdls peer event for invalid vdev id %u\n",
-+ vdev_id);
-+ return;
-+ }
-+
-+ ieee80211_tdls_oper_request(arvif->vif, ev->peer_macaddr.addr,
-+ NL80211_TDLS_TEARDOWN, reason,
-+ GFP_ATOMIC);
-+
-+ ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ "received tdls teardown event for peer %pM reason %u\n",
-+ ev->peer_macaddr.addr, peer_reason);
-+ break;
-+ default:
-+ ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ "received unknown tdls peer event %u\n",
-+ peer_status);
-+ break;
-+ }
-+}
-+
- void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb)
- {
- ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PDEV_FTM_INTG_EVENTID\n");
-@@ -5478,6 +5547,9 @@ static void ath10k_wmi_10_4_op_rx(struct
- case WMI_10_4_PDEV_TPC_CONFIG_EVENTID:
- ath10k_wmi_event_pdev_tpc_config(ar, skb);
- break;
-+ case WMI_10_4_TDLS_PEER_EVENTID:
-+ ath10k_wmi_handle_tdls_peer_event(ar, skb);
-+ break;
- default:
- ath10k_warn(ar, "Unknown eventid: %d\n", id);
- break;
+++ /dev/null
-From 229329ff345f80c95202eaf2d7a0f2910c06144e Mon Sep 17 00:00:00 2001
-From: Rakesh Pillai <pillair@qti.qualcomm.com>
-Date: Mon, 11 Dec 2017 19:52:52 +0530
-Subject: [PATCH] ath10k: wmi: modify svc bitmap parsing for wcn3990
-
-Due to the limitation of wmi tlv parsing logic, if there are
-two parameters in a wmi event with same tlv tag, we can get only
-the last value, as it overwrites the prev value of the same tlv tag.
-
-The service ready event in wcn3990 contains two parameters of the
-same tag UINT32, due to which the svc bitmap is overwritten with the
-DBS support parameter.
-
-Refactor the service ready event parsing to allow parsing two tlv
-of the same tag UINT32 for wcn3990.
-
-Signed-off-by: Rakesh Pillai <pillair@qti.qualcomm.com>
-Signed-off-by: Govind Singh <govinds@qti.qualcomm.com>
-Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
----
- drivers/net/wireless/ath/ath10k/mac.c | 4 +-
- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 61 ++++++++++++++++++++++++-------
- drivers/net/wireless/ath/ath10k/wmi-tlv.h | 46 +++++++++++++++++++++++
- drivers/net/wireless/ath/ath10k/wmi.h | 1 +
- 4 files changed, 97 insertions(+), 15 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -3574,7 +3574,9 @@ ath10k_mac_tx_h_get_txpath(struct ath10k
- return ATH10K_MAC_TX_HTT;
- case ATH10K_HW_TXRX_MGMT:
- if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
-- ar->running_fw->fw_file.fw_features))
-+ ar->running_fw->fw_file.fw_features) ||
-+ test_bit(WMI_SERVICE_MGMT_TX_WMI,
-+ ar->wmi.svc_map))
- return ATH10K_MAC_TX_WMI_MGMT;
- else if (ar->htt.target_version_major >= 3)
- return ATH10K_MAC_TX_HTT;
---- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
-@@ -917,33 +917,69 @@ ath10k_wmi_tlv_parse_mem_reqs(struct ath
- return -ENOMEM;
- }
-
-+struct wmi_tlv_svc_rdy_parse {
-+ const struct hal_reg_capabilities *reg;
-+ const struct wmi_tlv_svc_rdy_ev *ev;
-+ const __le32 *svc_bmap;
-+ const struct wlan_host_mem_req *mem_reqs;
-+ bool svc_bmap_done;
-+ bool dbs_hw_mode_done;
-+};
-+
-+static int ath10k_wmi_tlv_svc_rdy_parse(struct ath10k *ar, u16 tag, u16 len,
-+ const void *ptr, void *data)
-+{
-+ struct wmi_tlv_svc_rdy_parse *svc_rdy = data;
-+
-+ switch (tag) {
-+ case WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT:
-+ svc_rdy->ev = ptr;
-+ break;
-+ case WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES:
-+ svc_rdy->reg = ptr;
-+ break;
-+ case WMI_TLV_TAG_ARRAY_STRUCT:
-+ svc_rdy->mem_reqs = ptr;
-+ break;
-+ case WMI_TLV_TAG_ARRAY_UINT32:
-+ if (!svc_rdy->svc_bmap_done) {
-+ svc_rdy->svc_bmap_done = true;
-+ svc_rdy->svc_bmap = ptr;
-+ } else if (!svc_rdy->dbs_hw_mode_done) {
-+ svc_rdy->dbs_hw_mode_done = true;
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ return 0;
-+}
-+
- static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
- struct sk_buff *skb,
- struct wmi_svc_rdy_ev_arg *arg)
- {
-- const void **tb;
- const struct hal_reg_capabilities *reg;
- const struct wmi_tlv_svc_rdy_ev *ev;
- const __le32 *svc_bmap;
- const struct wlan_host_mem_req *mem_reqs;
-+ struct wmi_tlv_svc_rdy_parse svc_rdy = { };
- int ret;
-
-- tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
-- if (IS_ERR(tb)) {
-- ret = PTR_ERR(tb);
-+ ret = ath10k_wmi_tlv_iter(ar, skb->data, skb->len,
-+ ath10k_wmi_tlv_svc_rdy_parse, &svc_rdy);
-+ if (ret) {
- ath10k_warn(ar, "failed to parse tlv: %d\n", ret);
- return ret;
- }
-
-- ev = tb[WMI_TLV_TAG_STRUCT_SERVICE_READY_EVENT];
-- reg = tb[WMI_TLV_TAG_STRUCT_HAL_REG_CAPABILITIES];
-- svc_bmap = tb[WMI_TLV_TAG_ARRAY_UINT32];
-- mem_reqs = tb[WMI_TLV_TAG_ARRAY_STRUCT];
-+ ev = svc_rdy.ev;
-+ reg = svc_rdy.reg;
-+ svc_bmap = svc_rdy.svc_bmap;
-+ mem_reqs = svc_rdy.mem_reqs;
-
-- if (!ev || !reg || !svc_bmap || !mem_reqs) {
-- kfree(tb);
-+ if (!ev || !reg || !svc_bmap || !mem_reqs)
- return -EPROTO;
-- }
-
- /* This is an internal ABI compatibility check for WMI TLV so check it
- * here instead of the generic WMI code.
-@@ -961,7 +997,6 @@ static int ath10k_wmi_tlv_op_pull_svc_rd
- __le32_to_cpu(ev->abi.abi_ver_ns1) != WMI_TLV_ABI_VER_NS1 ||
- __le32_to_cpu(ev->abi.abi_ver_ns2) != WMI_TLV_ABI_VER_NS2 ||
- __le32_to_cpu(ev->abi.abi_ver_ns3) != WMI_TLV_ABI_VER_NS3) {
-- kfree(tb);
- return -ENOTSUPP;
- }
-
-@@ -982,12 +1017,10 @@ static int ath10k_wmi_tlv_op_pull_svc_rd
- ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
- ath10k_wmi_tlv_parse_mem_reqs, arg);
- if (ret) {
-- kfree(tb);
- ath10k_warn(ar, "failed to parse mem_reqs tlv: %d\n", ret);
- return ret;
- }
-
-- kfree(tb);
- return 0;
- }
-
---- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
-@@ -965,6 +965,50 @@ enum wmi_tlv_service {
- WMI_TLV_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT,
- WMI_TLV_SERVICE_MDNS_OFFLOAD,
- WMI_TLV_SERVICE_SAP_AUTH_OFFLOAD,
-+ WMI_TLV_SERVICE_DUAL_BAND_SIMULTANEOUS_SUPPORT,
-+ WMI_TLV_SERVICE_OCB,
-+ WMI_TLV_SERVICE_AP_ARPNS_OFFLOAD,
-+ WMI_TLV_SERVICE_PER_BAND_CHAINMASK_SUPPORT,
-+ WMI_TLV_SERVICE_PACKET_FILTER_OFFLOAD,
-+ WMI_TLV_SERVICE_MGMT_TX_HTT,
-+ WMI_TLV_SERVICE_MGMT_TX_WMI,
-+ WMI_TLV_SERVICE_EXT_MSG,
-+ WMI_TLV_SERVICE_MAWC,
-+ WMI_TLV_SERVICE_PEER_ASSOC_CONF,
-+ WMI_TLV_SERVICE_EGAP,
-+ WMI_TLV_SERVICE_STA_PMF_OFFLOAD,
-+ WMI_TLV_SERVICE_UNIFIED_WOW_CAPABILITY,
-+ WMI_TLV_SERVICE_ENHANCED_PROXY_STA,
-+ WMI_TLV_SERVICE_ATF,
-+ WMI_TLV_SERVICE_COEX_GPIO,
-+ WMI_TLV_SERVICE_AUX_SPECTRAL_INTF,
-+ WMI_TLV_SERVICE_AUX_CHAN_LOAD_INTF,
-+ WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64,
-+ WMI_TLV_SERVICE_ENTERPRISE_MESH,
-+ WMI_TLV_SERVICE_RESTRT_CHNL_SUPPORT,
-+ WMI_TLV_SERVICE_BPF_OFFLOAD,
-+ WMI_TLV_SERVICE_SYNC_DELETE_CMDS,
-+ WMI_TLV_SERVICE_SMART_ANTENNA_SW_SUPPORT,
-+ WMI_TLV_SERVICE_SMART_ANTENNA_HW_SUPPORT,
-+ WMI_TLV_SERVICE_RATECTRL_LIMIT_MAX_MIN_RATES,
-+ WMI_TLV_SERVICE_NAN_DATA,
-+ WMI_TLV_SERVICE_NAN_RTT,
-+ WMI_TLV_SERVICE_11AX,
-+ WMI_TLV_SERVICE_DEPRECATED_REPLACE,
-+ WMI_TLV_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE,
-+ WMI_TLV_SERVICE_ENHANCED_MCAST_FILTER,
-+ WMI_TLV_SERVICE_PERIODIC_CHAN_STAT_SUPPORT,
-+ WMI_TLV_SERVICE_MESH_11S,
-+ WMI_TLV_SERVICE_HALF_RATE_QUARTER_RATE_SUPPORT,
-+ WMI_TLV_SERVICE_VDEV_RX_FILTER,
-+ WMI_TLV_SERVICE_P2P_LISTEN_OFFLOAD_SUPPORT,
-+ WMI_TLV_SERVICE_MARK_FIRST_WAKEUP_PACKET,
-+ WMI_TLV_SERVICE_MULTIPLE_MCAST_FILTER_SET,
-+ WMI_TLV_SERVICE_HOST_MANAGED_RX_REORDER,
-+ WMI_TLV_SERVICE_FLASH_RDWR_SUPPORT,
-+ WMI_TLV_SERVICE_WLAN_STATS_REPORT,
-+ WMI_TLV_SERVICE_TX_MSDU_ID_NEW_PARTITION_SUPPORT,
-+ WMI_TLV_SERVICE_DFS_PHYERR_OFFLOAD,
- };
-
- #define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
-@@ -1121,6 +1165,8 @@ wmi_tlv_svc_map(const __le32 *in, unsign
- WMI_SERVICE_MDNS_OFFLOAD, len);
- SVCMAP(WMI_TLV_SERVICE_SAP_AUTH_OFFLOAD,
- WMI_SERVICE_SAP_AUTH_OFFLOAD, len);
-+ SVCMAP(WMI_TLV_SERVICE_MGMT_TX_WMI,
-+ WMI_SERVICE_MGMT_TX_WMI, len);
- }
-
- #undef SVCMAP
---- a/drivers/net/wireless/ath/ath10k/wmi.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -195,6 +195,7 @@ enum wmi_service {
- WMI_SERVICE_SMART_LOGGING_SUPPORT,
- WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE,
- WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
-+ WMI_SERVICE_MGMT_TX_WMI,
-
- /* keep last */
- WMI_SERVICE_MAX,
+++ /dev/null
-From 14d65775687cb3a6f76a52f48f4be27a522bb396 Mon Sep 17 00:00:00 2001
-From: Balaji Pothunoori <bpothuno@qti.qualcomm.com>
-Date: Thu, 21 Dec 2017 20:00:42 +0530
-Subject: [PATCH] ath10k: advertise TDLS wider bandwidth support for 5GHz
-
-Enable TDLS wider bandwidth support for 5GHz based on firmware wmi capabilities.
-
-This patch is required for chipset QCA9888. Tested with firmware version
-10.4-3.5.1-00018.
-
-Signed-off-by: Balaji Pothunoori <bpothuno@qti.qualcomm.com>
-Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
----
- drivers/net/wireless/ath/ath10k/mac.c | 3 ++-
- drivers/net/wireless/ath/ath10k/wmi.h | 5 +++++
- 2 files changed, 7 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -8236,7 +8236,8 @@ int ath10k_mac_register(struct ath10k *a
- if (test_bit(WMI_SERVICE_TDLS, ar->wmi.svc_map) ||
- test_bit(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, ar->wmi.svc_map)) {
- ar->hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
-- ieee80211_hw_set(ar->hw, TDLS_WIDER_BW);
-+ if (test_bit(WMI_SERVICE_TDLS_WIDER_BANDWIDTH, ar->wmi.svc_map))
-+ ieee80211_hw_set(ar->hw, TDLS_WIDER_BW);
- }
-
- ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
---- a/drivers/net/wireless/ath/ath10k/wmi.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -196,6 +196,7 @@ enum wmi_service {
- WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE,
- WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
- WMI_SERVICE_MGMT_TX_WMI,
-+ WMI_SERVICE_TDLS_WIDER_BANDWIDTH,
-
- /* keep last */
- WMI_SERVICE_MAX,
-@@ -337,6 +338,7 @@ enum wmi_10_4_service {
- WMI_10_4_SERVICE_TDLS_UAPSD_SLEEP_STA,
- WMI_10_4_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE,
- WMI_10_4_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
-+ WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH,
- };
-
- static inline char *wmi_service_name(int service_id)
-@@ -445,6 +447,7 @@ static inline char *wmi_service_name(int
- SVCSTR(WMI_SERVICE_SMART_LOGGING_SUPPORT);
- SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE);
- SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY);
-+ SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH);
- default:
- return NULL;
- }
-@@ -741,6 +744,8 @@ static inline void wmi_10_4_svc_map(cons
- WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE, len);
- SVCMAP(WMI_10_4_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
- WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, len);
-+ SVCMAP(WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH,
-+ WMI_SERVICE_TDLS_WIDER_BANDWIDTH, len);
- }
-
- #undef SVCMAP
+++ /dev/null
-From bc64d05220f3e34cf432a166b83c8fff14cd7a3d Mon Sep 17 00:00:00 2001
-From: Maharaja Kennadyrajan <mkenna@codeaurora.org>
-Date: Wed, 14 Mar 2018 12:14:08 +0200
-Subject: [PATCH] ath10k: debugfs support to get final TPC stats for 10.4
- variants
-
-Export the final Transmit Power Control (TPC) value, which is the
-minimum of control power and existing TPC value to user space via
-a new debugfs file "tpc_stats_final" to help with debugging.
-It works with the new wmi cmd and event introduced in 10.4 firmware
-branch.
-
-WMI command ID: WMI_PDEV_GET_TPC_TABLE_CMDID
-WMI event ID: WMI_PDEV_TPC_TABLE_EVENTID
-
-cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats_final
-
-$ cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats_final
-
-TPC config for channel 5180 mode 10
-
-CTL = 0x 0 Reg. Domain = 58
-Antenna Gain = 0 Reg. Max Antenna Gain = 0
-Power Limit = 60 Reg. Max Power = 60
-Num tx chains = 2 Num supported rates = 109
-
-******************* CDD POWER TABLE ****************
-
-No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3
-0 CCK 0x40 0 0
-1 CCK 0x41 0 0
-[...]
-107 HTCUP 0x 0 46 46
-108 HTCUP 0x 0 46 46
-
-******************* STBC POWER TABLE ****************
-
-No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3
-0 CCK 0x40 0 0
-1 CCK 0x41 0 0
-[...]
-107 HTCUP 0x 0 46 46
-108 HTCUP 0x 0 46 46
-
-***********************************
-TXBF not supported
-**********************************
-
-The existing tpc_stats debugfs file provides the dump
-which is minimum of target power and regulatory domain.
-
-cat /sys/kernel/debug/ieee80211/phyX/ath10k/tpc_stats
-
-Hardware_used: QCA4019
-Firmware version: firmware-5.bin_10.4-3.0-00209
-
-Signed-off-by: Maharaja Kennadyrajan <mkenna@codeaurora.org>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/core.h | 22 +++
- drivers/net/wireless/ath/ath10k/debug.c | 107 +++++++++++
- drivers/net/wireless/ath/ath10k/debug.h | 10 +
- drivers/net/wireless/ath/ath10k/wmi-ops.h | 20 ++
- drivers/net/wireless/ath/ath10k/wmi.c | 308 ++++++++++++++++++++++++++++--
- drivers/net/wireless/ath/ath10k/wmi.h | 66 +++++++
- 6 files changed, 518 insertions(+), 15 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/core.h
-+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -322,6 +322,27 @@ struct ath10k_tpc_stats {
- struct ath10k_tpc_table tpc_table[WMI_TPC_FLAG];
- };
-
-+struct ath10k_tpc_table_final {
-+ u32 pream_idx[WMI_TPC_FINAL_RATE_MAX];
-+ u8 rate_code[WMI_TPC_FINAL_RATE_MAX];
-+ char tpc_value[WMI_TPC_FINAL_RATE_MAX][WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE];
-+};
-+
-+struct ath10k_tpc_stats_final {
-+ u32 reg_domain;
-+ u32 chan_freq;
-+ u32 phy_mode;
-+ u32 twice_antenna_reduction;
-+ u32 twice_max_rd_power;
-+ s32 twice_antenna_gain;
-+ u32 power_limit;
-+ u32 num_tx_chain;
-+ u32 ctl;
-+ u32 rate_max;
-+ u8 flag[WMI_TPC_FLAG];
-+ struct ath10k_tpc_table_final tpc_table_final[WMI_TPC_FLAG];
-+};
-+
- struct ath10k_dfs_stats {
- u32 phy_errors;
- u32 pulses_total;
-@@ -482,6 +503,7 @@ struct ath10k_debug {
-
- /* used for tpc-dump storage, protected by data-lock */
- struct ath10k_tpc_stats *tpc_stats;
-+ struct ath10k_tpc_stats_final *tpc_stats_final;
-
- struct completion tpc_complete;
-
---- a/drivers/net/wireless/ath/ath10k/debug.c
-+++ b/drivers/net/wireless/ath/ath10k/debug.c
-@@ -1737,6 +1737,19 @@ void ath10k_debug_tpc_stats_process(stru
- spin_unlock_bh(&ar->data_lock);
- }
-
-+void
-+ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
-+ struct ath10k_tpc_stats_final *tpc_stats)
-+{
-+ spin_lock_bh(&ar->data_lock);
-+
-+ kfree(ar->debug.tpc_stats_final);
-+ ar->debug.tpc_stats_final = tpc_stats;
-+ complete(&ar->debug.tpc_complete);
-+
-+ spin_unlock_bh(&ar->data_lock);
-+}
-+
- static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
- unsigned int j, char *buf, size_t *len)
- {
-@@ -2400,6 +2413,95 @@ static const struct file_operations fops
- .llseek = default_llseek,
- };
-
-+static int ath10k_debug_tpc_stats_final_request(struct ath10k *ar)
-+{
-+ int ret;
-+ unsigned long time_left;
-+
-+ lockdep_assert_held(&ar->conf_mutex);
-+
-+ reinit_completion(&ar->debug.tpc_complete);
-+
-+ ret = ath10k_wmi_pdev_get_tpc_table_cmdid(ar, WMI_TPC_CONFIG_PARAM);
-+ if (ret) {
-+ ath10k_warn(ar, "failed to request tpc table cmdid: %d\n", ret);
-+ return ret;
-+ }
-+
-+ time_left = wait_for_completion_timeout(&ar->debug.tpc_complete,
-+ 1 * HZ);
-+ if (time_left == 0)
-+ return -ETIMEDOUT;
-+
-+ return 0;
-+}
-+
-+static int ath10k_tpc_stats_final_open(struct inode *inode, struct file *file)
-+{
-+ struct ath10k *ar = inode->i_private;
-+ void *buf;
-+ int ret;
-+
-+ mutex_lock(&ar->conf_mutex);
-+
-+ if (ar->state != ATH10K_STATE_ON) {
-+ ret = -ENETDOWN;
-+ goto err_unlock;
-+ }
-+
-+ buf = vmalloc(ATH10K_TPC_CONFIG_BUF_SIZE);
-+ if (!buf) {
-+ ret = -ENOMEM;
-+ goto err_unlock;
-+ }
-+
-+ ret = ath10k_debug_tpc_stats_final_request(ar);
-+ if (ret) {
-+ ath10k_warn(ar, "failed to request tpc stats final: %d\n",
-+ ret);
-+ goto err_free;
-+ }
-+
-+ ath10k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
-+ file->private_data = buf;
-+
-+ mutex_unlock(&ar->conf_mutex);
-+ return 0;
-+
-+err_free:
-+ vfree(buf);
-+
-+err_unlock:
-+ mutex_unlock(&ar->conf_mutex);
-+ return ret;
-+}
-+
-+static int ath10k_tpc_stats_final_release(struct inode *inode,
-+ struct file *file)
-+{
-+ vfree(file->private_data);
-+
-+ return 0;
-+}
-+
-+static ssize_t ath10k_tpc_stats_final_read(struct file *file,
-+ char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ const char *buf = file->private_data;
-+ unsigned int len = strlen(buf);
-+
-+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-+}
-+
-+static const struct file_operations fops_tpc_stats_final = {
-+ .open = ath10k_tpc_stats_final_open,
-+ .release = ath10k_tpc_stats_final_release,
-+ .read = ath10k_tpc_stats_final_read,
-+ .owner = THIS_MODULE,
-+ .llseek = default_llseek,
-+};
-+
- int ath10k_debug_create(struct ath10k *ar)
- {
- ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
-@@ -2525,6 +2627,11 @@ int ath10k_debug_register(struct ath10k
- debugfs_create_file("fw_checksums", 0400, ar->debug.debugfs_phy, ar,
- &fops_fw_checksums);
-
-+ if (test_bit(WMI_SERVICE_TPC_STATS_FINAL, ar->wmi.svc_map))
-+ debugfs_create_file("tpc_stats_final", 0400,
-+ ar->debug.debugfs_phy, ar,
-+ &fops_tpc_stats_final);
-+
- return 0;
- }
-
---- a/drivers/net/wireless/ath/ath10k/debug.h
-+++ b/drivers/net/wireless/ath/ath10k/debug.h
-@@ -84,6 +84,9 @@ void ath10k_debug_unregister(struct ath1
- void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
- void ath10k_debug_tpc_stats_process(struct ath10k *ar,
- struct ath10k_tpc_stats *tpc_stats);
-+void
-+ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
-+ struct ath10k_tpc_stats_final *tpc_stats);
- struct ath10k_fw_crash_data *
- ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
-
-@@ -151,6 +154,13 @@ static inline void ath10k_debug_tpc_stat
- {
- kfree(tpc_stats);
- }
-+
-+static inline void
-+ath10k_debug_tpc_stats_final_process(struct ath10k *ar,
-+ struct ath10k_tpc_stats_final *tpc_stats)
-+{
-+ kfree(tpc_stats);
-+}
-
- static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer,
- int len)
---- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
-@@ -197,6 +197,9 @@ struct wmi_ops {
- (struct ath10k *ar,
- enum wmi_bss_survey_req_type type);
- struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value);
-+ struct sk_buff *(*gen_pdev_get_tpc_table_cmdid)(struct ath10k *ar,
-+ u32 param);
-+
- };
-
- int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
-@@ -1418,4 +1421,21 @@ ath10k_wmi_echo(struct ath10k *ar, u32 v
- return ath10k_wmi_cmd_send(ar, skb, wmi->cmd->echo_cmdid);
- }
-
-+static inline int
-+ath10k_wmi_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param)
-+{
-+ struct sk_buff *skb;
-+
-+ if (!ar->wmi.ops->gen_pdev_get_tpc_table_cmdid)
-+ return -EOPNOTSUPP;
-+
-+ skb = ar->wmi.ops->gen_pdev_get_tpc_table_cmdid(ar, param);
-+
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ return ath10k_wmi_cmd_send(ar, skb,
-+ ar->wmi.cmd->pdev_get_tpc_table_cmdid);
-+}
-+
- #endif
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -1,6 +1,7 @@
- /*
- * Copyright (c) 2005-2011 Atheros Communications Inc.
- * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
-+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
-@@ -196,6 +197,7 @@ static struct wmi_cmd_map wmi_cmd_map =
- .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
- .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
-+ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
- };
-
- /* 10.X WMI cmd track */
-@@ -362,6 +364,7 @@ static struct wmi_cmd_map wmi_10x_cmd_ma
- .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
- .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
-+ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
- };
-
- /* 10.2.4 WMI cmd track */
-@@ -528,6 +531,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd
- .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_bss_chan_info_request_cmdid =
- WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
-+ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
- };
-
- /* 10.4 WMI cmd track */
-@@ -1480,6 +1484,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_m
- .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
-+ .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
- };
-
- static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
-@@ -4313,19 +4318,11 @@ static void ath10k_tpc_config_disp_table
- }
- }
-
--void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
-+void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table,
-+ u32 num_tx_chain)
- {
-- u32 i, j, pream_idx, num_tx_chain;
-- u8 rate_code[WMI_TPC_RATE_MAX], rate_idx;
-- u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
-- struct wmi_pdev_tpc_config_event *ev;
-- struct ath10k_tpc_stats *tpc_stats;
--
-- ev = (struct wmi_pdev_tpc_config_event *)skb->data;
--
-- tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
-- if (!tpc_stats)
-- return;
-+ u32 i, j, pream_idx;
-+ u8 rate_idx;
-
- /* Create the rate code table based on the chains supported */
- rate_idx = 0;
-@@ -4349,8 +4346,6 @@ void ath10k_wmi_event_pdev_tpc_config(st
- pream_table[pream_idx] = rate_idx;
- pream_idx++;
-
-- num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
--
- /* Fill HT20 rate code */
- for (i = 0; i < num_tx_chain; i++) {
- for (j = 0; j < 8; j++) {
-@@ -4374,7 +4369,7 @@ void ath10k_wmi_event_pdev_tpc_config(st
- pream_idx++;
-
- /* Fill VHT20 rate code */
-- for (i = 0; i < __le32_to_cpu(ev->num_tx_chain); i++) {
-+ for (i = 0; i < num_tx_chain; i++) {
- for (j = 0; j < 10; j++) {
- rate_code[rate_idx] =
- ATH10K_HW_RATECODE(j, i, WMI_RATE_PREAMBLE_VHT);
-@@ -4418,6 +4413,26 @@ void ath10k_wmi_event_pdev_tpc_config(st
- ATH10K_HW_RATECODE(0, 0, WMI_RATE_PREAMBLE_OFDM);
-
- pream_table[pream_idx] = ATH10K_TPC_PREAM_TABLE_END;
-+}
-+
-+void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
-+{
-+ u32 num_tx_chain;
-+ u8 rate_code[WMI_TPC_RATE_MAX];
-+ u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
-+ struct wmi_pdev_tpc_config_event *ev;
-+ struct ath10k_tpc_stats *tpc_stats;
-+
-+ ev = (struct wmi_pdev_tpc_config_event *)skb->data;
-+
-+ tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
-+ if (!tpc_stats)
-+ return;
-+
-+ num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
-+
-+ ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table,
-+ num_tx_chain);
-
- tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq);
- tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode);
-@@ -4457,6 +4472,246 @@ void ath10k_wmi_event_pdev_tpc_config(st
- __le32_to_cpu(ev->rate_max));
- }
-
-+static u8
-+ath10k_wmi_tpc_final_get_rate(struct ath10k *ar,
-+ struct wmi_pdev_tpc_final_table_event *ev,
-+ u32 rate_idx, u32 num_chains,
-+ u32 rate_code, u8 type, u32 pream_idx)
-+{
-+ u8 tpc, num_streams, preamble, ch, stm_idx;
-+ s8 pow_agcdd, pow_agstbc, pow_agtxbf;
-+ int pream;
-+
-+ num_streams = ATH10K_HW_NSS(rate_code);
-+ preamble = ATH10K_HW_PREAMBLE(rate_code);
-+ ch = num_chains - 1;
-+ stm_idx = num_streams - 1;
-+ pream = -1;
-+
-+ if (__le32_to_cpu(ev->chan_freq) <= 2483) {
-+ switch (pream_idx) {
-+ case WMI_TPC_PREAM_2GHZ_CCK:
-+ pream = 0;
-+ break;
-+ case WMI_TPC_PREAM_2GHZ_OFDM:
-+ pream = 1;
-+ break;
-+ case WMI_TPC_PREAM_2GHZ_HT20:
-+ case WMI_TPC_PREAM_2GHZ_VHT20:
-+ pream = 2;
-+ break;
-+ case WMI_TPC_PREAM_2GHZ_HT40:
-+ case WMI_TPC_PREAM_2GHZ_VHT40:
-+ pream = 3;
-+ break;
-+ case WMI_TPC_PREAM_2GHZ_VHT80:
-+ pream = 4;
-+ break;
-+ default:
-+ pream = -1;
-+ break;
-+ }
-+ }
-+
-+ if (__le32_to_cpu(ev->chan_freq) >= 5180) {
-+ switch (pream_idx) {
-+ case WMI_TPC_PREAM_5GHZ_OFDM:
-+ pream = 0;
-+ break;
-+ case WMI_TPC_PREAM_5GHZ_HT20:
-+ case WMI_TPC_PREAM_5GHZ_VHT20:
-+ pream = 1;
-+ break;
-+ case WMI_TPC_PREAM_5GHZ_HT40:
-+ case WMI_TPC_PREAM_5GHZ_VHT40:
-+ pream = 2;
-+ break;
-+ case WMI_TPC_PREAM_5GHZ_VHT80:
-+ pream = 3;
-+ break;
-+ case WMI_TPC_PREAM_5GHZ_HTCUP:
-+ pream = 4;
-+ break;
-+ default:
-+ pream = -1;
-+ break;
-+ }
-+ }
-+
-+ if (pream == 4)
-+ tpc = min_t(u8, ev->rates_array[rate_idx],
-+ ev->max_reg_allow_pow[ch]);
-+ else
-+ tpc = min_t(u8, min_t(u8, ev->rates_array[rate_idx],
-+ ev->max_reg_allow_pow[ch]),
-+ ev->ctl_power_table[0][pream][stm_idx]);
-+
-+ if (__le32_to_cpu(ev->num_tx_chain) <= 1)
-+ goto out;
-+
-+ if (preamble == WMI_RATE_PREAMBLE_CCK)
-+ goto out;
-+
-+ if (num_chains <= num_streams)
-+ goto out;
-+
-+ switch (type) {
-+ case WMI_TPC_TABLE_TYPE_STBC:
-+ pow_agstbc = ev->max_reg_allow_pow_agstbc[ch - 1][stm_idx];
-+ if (pream == 4)
-+ tpc = min_t(u8, tpc, pow_agstbc);
-+ else
-+ tpc = min_t(u8, min_t(u8, tpc, pow_agstbc),
-+ ev->ctl_power_table[0][pream][stm_idx]);
-+ break;
-+ case WMI_TPC_TABLE_TYPE_TXBF:
-+ pow_agtxbf = ev->max_reg_allow_pow_agtxbf[ch - 1][stm_idx];
-+ if (pream == 4)
-+ tpc = min_t(u8, tpc, pow_agtxbf);
-+ else
-+ tpc = min_t(u8, min_t(u8, tpc, pow_agtxbf),
-+ ev->ctl_power_table[1][pream][stm_idx]);
-+ break;
-+ case WMI_TPC_TABLE_TYPE_CDD:
-+ pow_agcdd = ev->max_reg_allow_pow_agcdd[ch - 1][stm_idx];
-+ if (pream == 4)
-+ tpc = min_t(u8, tpc, pow_agcdd);
-+ else
-+ tpc = min_t(u8, min_t(u8, tpc, pow_agcdd),
-+ ev->ctl_power_table[0][pream][stm_idx]);
-+ break;
-+ default:
-+ ath10k_warn(ar, "unknown wmi tpc final table type: %d\n", type);
-+ tpc = 0;
-+ break;
-+ }
-+
-+out:
-+ return tpc;
-+}
-+
-+static void
-+ath10k_wmi_tpc_stats_final_disp_tables(struct ath10k *ar,
-+ struct wmi_pdev_tpc_final_table_event *ev,
-+ struct ath10k_tpc_stats_final *tpc_stats,
-+ u8 *rate_code, u16 *pream_table, u8 type)
-+{
-+ u32 i, j, pream_idx, flags;
-+ u8 tpc[WMI_TPC_TX_N_CHAIN];
-+ char tpc_value[WMI_TPC_TX_N_CHAIN * WMI_TPC_BUF_SIZE];
-+ char buff[WMI_TPC_BUF_SIZE];
-+
-+ flags = __le32_to_cpu(ev->flags);
-+
-+ switch (type) {
-+ case WMI_TPC_TABLE_TYPE_CDD:
-+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_CDD)) {
-+ ath10k_dbg(ar, ATH10K_DBG_WMI, "CDD not supported\n");
-+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
-+ return;
-+ }
-+ break;
-+ case WMI_TPC_TABLE_TYPE_STBC:
-+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_STBC)) {
-+ ath10k_dbg(ar, ATH10K_DBG_WMI, "STBC not supported\n");
-+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
-+ return;
-+ }
-+ break;
-+ case WMI_TPC_TABLE_TYPE_TXBF:
-+ if (!(flags & WMI_TPC_CONFIG_EVENT_FLAG_TABLE_TXBF)) {
-+ ath10k_dbg(ar, ATH10K_DBG_WMI, "TXBF not supported\n");
-+ tpc_stats->flag[type] = ATH10K_TPC_TABLE_TYPE_FLAG;
-+ return;
-+ }
-+ break;
-+ default:
-+ ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ "invalid table type in wmi tpc event: %d\n", type);
-+ return;
-+ }
-+
-+ pream_idx = 0;
-+ for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) {
-+ memset(tpc_value, 0, sizeof(tpc_value));
-+ memset(buff, 0, sizeof(buff));
-+ if (i == pream_table[pream_idx])
-+ pream_idx++;
-+
-+ for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) {
-+ if (j >= __le32_to_cpu(ev->num_tx_chain))
-+ break;
-+
-+ tpc[j] = ath10k_wmi_tpc_final_get_rate(ar, ev, i, j + 1,
-+ rate_code[i],
-+ type, pream_idx);
-+ snprintf(buff, sizeof(buff), "%8d ", tpc[j]);
-+ strncat(tpc_value, buff, strlen(buff));
-+ }
-+ tpc_stats->tpc_table_final[type].pream_idx[i] = pream_idx;
-+ tpc_stats->tpc_table_final[type].rate_code[i] = rate_code[i];
-+ memcpy(tpc_stats->tpc_table_final[type].tpc_value[i],
-+ tpc_value, sizeof(tpc_value));
-+ }
-+}
-+
-+void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb)
-+{
-+ u32 num_tx_chain;
-+ u8 rate_code[WMI_TPC_FINAL_RATE_MAX];
-+ u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
-+ struct wmi_pdev_tpc_final_table_event *ev;
-+ struct ath10k_tpc_stats_final *tpc_stats;
-+
-+ ev = (struct wmi_pdev_tpc_final_table_event *)skb->data;
-+
-+ tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
-+ if (!tpc_stats)
-+ return;
-+
-+ num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
-+
-+ ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table,
-+ num_tx_chain);
-+
-+ tpc_stats->chan_freq = __le32_to_cpu(ev->chan_freq);
-+ tpc_stats->phy_mode = __le32_to_cpu(ev->phy_mode);
-+ tpc_stats->ctl = __le32_to_cpu(ev->ctl);
-+ tpc_stats->reg_domain = __le32_to_cpu(ev->reg_domain);
-+ tpc_stats->twice_antenna_gain = a_sle32_to_cpu(ev->twice_antenna_gain);
-+ tpc_stats->twice_antenna_reduction =
-+ __le32_to_cpu(ev->twice_antenna_reduction);
-+ tpc_stats->power_limit = __le32_to_cpu(ev->power_limit);
-+ tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power);
-+ tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
-+ tpc_stats->rate_max = __le32_to_cpu(ev->rate_max);
-+
-+ ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
-+ rate_code, pream_table,
-+ WMI_TPC_TABLE_TYPE_CDD);
-+ ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
-+ rate_code, pream_table,
-+ WMI_TPC_TABLE_TYPE_STBC);
-+ ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
-+ rate_code, pream_table,
-+ WMI_TPC_TABLE_TYPE_TXBF);
-+
-+ ath10k_debug_tpc_stats_final_process(ar, tpc_stats);
-+
-+ ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ "wmi event tpc final table channel %d mode %d ctl %d regd %d gain %d %d limit %d max_power %d tx_chanins %d rates %d\n",
-+ __le32_to_cpu(ev->chan_freq),
-+ __le32_to_cpu(ev->phy_mode),
-+ __le32_to_cpu(ev->ctl),
-+ __le32_to_cpu(ev->reg_domain),
-+ a_sle32_to_cpu(ev->twice_antenna_gain),
-+ __le32_to_cpu(ev->twice_antenna_reduction),
-+ __le32_to_cpu(ev->power_limit),
-+ __le32_to_cpu(ev->twice_max_rd_power) / 2,
-+ __le32_to_cpu(ev->num_tx_chain),
-+ __le32_to_cpu(ev->rate_max));
-+}
-+
- static void
- ath10k_wmi_handle_tdls_peer_event(struct ath10k *ar, struct sk_buff *skb)
- {
-@@ -5550,6 +5805,9 @@ static void ath10k_wmi_10_4_op_rx(struct
- case WMI_10_4_TDLS_PEER_EVENTID:
- ath10k_wmi_handle_tdls_peer_event(ar, skb);
- break;
-+ case WMI_10_4_PDEV_TPC_TABLE_EVENTID:
-+ ath10k_wmi_event_tpc_final_table(ar, skb);
-+ break;
- default:
- ath10k_warn(ar, "Unknown eventid: %d\n", id);
- break;
-@@ -7990,6 +8248,24 @@ static u32 ath10k_wmi_prepare_peer_qos(u
- }
-
- static struct sk_buff *
-+ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param)
-+{
-+ struct wmi_pdev_get_tpc_table_cmd *cmd;
-+ struct sk_buff *skb;
-+
-+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ if (!skb)
-+ return ERR_PTR(-ENOMEM);
-+
-+ cmd = (struct wmi_pdev_get_tpc_table_cmd *)skb->data;
-+ cmd->param = __cpu_to_le32(param);
-+
-+ ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ "wmi pdev get tpc table param:%d\n", param);
-+ return skb;
-+}
-+
-+static struct sk_buff *
- ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar,
- const struct wmi_tdls_peer_update_cmd_arg *arg,
- const struct wmi_tdls_peer_capab_arg *cap,
-@@ -8430,6 +8706,8 @@ static const struct wmi_ops wmi_10_4_ops
- .ext_resource_config = ath10k_wmi_10_4_ext_resource_config,
- .gen_update_fw_tdls_state = ath10k_wmi_10_4_gen_update_fw_tdls_state,
- .gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update,
-+ .gen_pdev_get_tpc_table_cmdid =
-+ ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid,
-
- /* shared with 10.2 */
- .pull_echo_ev = ath10k_wmi_op_pull_echo_ev,
---- a/drivers/net/wireless/ath/ath10k/wmi.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -1,6 +1,7 @@
- /*
- * Copyright (c) 2005-2011 Atheros Communications Inc.
- * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
-+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
-@@ -197,6 +198,9 @@ enum wmi_service {
- WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
- WMI_SERVICE_MGMT_TX_WMI,
- WMI_SERVICE_TDLS_WIDER_BANDWIDTH,
-+ WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
-+ WMI_SERVICE_HOST_DFS_CHECK_SUPPORT,
-+ WMI_SERVICE_TPC_STATS_FINAL,
-
- /* keep last */
- WMI_SERVICE_MAX,
-@@ -339,6 +343,9 @@ enum wmi_10_4_service {
- WMI_10_4_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE,
- WMI_10_4_SERVICE_TDLS_EXPLICIT_MODE_ONLY,
- WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH,
-+ WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
-+ WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT,
-+ WMI_10_4_SERVICE_TPC_STATS_FINAL,
- };
-
- static inline char *wmi_service_name(int service_id)
-@@ -448,6 +455,9 @@ static inline char *wmi_service_name(int
- SVCSTR(WMI_SERVICE_TDLS_CONN_TRACKER_IN_HOST_MODE);
- SVCSTR(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY);
- SVCSTR(WMI_SERVICE_TDLS_WIDER_BANDWIDTH);
-+ SVCSTR(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS);
-+ SVCSTR(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT);
-+ SVCSTR(WMI_SERVICE_TPC_STATS_FINAL);
- default:
- return NULL;
- }
-@@ -746,6 +756,12 @@ static inline void wmi_10_4_svc_map(cons
- WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, len);
- SVCMAP(WMI_10_4_SERVICE_TDLS_WIDER_BANDWIDTH,
- WMI_SERVICE_TDLS_WIDER_BANDWIDTH, len);
-+ SVCMAP(WMI_10_4_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS,
-+ WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, len);
-+ SVCMAP(WMI_10_4_SERVICE_HOST_DFS_CHECK_SUPPORT,
-+ WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, len);
-+ SVCMAP(WMI_10_4_SERVICE_TPC_STATS_FINAL,
-+ WMI_SERVICE_TPC_STATS_FINAL, len);
- }
-
- #undef SVCMAP
-@@ -3992,10 +4008,12 @@ struct wmi_pdev_get_tpc_config_cmd {
-
- #define WMI_TPC_CONFIG_PARAM 1
- #define WMI_TPC_RATE_MAX 160
-+#define WMI_TPC_FINAL_RATE_MAX 240
- #define WMI_TPC_TX_N_CHAIN 4
- #define WMI_TPC_PREAM_TABLE_MAX 10
- #define WMI_TPC_FLAG 3
- #define WMI_TPC_BUF_SIZE 10
-+#define WMI_TPC_BEAMFORMING 2
-
- enum wmi_tpc_table_type {
- WMI_TPC_TABLE_TYPE_CDD = 0,
-@@ -4038,6 +4056,51 @@ enum wmi_tp_scale {
- WMI_TP_SCALE_SIZE = 5, /* max num of enum */
- };
-
-+struct wmi_pdev_tpc_final_table_event {
-+ __le32 reg_domain;
-+ __le32 chan_freq;
-+ __le32 phy_mode;
-+ __le32 twice_antenna_reduction;
-+ __le32 twice_max_rd_power;
-+ a_sle32 twice_antenna_gain;
-+ __le32 power_limit;
-+ __le32 rate_max;
-+ __le32 num_tx_chain;
-+ __le32 ctl;
-+ __le32 flags;
-+ s8 max_reg_allow_pow[WMI_TPC_TX_N_CHAIN];
-+ s8 max_reg_allow_pow_agcdd[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN];
-+ s8 max_reg_allow_pow_agstbc[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN];
-+ s8 max_reg_allow_pow_agtxbf[WMI_TPC_TX_N_CHAIN][WMI_TPC_TX_N_CHAIN];
-+ u8 rates_array[WMI_TPC_FINAL_RATE_MAX];
-+ u8 ctl_power_table[WMI_TPC_BEAMFORMING][WMI_TPC_TX_N_CHAIN]
-+ [WMI_TPC_TX_N_CHAIN];
-+} __packed;
-+
-+struct wmi_pdev_get_tpc_table_cmd {
-+ __le32 param;
-+} __packed;
-+
-+enum wmi_tpc_pream_2ghz {
-+ WMI_TPC_PREAM_2GHZ_CCK = 0,
-+ WMI_TPC_PREAM_2GHZ_OFDM,
-+ WMI_TPC_PREAM_2GHZ_HT20,
-+ WMI_TPC_PREAM_2GHZ_HT40,
-+ WMI_TPC_PREAM_2GHZ_VHT20,
-+ WMI_TPC_PREAM_2GHZ_VHT40,
-+ WMI_TPC_PREAM_2GHZ_VHT80,
-+};
-+
-+enum wmi_tpc_pream_5ghz {
-+ WMI_TPC_PREAM_5GHZ_OFDM = 1,
-+ WMI_TPC_PREAM_5GHZ_HT20,
-+ WMI_TPC_PREAM_5GHZ_HT40,
-+ WMI_TPC_PREAM_5GHZ_VHT20,
-+ WMI_TPC_PREAM_5GHZ_VHT40,
-+ WMI_TPC_PREAM_5GHZ_VHT80,
-+ WMI_TPC_PREAM_5GHZ_HTCUP,
-+};
-+
- struct wmi_pdev_chanlist_update_event {
- /* number of channels */
- __le32 num_chan;
-@@ -6977,5 +7040,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(st
- int ath10k_wmi_op_get_vdev_subtype(struct ath10k *ar,
- enum wmi_vdev_subtype subtype);
- int ath10k_wmi_barrier(struct ath10k *ar);
-+void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table,
-+ u32 num_tx_chain);
-+void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb);
-
- #endif /* _WMI_H_ */
+++ /dev/null
-From 8b2d93dd22615cb7f3046a5a2083a6f8bb8052ed Mon Sep 17 00:00:00 2001
-From: Karthikeyan Periyasamy <periyasa@codeaurora.org>
-Date: Mon, 12 Mar 2018 17:09:40 +0530
-Subject: [PATCH] ath10k: Fix kernel panic while using worker
- (ath10k_sta_rc_update_wk)
-
-When attempt to run worker (ath10k_sta_rc_update_wk) after the station object
-(ieee80211_sta) delete will trigger the kernel panic.
-
-This problem arise in AP + Mesh configuration, Where the current node AP VAP
-and neighbor node mesh VAP MAC address are same. When the current mesh node
-try to establish the mesh link with neighbor node, driver peer creation for
-the neighbor mesh node fails due to duplication MAC address. Already the AP
-VAP created with same MAC address.
-
-It is caused by the following scenario steps.
-
-Steps:
-1. In above condition, ath10k driver sta_state callback (ath10k_sta_state)
- fails to do the state change for a station from IEEE80211_STA_NOTEXIST
- to IEEE80211_STA_NONE due to peer creation fails. Sta_state callback is
- called from ieee80211_add_station() to handle the new station
- (neighbor mesh node) request from the wpa_supplicant.
-2. Concurrently ath10k receive the sta_rc_update callback notification from
- the mesh_neighbour_update() to handle the beacon frames of the above
- neighbor mesh node. since its atomic callback, ath10k driver queue the
- work (ath10k_sta_rc_update_wk) to handle rc update.
-3. Due to driver sta_state callback fails (step 1), mac80211 free the station
- object.
-4. When the worker (ath10k_sta_rc_update_wk) scheduled to run, it will access
- the station object which is already deleted. so it will trigger kernel
- panic.
-
-Added the peer exist check in sta_rc_update callback before queue the work.
-
-Kernel Panic log:
-
-Unable to handle kernel NULL pointer dereference at virtual address 00000000
-pgd = c0204000
-[00000000] *pgd=00000000
-Internal error: Oops: 17 [#1] PREEMPT SMP ARM
-CPU: 1 PID: 1833 Comm: kworker/u4:2 Not tainted 3.14.77 #1
-task: dcef0000 ti: d72b6000 task.ti: d72b6000
-PC is at pwq_activate_delayed_work+0x10/0x40
-LR is at pwq_activate_delayed_work+0xc/0x40
-pc : [<c023f988>] lr : [<c023f984>] psr: 40000193
-sp : d72b7f18 ip : 0000007a fp : d72b6000
-r10: 00000000 r9 : dd404414 r8 : d8c31998
-r7 : d72b6038 r6 : 00000004 r5 : d4907ec8 r4 : dcee1300
-r3 : ffffffe0 r2 : 00000000 r1 : 00000001 r0 : 00000000
-Flags: nZcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment kernel
-Control: 10c5787d Table: 595bc06a DAC: 00000015
-...
-Process kworker/u4:2 (pid: 1833, stack limit = 0xd72b6238)
-Stack: (0xd72b7f18 to 0xd72b8000)
-7f00: 00000001 dcee1300
-7f20: 00000001 c02410dc d8c31980 dd404400 dd404400 c0242790 d8c31980 00000089
-7f40: 00000000 d93e1340 00000000 d8c31980 c0242568 00000000 00000000 00000000
-7f60: 00000000 c02474dc 00000000 00000000 000000f8 d8c31980 00000000 00000000
-7f80: d72b7f80 d72b7f80 00000000 00000000 d72b7f90 d72b7f90 d72b7fac d93e1340
-7fa0: c0247404 00000000 00000000 c0208d20 00000000 00000000 00000000 00000000
-7fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
-7fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
-[<c023f988>] (pwq_activate_delayed_work) from [<c02410dc>] (pwq_dec_nr_in_flight+0x58/0xc4)
-[<c02410dc>] (pwq_dec_nr_in_flight) from [<c0242790>] (worker_thread+0x228/0x360)
-[<c0242790>] (worker_thread) from [<c02474dc>] (kthread+0xd8/0xec)
-[<c02474dc>] (kthread) from [<c0208d20>] (ret_from_fork+0x14/0x34)
-Code: e92d4038 e1a05000 ebffffbc[69210.619376] SMP: failed to stop secondary CPUs
-Rebooting in 3 seconds..
-
-Signed-off-by: Karthikeyan Periyasamy <periyasa@codeaurora.org>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/mac.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -7065,10 +7065,20 @@ static void ath10k_sta_rc_update(struct
- {
- struct ath10k *ar = hw->priv;
- struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
-+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
-+ struct ath10k_peer *peer;
- u32 bw, smps;
-
- spin_lock_bh(&ar->data_lock);
-
-+ peer = ath10k_peer_find(ar, arvif->vdev_id, sta->addr);
-+ if (!peer) {
-+ spin_unlock_bh(&ar->data_lock);
-+ ath10k_warn(ar, "mac sta rc update failed to find peer %pM on vdev %i\n",
-+ sta->addr, arvif->vdev_id);
-+ return;
-+ }
-+
- ath10k_dbg(ar, ATH10K_DBG_MAC,
- "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
- sta->addr, changed, sta->bandwidth, sta->rx_nss,
+++ /dev/null
-From 4b190675ad06f5a6ecbeef0b01890c5fb372e3eb Mon Sep 17 00:00:00 2001
-From: Tamizh Chelvam <tamizhr@codeaurora.org>
-Date: Wed, 25 Apr 2018 11:36:44 +0300
-Subject: [PATCH] ath10k: fix kernel panic while reading tpc_stats
-
-When attempt to read tpc_stats for the chipsets which support
-more than 3 tx chain will trigger kernel panic(kernel stack is corrupted)
-due to writing values on rate_code array out of range.
-This patch changes the array size depends on the WMI_TPC_TX_N_CHAIN and
-added check to avoid write values on the array if the num tx chain
-get in tpc config event is greater than WMI_TPC_TX_N_CHAIN.
-
-Tested on QCA9984 with firmware-5.bin_10.4-3.5.3-00057
-
-Kernel panic log :
-
-[ 323.510944] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: bf90c654
-[ 323.510944]
-[ 323.524390] CPU: 0 PID: 1908 Comm: cat Not tainted 3.14.77 #31
-[ 323.530224] [<c021db48>] (unwind_backtrace) from [<c021ac08>] (show_stack+0x10/0x14)
-[ 323.537941] [<c021ac08>] (show_stack) from [<c03c53c0>] (dump_stack+0x80/0xa0)
-[ 323.545146] [<c03c53c0>] (dump_stack) from [<c022e4ac>] (panic+0x84/0x1e4)
-[ 323.552000] [<c022e4ac>] (panic) from [<c022e61c>] (__stack_chk_fail+0x10/0x14)
-[ 323.559350] [<c022e61c>] (__stack_chk_fail) from [<bf90c654>] (ath10k_wmi_event_pdev_tpc_config+0x424/0x438 [ath10k_core])
-[ 323.570471] [<bf90c654>] (ath10k_wmi_event_pdev_tpc_config [ath10k_core]) from [<bf90d800>] (ath10k_wmi_10_4_op_rx+0x2f0/0x39c [ath10k_core])
-[ 323.583047] [<bf90d800>] (ath10k_wmi_10_4_op_rx [ath10k_core]) from [<bf8fcc18>] (ath10k_htc_rx_completion_handler+0x170/0x1a0 [ath10k_core])
-[ 323.595702] [<bf8fcc18>] (ath10k_htc_rx_completion_handler [ath10k_core]) from [<bf961f44>] (ath10k_pci_hif_send_complete_check+0x1f0/0x220 [ath10k_pci])
-[ 323.609421] [<bf961f44>] (ath10k_pci_hif_send_complete_check [ath10k_pci]) from [<bf96562c>] (ath10k_ce_per_engine_service+0x74/0xc4 [ath10k_pci])
-[ 323.622490] [<bf96562c>] (ath10k_ce_per_engine_service [ath10k_pci]) from [<bf9656f0>] (ath10k_ce_per_engine_service_any+0x74/0x80 [ath10k_pci])
-[ 323.635423] [<bf9656f0>] (ath10k_ce_per_engine_service_any [ath10k_pci]) from [<bf96365c>] (ath10k_pci_napi_poll+0x44/0xe8 [ath10k_pci])
-[ 323.647665] [<bf96365c>] (ath10k_pci_napi_poll [ath10k_pci]) from [<c0599994>] (net_rx_action+0xac/0x160)
-[ 323.657208] [<c0599994>] (net_rx_action) from [<c02324a4>] (__do_softirq+0x104/0x294)
-[ 323.665017] [<c02324a4>] (__do_softirq) from [<c0232920>] (irq_exit+0x9c/0x11c)
-[ 323.672314] [<c0232920>] (irq_exit) from [<c0217fc0>] (handle_IRQ+0x6c/0x90)
-[ 323.679341] [<c0217fc0>] (handle_IRQ) from [<c02084e0>] (gic_handle_irq+0x3c/0x60)
-[ 323.686893] [<c02084e0>] (gic_handle_irq) from [<c02095c0>] (__irq_svc+0x40/0x70)
-[ 323.694349] Exception stack(0xdd489c58 to 0xdd489ca0)
-[ 323.699384] 9c40: 00000000 a0000013
-[ 323.707547] 9c60: 00000000 dc4bce40 60000013 ddc1d800 dd488000 00000990 00000000 c085c800
-[ 323.715707] 9c80: 00000000 dd489d44 0000092d dd489ca0 c026e664 c026e668 60000013 ffffffff
-[ 323.723877] [<c02095c0>] (__irq_svc) from [<c026e668>] (rcu_note_context_switch+0x170/0x184)
-[ 323.732298] [<c026e668>] (rcu_note_context_switch) from [<c020e928>] (__schedule+0x50/0x4d4)
-[ 323.740716] [<c020e928>] (__schedule) from [<c020e490>] (schedule_timeout+0x148/0x178)
-[ 323.748611] [<c020e490>] (schedule_timeout) from [<c020f804>] (wait_for_common+0x114/0x154)
-[ 323.756972] [<c020f804>] (wait_for_common) from [<bf8f6ef0>] (ath10k_tpc_stats_open+0xc8/0x340 [ath10k_core])
-[ 323.766873] [<bf8f6ef0>] (ath10k_tpc_stats_open [ath10k_core]) from [<c02bb598>] (do_dentry_open+0x1ac/0x274)
-[ 323.776741] [<c02bb598>] (do_dentry_open) from [<c02c838c>] (do_last+0x8c0/0xb08)
-[ 323.784201] [<c02c838c>] (do_last) from [<c02c87e4>] (path_openat+0x210/0x598)
-[ 323.791408] [<c02c87e4>] (path_openat) from [<c02c9d1c>] (do_filp_open+0x2c/0x78)
-[ 323.798873] [<c02c9d1c>] (do_filp_open) from [<c02bc85c>] (do_sys_open+0x114/0x1b4)
-[ 323.806509] [<c02bc85c>] (do_sys_open) from [<c0208c80>] (ret_fast_syscall+0x0/0x44)
-[ 323.814241] CPU1: stopping
-[ 323.816927] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.14.77 #31
-[ 323.823008] [<c021db48>] (unwind_backtrace) from [<c021ac08>] (show_stack+0x10/0x14)
-[ 323.830731] [<c021ac08>] (show_stack) from [<c03c53c0>] (dump_stack+0x80/0xa0)
-[ 323.837934] [<c03c53c0>] (dump_stack) from [<c021cfac>] (handle_IPI+0xb8/0x140)
-[ 323.845224] [<c021cfac>] (handle_IPI) from [<c02084fc>] (gic_handle_irq+0x58/0x60)
-[ 323.852774] [<c02084fc>] (gic_handle_irq) from [<c02095c0>] (__irq_svc+0x40/0x70)
-[ 323.860233] Exception stack(0xdd499fa0 to 0xdd499fe8)
-[ 323.865273] 9fa0: ffffffed 00000000 1d3c9000 00000000 dd498000 dd498030 10c0387d c08b62c8
-[ 323.873432] 9fc0: 4220406a 512f04d0 00000000 00000000 00000001 dd499fe8 c021838c c0218390
-[ 323.881588] 9fe0: 60000013 ffffffff
-[ 323.885070] [<c02095c0>] (__irq_svc) from [<c0218390>] (arch_cpu_idle+0x30/0x50)
-[ 323.892454] [<c0218390>] (arch_cpu_idle) from [<c026500c>] (cpu_startup_entry+0xa4/0x108)
-[ 323.900690] [<c026500c>] (cpu_startup_entry) from [<422085a4>] (0x422085a4)
-
-Signed-off-by: Tamizh chelvam <tamizhr@codeaurora.org>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/debug.c | 8 +++++++-
- drivers/net/wireless/ath/ath10k/wmi.c | 6 ++++++
- drivers/net/wireless/ath/ath10k/wmi.h | 2 +-
- 3 files changed, 14 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/debug.c
-+++ b/drivers/net/wireless/ath/ath10k/debug.c
-@@ -1776,7 +1776,13 @@ static void ath10k_tpc_stats_print(struc
- *len += scnprintf(buf + *len, buf_len - *len,
- "********************************\n");
- *len += scnprintf(buf + *len, buf_len - *len,
-- "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n");
-+ "No. Preamble Rate_code ");
-+
-+ for (i = 0; i < WMI_TPC_TX_N_CHAIN; i++)
-+ *len += scnprintf(buf + *len, buf_len - *len,
-+ "tpc_value%d ", i);
-+
-+ *len += scnprintf(buf + *len, buf_len - *len, "\n");
-
- for (i = 0; i < tpc_stats->rate_max; i++) {
- *len += scnprintf(buf + *len, buf_len - *len,
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -4431,6 +4431,12 @@ void ath10k_wmi_event_pdev_tpc_config(st
-
- num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
-
-+ if (num_tx_chain > WMI_TPC_TX_N_CHAIN) {
-+ ath10k_warn(ar, "number of tx chain is %d greater than TPC configured tx chain %d\n",
-+ num_tx_chain, WMI_TPC_TX_N_CHAIN);
-+ return;
-+ }
-+
- ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table,
- num_tx_chain);
-
---- a/drivers/net/wireless/ath/ath10k/wmi.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -4007,9 +4007,9 @@ struct wmi_pdev_get_tpc_config_cmd {
- } __packed;
-
- #define WMI_TPC_CONFIG_PARAM 1
--#define WMI_TPC_RATE_MAX 160
- #define WMI_TPC_FINAL_RATE_MAX 240
- #define WMI_TPC_TX_N_CHAIN 4
-+#define WMI_TPC_RATE_MAX (WMI_TPC_TX_N_CHAIN * 65)
- #define WMI_TPC_PREAM_TABLE_MAX 10
- #define WMI_TPC_FLAG 3
- #define WMI_TPC_BUF_SIZE 10
+++ /dev/null
-From be8cce96f14dc925ecfb702be0392a52cf78adb5 Mon Sep 17 00:00:00 2001
-From: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
-Date: Wed, 23 May 2018 11:09:09 +0300
-Subject: [PATCH] ath10k: add support to configure channel dwell time
-
-Configure channel dwell time from duration of the scan request
-received from mac80211 when the duration is non-zero. When the
-scan request does not have duration value, use the default ones,
-the current implementation.
-
-Corresponding flag NL80211_EXT_FEATURE_SET_SCAN_DWELL is
-advertized.
-
-Supported Chipsets:
- -QCA988X/QCA9887 PCI
- -QCA99X0/QCA9984/QCA9888/QCA4019 PCI
- -QCA6174/QCA9377 PCI/USB/SDIO
- -WCN3990 SNOC
-
-Tested on QCA9984 with firmware ver 10.4-3.6-0010
-
-Signed-off-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/core.h | 1 +
- drivers/net/wireless/ath/ath10k/mac.c | 23 ++++++++++++++++++++---
- 2 files changed, 21 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/core.h
-+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -43,6 +43,7 @@
- #define WO(_f) ((_f##_OFFSET) >> 2)
-
- #define ATH10K_SCAN_ID 0
-+#define ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD 10 /* msec */
- #define WMI_READY_TIMEOUT (5 * HZ)
- #define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ)
- #define ATH10K_CONNECTION_LOSS_HZ (3 * HZ)
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -5597,6 +5597,7 @@ static int ath10k_hw_scan(struct ieee802
- struct wmi_start_scan_arg arg;
- int ret = 0;
- int i;
-+ u32 scan_timeout;
-
- mutex_lock(&ar->conf_mutex);
-
-@@ -5647,6 +5648,22 @@ static int ath10k_hw_scan(struct ieee802
- arg.channels[i] = req->channels[i]->center_freq;
- }
-
-+ /* if duration is set, default dwell times will be overwritten */
-+ if (req->duration) {
-+ arg.dwell_time_active = req->duration;
-+ arg.dwell_time_passive = req->duration;
-+ arg.burst_duration_ms = req->duration;
-+
-+ scan_timeout = min_t(u32, arg.max_rest_time *
-+ (arg.n_channels - 1) + (req->duration +
-+ ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) *
-+ arg.n_channels, arg.max_scan_time + 200);
-+
-+ } else {
-+ /* Add a 200ms margin to account for event/command processing */
-+ scan_timeout = arg.max_scan_time + 200;
-+ }
-+
- ret = ath10k_start_scan(ar, &arg);
- if (ret) {
- ath10k_warn(ar, "failed to start hw scan: %d\n", ret);
-@@ -5655,10 +5672,8 @@ static int ath10k_hw_scan(struct ieee802
- spin_unlock_bh(&ar->data_lock);
- }
-
-- /* Add a 200ms margin to account for event/command processing */
- ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout,
-- msecs_to_jiffies(arg.max_scan_time +
-- 200));
-+ msecs_to_jiffies(scan_timeout));
-
- exit:
- mutex_unlock(&ar->conf_mutex);
-@@ -8267,6 +8282,8 @@ int ath10k_mac_register(struct ath10k *a
- }
-
- wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
-+ wiphy_ext_feature_set(ar->hw->wiphy,
-+ NL80211_EXT_FEATURE_SET_SCAN_DWELL);
-
- /*
- * on LL hardware queues are managed entirely by the FW
+++ /dev/null
-From f40105e6747892e8edab94020567c158c9bec0df Mon Sep 17 00:00:00 2001
-From: Sriram R <srirrama@codeaurora.org>
-Date: Tue, 15 May 2018 14:39:48 +0530
-Subject: [PATCH] ath: add support to get the detected radar specifications
-
-This enables ath10k/ath9k drivers to collect the specifications of the
-radar type once it is detected by the dfs pattern detector unit.
-Usage of the collected info is specific to driver implementation.
-For example, collected radar info could be used by the host driver
-to send to co-processors for additional processing/validation.
-
-Note: 'radar_detector_specs' data containing the specifications of
-different radar types which was private within dfs_pattern_detector/
-dfs_pri_detector is now shared with drivers as well for making use
-of this information.
-
-Signed-off-by: Sriram R <srirrama@codeaurora.org>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/wmi.c | 2 +-
- drivers/net/wireless/ath/ath9k/dfs.c | 2 +-
- drivers/net/wireless/ath/dfs_pattern_detector.c | 5 ++++-
- drivers/net/wireless/ath/dfs_pattern_detector.h | 3 ++-
- drivers/net/wireless/ath/dfs_pri_detector.h | 3 ++-
- 5 files changed, 10 insertions(+), 5 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -3712,7 +3712,7 @@ static void ath10k_dfs_radar_report(stru
-
- ATH10K_DFS_STAT_INC(ar, pulses_detected);
-
-- if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe)) {
-+ if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe, NULL)) {
- ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
- "dfs no pulse pattern detected, yet\n");
- return;
---- a/drivers/net/wireless/ath/ath9k/dfs.c
-+++ b/drivers/net/wireless/ath/ath9k/dfs.c
-@@ -279,7 +279,7 @@ ath9k_dfs_process_radar_pulse(struct ath
- DFS_STAT_INC(sc, pulses_processed);
- if (pd == NULL)
- return;
-- if (!pd->add_pulse(pd, pe))
-+ if (!pd->add_pulse(pd, pe, NULL))
- return;
- DFS_STAT_INC(sc, radar_detected);
- ieee80211_radar_detected(sc->hw);
---- a/drivers/net/wireless/ath/dfs_pattern_detector.c
-+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
-@@ -268,7 +268,8 @@ static void dpd_exit(struct dfs_pattern_
- }
-
- static bool
--dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event)
-+dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event,
-+ struct radar_detector_specs *rs)
- {
- u32 i;
- struct channel_detector *cd;
-@@ -294,6 +295,8 @@ dpd_add_pulse(struct dfs_pattern_detecto
- struct pri_detector *pd = cd->detectors[i];
- struct pri_sequence *ps = pd->add_pulse(pd, event);
- if (ps != NULL) {
-+ if (rs != NULL)
-+ memcpy(rs, pd->rs, sizeof(*rs));
- ath_dbg(dpd->common, DFS,
- "DFS: radar found on freq=%d: id=%d, pri=%d, "
- "count=%d, count_false=%d\n",
---- a/drivers/net/wireless/ath/dfs_pattern_detector.h
-+++ b/drivers/net/wireless/ath/dfs_pattern_detector.h
-@@ -97,7 +97,8 @@ struct dfs_pattern_detector {
- bool (*set_dfs_domain)(struct dfs_pattern_detector *dpd,
- enum nl80211_dfs_regions region);
- bool (*add_pulse)(struct dfs_pattern_detector *dpd,
-- struct pulse_event *pe);
-+ struct pulse_event *pe,
-+ struct radar_detector_specs *rs);
-
- struct ath_dfs_pool_stats (*get_stats)(struct dfs_pattern_detector *dpd);
- enum nl80211_dfs_regions region;
---- a/drivers/net/wireless/ath/dfs_pri_detector.h
-+++ b/drivers/net/wireless/ath/dfs_pri_detector.h
-@@ -62,8 +62,9 @@ struct pri_detector {
- (*add_pulse)(struct pri_detector *de, struct pulse_event *e);
- void (*reset) (struct pri_detector *de, u64 ts);
-
--/* private: internal use only */
- const struct radar_detector_specs *rs;
-+
-+/* private: internal use only */
- u64 last_ts;
- struct list_head sequences;
- struct list_head pulses;
+++ /dev/null
-From 6f6eb1bcbeff48c875617b800f00f1c5d1b12290 Mon Sep 17 00:00:00 2001
-From: Sriram R <srirrama@codeaurora.org>
-Date: Tue, 15 May 2018 14:39:49 +0530
-Subject: [PATCH] ath10k: DFS Host Confirmation
-
-In the 10.4-3.6 firmware branch there's a new DFS Host confirmation
-feature which is advertised using WMI_SERVICE_HOST_DFS_CHECK_SUPPORT flag.
-
-This new features enables the ath10k host to send information to the
-firmware on the specifications of detected radar type. This allows the
-firmware to validate if the host's radar pattern detector unit is
-operational and check if the radar information shared by host matches
-the radar pulses sent as phy error events from firmware. If the check
-fails the firmware won't allow use of DFS channels on AP mode when using
-FCC regulatory region.
-
-Hence this patch is mandatory when using a firmware from 10.4-3.6 branch.
-Else, DFS channels on FCC regions cannot be used.
-
-Supported Chipsets : QCA9984/QCA9888/QCA4019
-Firmware Version : 10.4-3.6-00104
-
-Signed-off-by: Sriram R <srirrama@codeaurora.org>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/core.h | 21 ++++
- drivers/net/wireless/ath/ath10k/mac.c | 12 ++
- drivers/net/wireless/ath/ath10k/wmi-ops.h | 32 +++++
- drivers/net/wireless/ath/ath10k/wmi.c | 186 ++++++++++++++++++++++++++++--
- drivers/net/wireless/ath/ath10k/wmi.h | 32 +++++
- 5 files changed, 273 insertions(+), 10 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/core.h
-+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -171,6 +171,7 @@ struct ath10k_wmi {
- struct completion service_ready;
- struct completion unified_ready;
- struct completion barrier;
-+ struct completion radar_confirm;
- wait_queue_head_t tx_credits_wq;
- DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX);
- struct wmi_cmd_map *cmd;
-@@ -352,6 +353,21 @@ struct ath10k_dfs_stats {
- u32 radar_detected;
- };
-
-+enum ath10k_radar_confirmation_state {
-+ ATH10K_RADAR_CONFIRMATION_IDLE = 0,
-+ ATH10K_RADAR_CONFIRMATION_INPROGRESS,
-+ ATH10K_RADAR_CONFIRMATION_STOPPED,
-+};
-+
-+struct ath10k_radar_found_info {
-+ u32 pri_min;
-+ u32 pri_max;
-+ u32 width_min;
-+ u32 width_max;
-+ u32 sidx_min;
-+ u32 sidx_max;
-+};
-+
- #define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */
-
- struct ath10k_peer {
-@@ -1026,6 +1042,11 @@ struct ath10k {
-
- void *ce_priv;
-
-+ /* protected by data_lock */
-+ enum ath10k_radar_confirmation_state radar_conf_state;
-+ struct ath10k_radar_found_info last_radar_info;
-+ struct work_struct radar_confirmation_work;
-+
- /* must be last */
- u8 drv_priv[0] __aligned(sizeof(void *));
- };
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -3216,6 +3216,15 @@ static void ath10k_reg_notifier(struct w
- ar->hw->wiphy->bands[NL80211_BAND_5GHZ]);
- }
-
-+static void ath10k_stop_radar_confirmation(struct ath10k *ar)
-+{
-+ spin_lock_bh(&ar->data_lock);
-+ ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_STOPPED;
-+ spin_unlock_bh(&ar->data_lock);
-+
-+ cancel_work_sync(&ar->radar_confirmation_work);
-+}
-+
- /***************/
- /* TX handlers */
- /***************/
-@@ -4315,6 +4324,7 @@ void ath10k_halt(struct ath10k *ar)
-
- ath10k_scan_finish(ar);
- ath10k_peer_cleanup_all(ar);
-+ ath10k_stop_radar_confirmation(ar);
- ath10k_core_stop(ar);
- ath10k_hif_power_down(ar);
-
-@@ -4733,6 +4743,8 @@ static int ath10k_start(struct ieee80211
- ath10k_spectral_start(ar);
- ath10k_thermal_set_throttling(ar);
-
-+ ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_IDLE;
-+
- mutex_unlock(&ar->conf_mutex);
- return 0;
-
---- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
-@@ -53,6 +53,8 @@ struct wmi_ops {
- struct wmi_wow_ev_arg *arg);
- int (*pull_echo_ev)(struct ath10k *ar, struct sk_buff *skb,
- struct wmi_echo_ev_arg *arg);
-+ int (*pull_dfs_status_ev)(struct ath10k *ar, struct sk_buff *skb,
-+ struct wmi_dfs_status_ev_arg *arg);
- enum wmi_txbf_conf (*get_txbf_conf_scheme)(struct ath10k *ar);
-
- struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
-@@ -178,6 +180,9 @@ struct wmi_ops {
- const struct wmi_tdls_peer_update_cmd_arg *arg,
- const struct wmi_tdls_peer_capab_arg *cap,
- const struct wmi_channel_arg *chan);
-+ struct sk_buff *(*gen_radar_found)
-+ (struct ath10k *ar,
-+ const struct ath10k_radar_found_info *arg);
- struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable);
- struct sk_buff *(*gen_pdev_get_tpc_config)(struct ath10k *ar,
- u32 param);
-@@ -365,6 +370,16 @@ ath10k_wmi_pull_echo_ev(struct ath10k *a
- return ar->wmi.ops->pull_echo_ev(ar, skb, arg);
- }
-
-+static inline int
-+ath10k_wmi_pull_dfs_status(struct ath10k *ar, struct sk_buff *skb,
-+ struct wmi_dfs_status_ev_arg *arg)
-+{
-+ if (!ar->wmi.ops->pull_dfs_status_ev)
-+ return -EOPNOTSUPP;
-+
-+ return ar->wmi.ops->pull_dfs_status_ev(ar, skb, arg);
-+}
-+
- static inline enum wmi_txbf_conf
- ath10k_wmi_get_txbf_conf_scheme(struct ath10k *ar)
- {
-@@ -1438,4 +1453,21 @@ ath10k_wmi_pdev_get_tpc_table_cmdid(stru
- ar->wmi.cmd->pdev_get_tpc_table_cmdid);
- }
-
-+static inline int
-+ath10k_wmi_report_radar_found(struct ath10k *ar,
-+ const struct ath10k_radar_found_info *arg)
-+{
-+ struct sk_buff *skb;
-+
-+ if (!ar->wmi.ops->gen_radar_found)
-+ return -EOPNOTSUPP;
-+
-+ skb = ar->wmi.ops->gen_radar_found(ar, arg);
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ return ath10k_wmi_cmd_send(ar, skb,
-+ ar->wmi.cmd->radar_found_cmdid);
-+}
-+
- #endif
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -34,6 +34,7 @@
-
- #define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9
- #define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ)
-+#define ATH10K_WMI_DFS_CONF_TIMEOUT_HZ (HZ / 6)
-
- /* MAIN WMI cmd track */
- static struct wmi_cmd_map wmi_cmd_map = {
-@@ -198,6 +199,7 @@ static struct wmi_cmd_map wmi_cmd_map =
- .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
-+ .radar_found_cmdid = WMI_CMD_UNSUPPORTED,
- };
-
- /* 10.X WMI cmd track */
-@@ -365,6 +367,7 @@ static struct wmi_cmd_map wmi_10x_cmd_ma
- .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
-+ .radar_found_cmdid = WMI_CMD_UNSUPPORTED,
- };
-
- /* 10.2.4 WMI cmd track */
-@@ -532,6 +535,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd
- .pdev_bss_chan_info_request_cmdid =
- WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
- .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
-+ .radar_found_cmdid = WMI_CMD_UNSUPPORTED,
- };
-
- /* 10.4 WMI cmd track */
-@@ -741,6 +745,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_m
- .tdls_set_state_cmdid = WMI_10_4_TDLS_SET_STATE_CMDID,
- .tdls_peer_update_cmdid = WMI_10_4_TDLS_PEER_UPDATE_CMDID,
- .tdls_set_offchan_mode_cmdid = WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID,
-+ .radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID,
- };
-
- /* MAIN WMI VDEV param map */
-@@ -1485,6 +1490,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_m
- .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
- .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED,
-+ .radar_found_cmdid = WMI_CMD_UNSUPPORTED,
- };
-
- static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
-@@ -3638,6 +3644,68 @@ void ath10k_wmi_event_tbttoffset_update(
- ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n");
- }
-
-+static void ath10k_radar_detected(struct ath10k *ar)
-+{
-+ ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n");
-+ ATH10K_DFS_STAT_INC(ar, radar_detected);
-+
-+ /* Control radar events reporting in debugfs file
-+ * dfs_block_radar_events
-+ */
-+ if (ar->dfs_block_radar_events)
-+ ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
-+ else
-+ ieee80211_radar_detected(ar->hw);
-+}
-+
-+static void ath10k_radar_confirmation_work(struct work_struct *work)
-+{
-+ struct ath10k *ar = container_of(work, struct ath10k,
-+ radar_confirmation_work);
-+ struct ath10k_radar_found_info radar_info;
-+ int ret, time_left;
-+
-+ reinit_completion(&ar->wmi.radar_confirm);
-+
-+ spin_lock_bh(&ar->data_lock);
-+ memcpy(&radar_info, &ar->last_radar_info, sizeof(radar_info));
-+ spin_unlock_bh(&ar->data_lock);
-+
-+ ret = ath10k_wmi_report_radar_found(ar, &radar_info);
-+ if (ret) {
-+ ath10k_warn(ar, "failed to send radar found %d\n", ret);
-+ goto wait_complete;
-+ }
-+
-+ time_left = wait_for_completion_timeout(&ar->wmi.radar_confirm,
-+ ATH10K_WMI_DFS_CONF_TIMEOUT_HZ);
-+ if (time_left) {
-+ /* DFS Confirmation status event received and
-+ * necessary action completed.
-+ */
-+ goto wait_complete;
-+ } else {
-+ /* DFS Confirmation event not received from FW.Considering this
-+ * as real radar.
-+ */
-+ ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ "dfs confirmation not received from fw, considering as radar\n");
-+ goto radar_detected;
-+ }
-+
-+radar_detected:
-+ ath10k_radar_detected(ar);
-+
-+ /* Reset state to allow sending confirmation on consecutive radar
-+ * detections, unless radar confirmation is disabled/stopped.
-+ */
-+wait_complete:
-+ spin_lock_bh(&ar->data_lock);
-+ if (ar->radar_conf_state != ATH10K_RADAR_CONFIRMATION_STOPPED)
-+ ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_IDLE;
-+ spin_unlock_bh(&ar->data_lock);
-+}
-+
- static void ath10k_dfs_radar_report(struct ath10k *ar,
- struct wmi_phyerr_ev_arg *phyerr,
- const struct phyerr_radar_report *rr,
-@@ -3646,8 +3714,10 @@ static void ath10k_dfs_radar_report(stru
- u32 reg0, reg1, tsf32l;
- struct ieee80211_channel *ch;
- struct pulse_event pe;
-+ struct radar_detector_specs rs;
- u64 tsf64;
- u8 rssi, width;
-+ struct ath10k_radar_found_info *radar_info;
-
- reg0 = __le32_to_cpu(rr->reg0);
- reg1 = __le32_to_cpu(rr->reg1);
-@@ -3712,25 +3782,46 @@ static void ath10k_dfs_radar_report(stru
-
- ATH10K_DFS_STAT_INC(ar, pulses_detected);
-
-- if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe, NULL)) {
-+ if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe, &rs)) {
- ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
- "dfs no pulse pattern detected, yet\n");
- return;
- }
-
--radar_detected:
-- ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n");
-- ATH10K_DFS_STAT_INC(ar, radar_detected);
-+ if ((test_bit(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, ar->wmi.svc_map)) &&
-+ ar->dfs_detector->region == NL80211_DFS_FCC) {
-+ /* Consecutive radar indications need not be
-+ * sent to the firmware until we get confirmation
-+ * for the previous detected radar.
-+ */
-+ spin_lock_bh(&ar->data_lock);
-+ if (ar->radar_conf_state != ATH10K_RADAR_CONFIRMATION_IDLE) {
-+ spin_unlock_bh(&ar->data_lock);
-+ return;
-+ }
-+ ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_INPROGRESS;
-+ radar_info = &ar->last_radar_info;
-
-- /* Control radar events reporting in debugfs file
-- * dfs_block_radar_events
-- */
-- if (ar->dfs_block_radar_events) {
-- ath10k_info(ar, "DFS Radar detected, but ignored as requested\n");
-+ radar_info->pri_min = rs.pri_min;
-+ radar_info->pri_max = rs.pri_max;
-+ radar_info->width_min = rs.width_min;
-+ radar_info->width_max = rs.width_max;
-+ /*TODO Find sidx_min and sidx_max */
-+ radar_info->sidx_min = MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX);
-+ radar_info->sidx_max = MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX);
-+
-+ ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ "sending wmi radar found cmd pri_min %d pri_max %d width_min %d width_max %d sidx_min %d sidx_max %d\n",
-+ radar_info->pri_min, radar_info->pri_max,
-+ radar_info->width_min, radar_info->width_max,
-+ radar_info->sidx_min, radar_info->sidx_max);
-+ ieee80211_queue_work(ar->hw, &ar->radar_confirmation_work);
-+ spin_unlock_bh(&ar->data_lock);
- return;
- }
-
-- ieee80211_radar_detected(ar->hw);
-+radar_detected:
-+ ath10k_radar_detected(ar);
- }
-
- static int ath10k_dfs_fft_report(struct ath10k *ar,
-@@ -4080,6 +4171,47 @@ void ath10k_wmi_event_phyerr(struct ath1
- }
- }
-
-+static int
-+ath10k_wmi_10_4_op_pull_dfs_status_ev(struct ath10k *ar, struct sk_buff *skb,
-+ struct wmi_dfs_status_ev_arg *arg)
-+{
-+ struct wmi_dfs_status_ev_arg *ev = (void *)skb->data;
-+
-+ if (skb->len < sizeof(*ev))
-+ return -EPROTO;
-+
-+ arg->status = ev->status;
-+
-+ return 0;
-+}
-+
-+static void
-+ath10k_wmi_event_dfs_status_check(struct ath10k *ar, struct sk_buff *skb)
-+{
-+ struct wmi_dfs_status_ev_arg status_arg = {};
-+ int ret;
-+
-+ ret = ath10k_wmi_pull_dfs_status(ar, skb, &status_arg);
-+
-+ if (ret) {
-+ ath10k_warn(ar, "failed to parse dfs status event: %d\n", ret);
-+ return;
-+ }
-+
-+ ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
-+ "dfs status event received from fw: %d\n",
-+ status_arg.status);
-+
-+ /* Even in case of radar detection failure we follow the same
-+ * behaviour as if radar is detected i.e to switch to a different
-+ * channel.
-+ */
-+ if (status_arg.status == WMI_HW_RADAR_DETECTED ||
-+ status_arg.status == WMI_RADAR_DETECTION_FAIL)
-+ ath10k_radar_detected(ar);
-+ complete(&ar->wmi.radar_confirm);
-+}
-+
- void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
- {
- struct wmi_roam_ev_arg arg = {};
-@@ -5814,6 +5946,9 @@ static void ath10k_wmi_10_4_op_rx(struct
- case WMI_10_4_PDEV_TPC_TABLE_EVENTID:
- ath10k_wmi_event_tpc_final_table(ar, skb);
- break;
-+ case WMI_10_4_DFS_STATUS_CHECK_EVENTID:
-+ ath10k_wmi_event_dfs_status_check(ar, skb);
-+ break;
- default:
- ath10k_warn(ar, "Unknown eventid: %d\n", id);
- break;
-@@ -8332,6 +8467,32 @@ ath10k_wmi_10_4_gen_tdls_peer_update(str
- }
-
- static struct sk_buff *
-+ath10k_wmi_10_4_gen_radar_found(struct ath10k *ar,
-+ const struct ath10k_radar_found_info *arg)
-+{
-+ struct wmi_radar_found_info *cmd;
-+ struct sk_buff *skb;
-+
-+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ if (!skb)
-+ return ERR_PTR(-ENOMEM);
-+
-+ cmd = (struct wmi_radar_found_info *)skb->data;
-+ cmd->pri_min = __cpu_to_le32(arg->pri_min);
-+ cmd->pri_max = __cpu_to_le32(arg->pri_max);
-+ cmd->width_min = __cpu_to_le32(arg->width_min);
-+ cmd->width_max = __cpu_to_le32(arg->width_max);
-+ cmd->sidx_min = __cpu_to_le32(arg->sidx_min);
-+ cmd->sidx_max = __cpu_to_le32(arg->sidx_max);
-+
-+ ath10k_dbg(ar, ATH10K_DBG_WMI,
-+ "wmi radar found pri_min %d pri_max %d width_min %d width_max %d sidx_min %d sidx_max %d\n",
-+ arg->pri_min, arg->pri_max, arg->width_min,
-+ arg->width_max, arg->sidx_min, arg->sidx_max);
-+ return skb;
-+}
-+
-+static struct sk_buff *
- ath10k_wmi_op_gen_echo(struct ath10k *ar, u32 value)
- {
- struct wmi_echo_cmd *cmd;
-@@ -8668,6 +8829,7 @@ static const struct wmi_ops wmi_10_4_ops
- .pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
- .pull_rdy = ath10k_wmi_op_pull_rdy_ev,
- .pull_roam_ev = ath10k_wmi_op_pull_roam_ev,
-+ .pull_dfs_status_ev = ath10k_wmi_10_4_op_pull_dfs_status_ev,
- .get_txbf_conf_scheme = ath10k_wmi_10_4_txbf_conf_scheme,
-
- .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
-@@ -8714,6 +8876,7 @@ static const struct wmi_ops wmi_10_4_ops
- .gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update,
- .gen_pdev_get_tpc_table_cmdid =
- ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid,
-+ .gen_radar_found = ath10k_wmi_10_4_gen_radar_found,
-
- /* shared with 10.2 */
- .pull_echo_ev = ath10k_wmi_op_pull_echo_ev,
-@@ -8776,8 +8939,11 @@ int ath10k_wmi_attach(struct ath10k *ar)
- init_completion(&ar->wmi.service_ready);
- init_completion(&ar->wmi.unified_ready);
- init_completion(&ar->wmi.barrier);
-+ init_completion(&ar->wmi.radar_confirm);
-
- INIT_WORK(&ar->svc_rdy_work, ath10k_wmi_event_service_ready_work);
-+ INIT_WORK(&ar->radar_confirmation_work,
-+ ath10k_radar_confirmation_work);
-
- return 0;
- }
---- a/drivers/net/wireless/ath/ath10k/wmi.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -959,6 +959,7 @@ struct wmi_cmd_map {
- u32 vdev_sifs_trigger_time_cmdid;
- u32 pdev_wds_entry_list_cmdid;
- u32 tdls_set_offchan_mode_cmdid;
-+ u32 radar_found_cmdid;
- };
-
- /*
-@@ -1792,6 +1793,11 @@ enum wmi_10_4_cmd_id {
- WMI_10_4_TDLS_SET_STATE_CMDID,
- WMI_10_4_TDLS_PEER_UPDATE_CMDID,
- WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID,
-+ WMI_10_4_PDEV_SEND_FD_CMDID,
-+ WMI_10_4_ENABLE_FILS_CMDID,
-+ WMI_10_4_PDEV_SET_BRIDGE_MACADDR_CMDID,
-+ WMI_10_4_ATF_GROUP_WMM_AC_CONFIG_REQUEST_CMDID,
-+ WMI_10_4_RADAR_FOUND_CMDID,
- WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
- };
-
-@@ -1867,6 +1873,9 @@ enum wmi_10_4_event_id {
- WMI_10_4_PDEV_TPC_TABLE_EVENTID,
- WMI_10_4_PDEV_WDS_ENTRY_LIST_EVENTID,
- WMI_10_4_TDLS_PEER_EVENTID,
-+ WMI_10_4_HOST_SWFDA_EVENTID,
-+ WMI_10_4_ESP_ESTIMATE_EVENTID,
-+ WMI_10_4_DFS_STATUS_CHECK_EVENTID,
- WMI_10_4_PDEV_UTF_EVENTID = WMI_10_4_END_EVENTID - 1,
- };
-
-@@ -3379,6 +3388,25 @@ struct wmi_10_4_phyerr_event {
- u8 buf[0];
- } __packed;
-
-+struct wmi_radar_found_info {
-+ __le32 pri_min;
-+ __le32 pri_max;
-+ __le32 width_min;
-+ __le32 width_max;
-+ __le32 sidx_min;
-+ __le32 sidx_max;
-+} __packed;
-+
-+enum wmi_radar_confirmation_status {
-+ /* Detected radar was due to SW pulses */
-+ WMI_SW_RADAR_DETECTED = 0,
-+
-+ WMI_RADAR_DETECTION_FAIL = 1,
-+
-+ /* Real radar detected */
-+ WMI_HW_RADAR_DETECTED = 2,
-+};
-+
- #define PHYERR_TLV_SIG 0xBB
- #define PHYERR_TLV_TAG_SEARCH_FFT_REPORT 0xFB
- #define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY 0xF8
-@@ -6586,6 +6614,10 @@ struct wmi_phyerr_hdr_arg {
- const void *phyerrs;
- };
-
-+struct wmi_dfs_status_ev_arg {
-+ u32 status;
-+};
-+
- struct wmi_svc_rdy_ev_arg {
- __le32 min_tx_power;
- __le32 max_tx_power;
+++ /dev/null
-From 260e629bbf441585860e21d5e10d2e88437f47c8 Mon Sep 17 00:00:00 2001
-From: Colin Ian King <colin.king@canonical.com>
-Date: Sun, 27 May 2018 22:17:02 +0100
-Subject: [PATCH] ath10k: fix memory leak of tpc_stats
-
-Currently tpc_stats is allocated and is leaked on the return
-path if num_tx_chain is greater than WMI_TPC_TX_N_CHAIN. Avoid
-this leak by performing the check on num_tx_chain before the
-allocation of tpc_stats.
-
-Detected by CoverityScan, CID#1469422 ("Resource Leak")
-Fixes: 4b190675ad06 ("ath10k: fix kernel panic while reading tpc_stats")
-
-Signed-off-by: Colin Ian King <colin.king@canonical.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/wmi.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -4557,10 +4557,6 @@ void ath10k_wmi_event_pdev_tpc_config(st
-
- ev = (struct wmi_pdev_tpc_config_event *)skb->data;
-
-- tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
-- if (!tpc_stats)
-- return;
--
- num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
-
- if (num_tx_chain > WMI_TPC_TX_N_CHAIN) {
-@@ -4569,6 +4565,10 @@ void ath10k_wmi_event_pdev_tpc_config(st
- return;
- }
-
-+ tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
-+ if (!tpc_stats)
-+ return;
-+
- ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table,
- num_tx_chain);
-
+++ /dev/null
-From 38441fb6fcbb97817dff5c012609860a2b39c3e9 Mon Sep 17 00:00:00 2001
-From: Ben Greear <greearb@candelatech.com>
-Date: Tue, 2 Jan 2018 16:51:01 -0800
-Subject: [PATCH] ath10k: support use of channel 173
-
-The India regulatory domain allows CH 173, so add that to the
-available channel list. I verified basic connectivity between
-a 9880 and 9984 NIC.
-
-Signed-off-by: Ben Greear <greearb@candelatech.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/core.h | 3 ++-
- drivers/net/wireless/ath/ath10k/mac.c | 3 +++
- drivers/net/wireless/ath/ath10k/wmi.c | 2 +-
- 3 files changed, 6 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/core.h
-+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -47,7 +47,8 @@
- #define WMI_READY_TIMEOUT (5 * HZ)
- #define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ)
- #define ATH10K_CONNECTION_LOSS_HZ (3 * HZ)
--#define ATH10K_NUM_CHANS 40
-+#define ATH10K_NUM_CHANS 41
-+#define ATH10K_MAX_5G_CHAN 173
-
- /* Antenna noise floor */
- #define ATH10K_DEFAULT_NOISE_FLOOR -95
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -7766,6 +7766,9 @@ static const struct ieee80211_channel at
- CHAN5G(161, 5805, 0),
- CHAN5G(165, 5825, 0),
- CHAN5G(169, 5845, 0),
-+ CHAN5G(173, 5865, 0),
-+ /* If you add more, you may need to change ATH10K_MAX_5G_CHAN */
-+ /* And you will definitely need to change ATH10K_NUM_CHANS in core.h */
- };
-
- struct ath10k *ath10k_mac_create(size_t priv_size)
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -2363,7 +2363,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath1
- */
- if (channel >= 1 && channel <= 14) {
- status->band = NL80211_BAND_2GHZ;
-- } else if (channel >= 36 && channel <= 169) {
-+ } else if (channel >= 36 && channel <= ATH10K_MAX_5G_CHAN) {
- status->band = NL80211_BAND_5GHZ;
- } else {
- /* Shouldn't happen unless list of advertised channels to
+++ /dev/null
-From 2e9bcd0d73243f5e49daf92508d64cc33c30da01 Mon Sep 17 00:00:00 2001
-From: Karthikeyan Periyasamy <periyasa@codeaurora.org>
-Date: Tue, 29 May 2018 17:01:13 +0530
-Subject: [PATCH] ath10k: fix spectral scan for QCA9984 and QCA9888 chipsets
-
-The spectral scan has been always broken on QCA9984 and QCA9888.
-
-Introduce a hardware parameter 'spectral_bin_offset' to resolve this issue for
-QCA9984 and QCA9888 chipsets. For other chipsets, the hardware parameter
-'spectral_bin_offset' is zero so that existing behaviour is retained as it is.
-
-In QCA9984 and QCA9888 chipsets, hardware param value 'spectral_bin_discard'
-is 12 bytes. This 12 bytes is derived as the sum of segment index (4 bytes),
-extra bins before the actual data (4 bytes) and extra bins after the actual
-data (4 bytes). Always discarding (12 bytes) happens at end of the samples and
-incorrect samples got dumped, so that user can find incorrect arrangement
-samples in spectral scan dump.
-
-To fix this issue, we have to discard first 8 bytes and last 4 bytes in every
-samples, so totally 12 bytes are discarded. In every sample we need to consider
-the offset while taking the actual spectral data. For QCA9984, QCA9888 the
-offset is 8 bytes (segment index + extra bins before actual data).
-
-Hardware tested: QCA9984 and QCA9888
-Firmware tested: 10.4-3.5.3-00053
-
-Signed-off-by: Karthikeyan Periyasamy <periyasa@codeaurora.org>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/ath/ath10k/core.c | 13 +++++++++++++
- drivers/net/wireless/ath/ath10k/hw.h | 3 +++
- drivers/net/wireless/ath/ath10k/spectral.c | 2 +-
- 3 files changed, 17 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ath/ath10k/core.c
-+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -72,6 +72,7 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca988x_ops,
- .decap_align_bytes = 4,
- .spectral_bin_discard = 0,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 8,
-@@ -96,6 +97,7 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca988x_ops,
- .decap_align_bytes = 4,
- .spectral_bin_discard = 0,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 8,
-@@ -119,6 +121,7 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca988x_ops,
- .decap_align_bytes = 4,
- .spectral_bin_discard = 0,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 8,
-@@ -142,6 +145,7 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca988x_ops,
- .decap_align_bytes = 4,
- .spectral_bin_discard = 0,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 8,
-@@ -165,6 +169,8 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca988x_ops,
- .decap_align_bytes = 4,
- .spectral_bin_discard = 0,
-+ .spectral_bin_offset = 0,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 8,
-@@ -191,6 +197,7 @@ static const struct ath10k_hw_params ath
- .target_cpu_freq = 176000000,
- .decap_align_bytes = 4,
- .spectral_bin_discard = 0,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 8,
-@@ -220,6 +227,7 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca99x0_ops,
- .decap_align_bytes = 1,
- .spectral_bin_discard = 4,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 11,
-@@ -250,6 +258,7 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca99x0_ops,
- .decap_align_bytes = 1,
- .spectral_bin_discard = 12,
-+ .spectral_bin_offset = 8,
-
- /* Can do only 2x2 VHT160 or 80+80. 1560Mbps is 4x4 80Mhz
- * or 2x2 160Mhz, long-guard-interval.
-@@ -283,6 +292,7 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca99x0_ops,
- .decap_align_bytes = 1,
- .spectral_bin_discard = 12,
-+ .spectral_bin_offset = 8,
-
- /* Can do only 1x1 VHT160 or 80+80. 780Mbps is 2x2 80Mhz or
- * 1x1 160Mhz, long-guard-interval.
-@@ -310,6 +320,7 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca988x_ops,
- .decap_align_bytes = 4,
- .spectral_bin_discard = 0,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 8,
-@@ -335,6 +346,7 @@ static const struct ath10k_hw_params ath
- .target_cpu_freq = 176000000,
- .decap_align_bytes = 4,
- .spectral_bin_discard = 0,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 8,
-@@ -365,6 +377,7 @@ static const struct ath10k_hw_params ath
- .hw_ops = &qca99x0_ops,
- .decap_align_bytes = 1,
- .spectral_bin_discard = 4,
-+ .spectral_bin_offset = 0,
- .vht160_mcs_rx_highest = 0,
- .vht160_mcs_tx_highest = 0,
- .n_cipher_suites = 11,
---- a/drivers/net/wireless/ath/ath10k/hw.h
-+++ b/drivers/net/wireless/ath/ath10k/hw.h
-@@ -553,6 +553,9 @@ struct ath10k_hw_params {
-
- /* Number of ciphers supported (i.e First N) in cipher_suites array */
- int n_cipher_suites;
-+
-+ /* Number of bytes to be the offset for each FFT sample */
-+ int spectral_bin_offset;
- };
-
- struct htt_rx_desc;
---- a/drivers/net/wireless/ath/ath10k/spectral.c
-+++ b/drivers/net/wireless/ath/ath10k/spectral.c
-@@ -145,7 +145,7 @@ int ath10k_spectral_process_fft(struct a
- fft_sample->noise = __cpu_to_be16(phyerr->nf_chains[chain_idx]);
-
- bins = (u8 *)fftr;
-- bins += sizeof(*fftr);
-+ bins += sizeof(*fftr) + ar->hw_params.spectral_bin_offset;
-
- fft_sample->tsf = __cpu_to_be64(tsf);
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Mon, 20 Aug 2018 11:35:05 +0200
-Subject: [PATCH] ath9k: fix tx99 with monitor mode interface
-
-Tx99 is typically configured via a monitor mode interface, which does
-not get added to the driver as a vif. Since the code currently expects
-a configured virtual interface for tx99, enabling tx99 via debugfs fails.
-Since the vif is not needed anyway, remove all checks for it.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -1074,7 +1074,6 @@ struct ath_softc {
-
- struct ath_spec_scan_priv spec_priv;
-
-- struct ieee80211_vif *tx99_vif;
- struct sk_buff *tx99_skb;
- bool tx99_state;
- s16 tx99_power;
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -1251,15 +1251,10 @@ static int ath9k_add_interface(struct ie
- struct ath_vif *avp = (void *)vif->drv_priv;
- struct ath_node *an = &avp->mcast_node;
-
-- mutex_lock(&sc->mutex);
-+ if (IS_ENABLED(CPTCFG_ATH9K_TX99))
-+ return -EOPNOTSUPP;
-
-- if (IS_ENABLED(CPTCFG_ATH9K_TX99)) {
-- if (sc->cur_chan->nvifs >= 1) {
-- mutex_unlock(&sc->mutex);
-- return -EOPNOTSUPP;
-- }
-- sc->tx99_vif = vif;
-- }
-+ mutex_lock(&sc->mutex);
-
- ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
- sc->cur_chan->nvifs++;
-@@ -1342,7 +1337,6 @@ static void ath9k_remove_interface(struc
- ath9k_p2p_remove_vif(sc, vif);
-
- sc->cur_chan->nvifs--;
-- sc->tx99_vif = NULL;
- if (!ath9k_is_chanctx_enabled())
- list_del(&avp->list);
-
---- a/drivers/net/wireless/ath/ath9k/tx99.c
-+++ b/drivers/net/wireless/ath/ath9k/tx99.c
-@@ -54,12 +54,6 @@ static struct sk_buff *ath9k_build_tx99_
- struct ieee80211_hdr *hdr;
- struct ieee80211_tx_info *tx_info;
- struct sk_buff *skb;
-- struct ath_vif *avp;
--
-- if (!sc->tx99_vif)
-- return NULL;
--
-- avp = (struct ath_vif *)sc->tx99_vif->drv_priv;
-
- skb = alloc_skb(len, GFP_KERNEL);
- if (!skb)
-@@ -77,14 +71,11 @@ static struct sk_buff *ath9k_build_tx99_
- memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
- memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
-
-- hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
--
- tx_info = IEEE80211_SKB_CB(skb);
- memset(tx_info, 0, sizeof(*tx_info));
- rate = &tx_info->control.rates[0];
- tx_info->band = sc->cur_chan->chandef.chan->band;
- tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
-- tx_info->control.vif = sc->tx99_vif;
- rate->count = 1;
- if (ah->curchan && IS_CHAN_HT(ah->curchan)) {
- rate->flags |= IEEE80211_TX_RC_MCS;
---- a/drivers/net/wireless/ath/ath9k/xmit.c
-+++ b/drivers/net/wireless/ath/ath9k/xmit.c
-@@ -2973,7 +2973,7 @@ int ath9k_tx99_send(struct ath_softc *sc
- return -EINVAL;
- }
-
-- ath_set_rates(sc->tx99_vif, NULL, bf);
-+ ath_set_rates(NULL, NULL, bf);
-
- 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);
+++ /dev/null
---- a/drivers/net/wireless/ath/Makefile
-+++ b/drivers/net/wireless/ath/Makefile
-@@ -13,10 +13,10 @@ ath-objs := main.o \
- regd.o \
- hw.o \
- key.o \
-+ debug.o \
- dfs_pattern_detector.o \
- dfs_pri_detector.o
-
--ath-$(CPTCFG_ATH_DEBUG) += debug.o
- ath-$(CPTCFG_ATH_TRACEPOINTS) += trace.o
-
- CFLAGS_trace.o := -I$(src)
---- a/drivers/net/wireless/ath/ath.h
-+++ b/drivers/net/wireless/ath/ath.h
-@@ -318,14 +318,7 @@ void _ath_dbg(struct ath_common *common,
- #endif /* CPTCFG_ATH_DEBUG */
-
- /** Returns string describing opmode, or NULL if unknown mode. */
--#ifdef CPTCFG_ATH_DEBUG
- const char *ath_opmode_to_string(enum nl80211_iftype opmode);
--#else
--static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
--{
-- return "UNKNOWN";
--}
--#endif
-
- extern const char *ath_bus_type_strings[];
- static inline const char *ath_bus_type_to_string(enum ath_bus_type bustype)
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -47,7 +47,7 @@ int ath9k_modparam_nohwcrypt;
- module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
- MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
-
--int ath9k_led_blink;
-+int ath9k_led_blink = 1;
- module_param_named(blink, ath9k_led_blink, int, 0444);
- MODULE_PARM_DESC(blink, "Enable LED blink on activity");
-
+++ /dev/null
---- a/drivers/net/wireless/ath/regd.c
-+++ b/drivers/net/wireless/ath/regd.c
-@@ -24,6 +24,7 @@
- #include "regd_common.h"
-
- static int __ath_regd_init(struct ath_regulatory *reg);
-+static struct reg_dmn_pair_mapping *ath_get_regpair(int regdmn);
-
- /*
- * This is a set of common rules used by our world regulatory domains.
-@@ -116,6 +117,9 @@ static const struct ieee80211_regdomain
-
- static bool dynamic_country_user_possible(struct ath_regulatory *reg)
- {
-+ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
-+ return true;
-+
- if (IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
- return true;
-
-@@ -188,6 +192,8 @@ static bool dynamic_country_user_possibl
-
- static bool ath_reg_dyn_country_user_allow(struct ath_regulatory *reg)
- {
-+ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
-+ return true;
- if (!IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_REG_HINTS))
- return false;
- if (!dynamic_country_user_possible(reg))
-@@ -345,6 +351,9 @@ ath_reg_apply_beaconing_flags(struct wip
- struct ieee80211_channel *ch;
- unsigned int i;
-
-+ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
-+ return;
-+
- for (band = 0; band < NUM_NL80211_BANDS; band++) {
- if (!wiphy->bands[band])
- continue;
-@@ -378,6 +387,9 @@ ath_reg_apply_ir_flags(struct wiphy *wip
- {
- struct ieee80211_supported_band *sband;
-
-+ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
-+ return;
-+
- sband = wiphy->bands[NL80211_BAND_2GHZ];
- if (!sband)
- return;
-@@ -407,6 +419,9 @@ static void ath_reg_apply_radar_flags(st
- struct ieee80211_channel *ch;
- unsigned int i;
-
-+ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
-+ return;
-+
- if (!wiphy->bands[NL80211_BAND_5GHZ])
- return;
-
-@@ -639,6 +654,10 @@ ath_regd_init_wiphy(struct ath_regulator
- const struct ieee80211_regdomain *regd;
-
- wiphy->reg_notifier = reg_notifier;
-+
-+ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
-+ return 0;
-+
- wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
- REGULATORY_CUSTOM_REG;
-
---- a/drivers/net/wireless/ath/Kconfig
-+++ b/drivers/net/wireless/ath/Kconfig
-@@ -23,6 +23,9 @@ config WLAN_VENDOR_ATH
-
- if WLAN_VENDOR_ATH
-
-+config ATH_USER_REGD
-+ bool "Do not enforce EEPROM regulatory restrictions"
-+
- config ATH_DEBUG
- bool "Atheros wireless debugging"
- ---help---
---- a/local-symbols
-+++ b/local-symbols
-@@ -87,6 +87,7 @@ ADM8211=
- ATH_COMMON=
- WLAN_VENDOR_ATH=
- ATH_DEBUG=
-+ATH_USER_REGD=
- ATH_TRACEPOINTS=
- ATH_REG_DYNAMIC_USER_REG_HINTS=
- ATH_REG_DYNAMIC_USER_CERT_TESTING=
+++ /dev/null
---- a/drivers/net/wireless/ath/regd.c
-+++ b/drivers/net/wireless/ath/regd.c
-@@ -44,7 +44,8 @@ static struct reg_dmn_pair_mapping *ath_
- NL80211_RRF_NO_OFDM)
-
- /* We allow IBSS on these on a case by case basis by regulatory domain */
--#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\
-+#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\
-+ REG_RULE(5260-10, 5350+10, 80, 0, 30,\
- NL80211_RRF_NO_IR)
- #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\
- NL80211_RRF_NO_IR)
-@@ -62,57 +63,56 @@ static struct reg_dmn_pair_mapping *ath_
- #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
- ATH9K_5GHZ_5725_5850
-
-+#define REGD_RULES(...) \
-+ .reg_rules = { __VA_ARGS__ }, \
-+ .n_reg_rules = ARRAY_SIZE(((struct ieee80211_reg_rule[]) { __VA_ARGS__ }))
-+
- /* Can be used for:
- * 0x60, 0x61, 0x62 */
- static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
-- .n_reg_rules = 5,
- .alpha2 = "99",
-- .reg_rules = {
-+ REGD_RULES(
- ATH9K_2GHZ_ALL,
- ATH9K_5GHZ_ALL,
-- }
-+ )
- };
-
- /* Can be used by 0x63 and 0x65 */
- static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
-- .n_reg_rules = 4,
- .alpha2 = "99",
-- .reg_rules = {
-+ REGD_RULES(
- ATH9K_2GHZ_CH01_11,
- ATH9K_2GHZ_CH12_13,
- ATH9K_5GHZ_NO_MIDBAND,
-- }
-+ )
- };
-
- /* Can be used by 0x64 only */
- static const struct ieee80211_regdomain ath_world_regdom_64 = {
-- .n_reg_rules = 3,
- .alpha2 = "99",
-- .reg_rules = {
-+ REGD_RULES(
- ATH9K_2GHZ_CH01_11,
- ATH9K_5GHZ_NO_MIDBAND,
-- }
-+ )
- };
-
- /* Can be used by 0x66 and 0x69 */
- static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
-- .n_reg_rules = 3,
- .alpha2 = "99",
-- .reg_rules = {
-+ REGD_RULES(
- ATH9K_2GHZ_CH01_11,
- ATH9K_5GHZ_ALL,
-- }
-+ )
- };
-
- /* Can be used by 0x67, 0x68, 0x6A and 0x6C */
- static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
-- .n_reg_rules = 4,
- .alpha2 = "99",
-- .reg_rules = {
-+ REGD_RULES(
- ATH9K_2GHZ_CH01_11,
- ATH9K_2GHZ_CH12_13,
- ATH9K_5GHZ_ALL,
-- }
-+ )
- };
-
- static bool dynamic_country_user_possible(struct ath_regulatory *reg)
+++ /dev/null
---- a/net/wireless/reg.c
-+++ b/net/wireless/reg.c
-@@ -2860,6 +2860,8 @@ void regulatory_hint_country_ie(struct w
- enum environment_cap env = ENVIRON_ANY;
- struct regulatory_request *request = NULL, *lr;
-
-+ return;
-+
- /* IE len must be evenly divisible by 2 */
- if (country_ie_len & 0x01)
- return;
-@@ -3066,6 +3068,7 @@ static void restore_regulatory_settings(
-
- void regulatory_hint_disconnect(void)
- {
-+ return;
- pr_debug("All devices are disconnected, going to restore regulatory settings\n");
- restore_regulatory_settings(false);
- }
+++ /dev/null
---- a/drivers/net/wireless/ath/regd_common.h
-+++ b/drivers/net/wireless/ath/regd_common.h
-@@ -32,6 +32,7 @@ enum EnumRd {
- FCC2_WORLD = 0x21,
- FCC2_ETSIC = 0x22,
- FCC6_WORLD = 0x23,
-+ FCC3_FCCA_2 = 0x2A,
- FRANCE_RES = 0x31,
- FCC3_FCCA = 0x3A,
- FCC3_WORLD = 0x3B,
-@@ -167,6 +168,7 @@ static struct reg_dmn_pair_mapping regDo
- {FCC2_WORLD, CTL_FCC, CTL_ETSI},
- {FCC2_ETSIC, CTL_FCC, CTL_ETSI},
- {FCC3_FCCA, CTL_FCC, CTL_FCC},
-+ {FCC3_FCCA_2, CTL_FCC, CTL_FCC},
- {FCC3_WORLD, CTL_FCC, CTL_ETSI},
- {FCC4_FCCA, CTL_FCC, CTL_FCC},
- {FCC5_FCCA, CTL_FCC, CTL_FCC},
-@@ -463,6 +465,7 @@ static struct country_code_to_enum_rd al
- {CTRY_UAE, NULL1_WORLD, "AE"},
- {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
- {CTRY_UNITED_STATES, FCC3_FCCA, "US"},
-+ {CTRY_UNITED_STATES, FCC3_FCCA_2, "US"},
- /* This "PS" is for US public safety actually... to support this we
- * would need to assign new special alpha2 to CRDA db as with the world
- * regdomain and use another alpha2 */
+++ /dev/null
---- a/drivers/net/wireless/ath/regd.c
-+++ b/drivers/net/wireless/ath/regd.c
-@@ -115,6 +115,16 @@ static const struct ieee80211_regdomain
- )
- };
-
-+static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
-+{
-+ return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
-+}
-+
-+static bool is_default_regd(struct ath_regulatory *reg)
-+{
-+ return ath_regd_get_eepromRD(reg) == CTRY_DEFAULT;
-+}
-+
- static bool dynamic_country_user_possible(struct ath_regulatory *reg)
- {
- if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
-@@ -123,6 +133,9 @@ static bool dynamic_country_user_possibl
- if (IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
- return true;
-
-+ if (is_default_regd(reg))
-+ return true;
-+
- switch (reg->country_code) {
- case CTRY_UNITED_STATES:
- case CTRY_JAPAN1:
-@@ -208,11 +221,6 @@ static inline bool is_wwr_sku(u16 regd)
- (regd == WORLD));
- }
-
--static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
--{
-- return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
--}
--
- bool ath_is_world_regd(struct ath_regulatory *reg)
- {
- return is_wwr_sku(ath_regd_get_eepromRD(reg));
-@@ -658,6 +666,9 @@ ath_regd_init_wiphy(struct ath_regulator
- if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
- return 0;
-
-+ if (is_default_regd(reg))
-+ return 0;
-+
- wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
- REGULATORY_CUSTOM_REG;
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -777,6 +777,7 @@ static const struct ieee80211_iface_limi
- BIT(NL80211_IFTYPE_AP) },
- { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_P2P_GO) },
-+ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
- };
-
- #ifdef CPTCFG_WIRELESS_WDS
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
-+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
-@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw
- goto end;
- }
-
-- /* Don't allow other interfaces if one ad-hoc is configured.
-- * TODO: Fix the problems with ad-hoc and multiple other interfaces.
-- * We would need to operate the HW in ad-hoc mode to allow TSF updates
-- * for the IBSS, but this breaks with additional AP or STA interfaces
-- * at the moment. */
-- if (ah->num_adhoc_vifs ||
-- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
-+ /* Don't allow more than one ad-hoc interface */
-+ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
- ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
- ret = -ELNRNG;
- goto end;
---- a/drivers/net/wireless/ath/ath5k/base.c
-+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -1965,7 +1965,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
- }
-
- if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
-- ah->num_mesh_vifs > 1) ||
-+ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) ||
- ah->opmode == NL80211_IFTYPE_MESH_POINT) {
- u64 tsf = ath5k_hw_get_tsf64(ah);
- u32 tsftu = TSF_TO_TU(tsf);
-@@ -2051,7 +2051,7 @@ ath5k_beacon_update_timers(struct ath5k_
-
- intval = ah->bintval & AR5K_BEACON_PERIOD;
- if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
-- + ah->num_mesh_vifs > 1) {
-+ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) {
- intval /= ATH_BCBUF; /* staggered multi-bss beacons */
- if (intval < 15)
- ATH5K_WARN(ah, "intval %u is too low, min 15\n",
-@@ -2518,6 +2518,7 @@ static const struct ieee80211_iface_limi
- BIT(NL80211_IFTYPE_MESH_POINT) |
- #endif
- BIT(NL80211_IFTYPE_AP) },
-+ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
- };
-
- static const struct ieee80211_iface_combination if_comb = {
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/reset.c
-+++ b/drivers/net/wireless/ath/ath5k/reset.c
-@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
- tsf_lo = 0;
- mode = 0;
-
-+#if 0
- /*
- * Sanity check for fast flag
- * Fast channel change only available
-@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
- */
- if (fast && (ah->ah_radio != AR5K_RF2413) &&
- (ah->ah_radio != AR5K_RF5413))
-+#endif
- fast = false;
-
- /* Disable sleep clock operation
+++ /dev/null
---- /dev/null
-+++ b/include/linux/ath5k_platform.h
-@@ -0,0 +1,30 @@
-+/*
-+ * Copyright (c) 2008 Atheros Communications Inc.
-+ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
-+ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
-+ * Copyright (c) 2010 Daniel Golle <daniel.golle@gmail.com>
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#ifndef _LINUX_ATH5K_PLATFORM_H
-+#define _LINUX_ATH5K_PLATFORM_H
-+
-+#define ATH5K_PLAT_EEP_MAX_WORDS 2048
-+
-+struct ath5k_platform_data {
-+ u16 *eeprom_data;
-+ u8 *macaddr;
-+};
-+
-+#endif /* _LINUX_ATH5K_PLATFORM_H */
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/pci.c
-+++ b/drivers/net/wireless/ath/ath5k/pci.c
-@@ -21,6 +21,7 @@
- #include <linux/pci-aspm.h>
- #include <linux/etherdevice.h>
- #include <linux/module.h>
-+#include <linux/ath5k_platform.h>
- #include "../ath.h"
- #include "ath5k.h"
- #include "debug.h"
-@@ -72,7 +73,7 @@ static void ath5k_pci_read_cachesize(str
- }
-
- /*
-- * Read from eeprom
-+ * Read from eeprom or platform_data
- */
- static bool
- ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
-@@ -80,6 +81,19 @@ ath5k_pci_eeprom_read(struct ath_common
- struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
- u32 status, timeout;
-
-+ struct ath5k_platform_data *pdata = NULL;
-+
-+ if (ah->pdev)
-+ pdata = ah->pdev->dev.platform_data;
-+
-+ if (pdata && pdata->eeprom_data && pdata->eeprom_data[61] == AR5K_EEPROM_MAGIC_VALUE) {
-+ if (offset >= ATH5K_PLAT_EEP_MAX_WORDS)
-+ return false;
-+
-+ *data = pdata->eeprom_data[offset];
-+ return true;
-+ }
-+
- /*
- * Initialize EEPROM access
- */
-@@ -123,6 +137,16 @@ static int ath5k_pci_eeprom_read_mac(str
- u16 data;
- int octet;
-
-+ struct ath5k_platform_data *pdata = NULL;
-+
-+ if (ah->pdev)
-+ pdata = ah->pdev->dev.platform_data;
-+
-+ if (pdata && pdata->macaddr) {
-+ memcpy(mac, pdata->macaddr, ETH_ALEN);
-+ return 0;
-+ }
-+
- AR5K_EEPROM_READ(0x20, data);
-
- for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+++ /dev/null
---- a/drivers/net/wireless/ath/ath5k/pci.c
-+++ b/drivers/net/wireless/ath/ath5k/pci.c
-@@ -48,6 +48,8 @@ static const struct pci_device_id ath5k_
- { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
- { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
- { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
-+ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */
-+ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */
- { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */
- { 0 }
- };
+++ /dev/null
-This adds a bwmode debugfs file which can be used to set alternate
-channel operating bandwidths. Only tested with AR5413 and only at
-5 and 20 mhz channels.
-
-Signed-off-by: Pat Erley <pat-lkml at erley.org>
----
-Other devices will need to be added to the switch in write_file_bwmode
-
-drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++
- 1 files changed, 86 insertions(+), 0 deletions(-)
-
---- a/drivers/net/wireless/ath/ath5k/debug.c
-+++ b/drivers/net/wireless/ath/ath5k/debug.c
-@@ -822,6 +822,97 @@ static const struct file_operations fops
- .llseek = default_llseek,
- };
-
-+/* debugfs: bwmode */
-+
-+static ssize_t read_file_bwmode(struct file *file, char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath5k_hw *ah = file->private_data;
-+ char buf[15];
-+ unsigned int len = 0;
-+
-+ int cur_ah_bwmode = ah->ah_bwmode_debug;
-+
-+#define print_selected(MODE, LABEL) \
-+ if (cur_ah_bwmode == MODE) \
-+ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \
-+ else \
-+ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \
-+ len += snprintf(buf+len, sizeof(buf)-len, " ");
-+
-+ print_selected(AR5K_BWMODE_5MHZ, "5");
-+ print_selected(AR5K_BWMODE_10MHZ, "10");
-+ print_selected(AR5K_BWMODE_DEFAULT, "20");
-+ print_selected(AR5K_BWMODE_40MHZ, "40");
-+#undef print_selected
-+
-+ len += snprintf(buf+len, sizeof(buf)-len, "\n");
-+
-+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-+}
-+
-+static ssize_t write_file_bwmode(struct file *file,
-+ const char __user *userbuf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath5k_hw *ah = file->private_data;
-+ char buf[3];
-+ int bw = 20;
-+ int tobwmode = AR5K_BWMODE_DEFAULT;
-+
-+ if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
-+ return -EFAULT;
-+
-+ /* TODO: Add check for active interface */
-+
-+ if(strncmp(buf, "5", 1) == 0 ) {
-+ tobwmode = AR5K_BWMODE_5MHZ;
-+ bw = 5;
-+ } else if ( strncmp(buf, "10", 2) == 0 ) {
-+ tobwmode = AR5K_BWMODE_10MHZ;
-+ bw = 10;
-+ } else if ( strncmp(buf, "20", 2) == 0 ) {
-+ tobwmode = AR5K_BWMODE_DEFAULT;
-+ bw = 20;
-+ } else if ( strncmp(buf, "40", 2) == 0 ) {
-+ tobwmode = AR5K_BWMODE_40MHZ;
-+ bw = 40;
-+ } else
-+ return -EINVAL;
-+
-+ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n",
-+ bw, tobwmode);
-+
-+ switch (ah->ah_radio) {
-+ /* TODO: only define radios that actually support 5/10mhz channels */
-+ case AR5K_RF5413:
-+ case AR5K_RF5110:
-+ case AR5K_RF5111:
-+ case AR5K_RF5112:
-+ case AR5K_RF2413:
-+ case AR5K_RF2316:
-+ case AR5K_RF2317:
-+ case AR5K_RF2425:
-+ if(ah->ah_bwmode_debug != tobwmode) {
-+ mutex_lock(&ah->lock);
-+ ah->ah_bwmode = tobwmode;
-+ ah->ah_bwmode_debug = tobwmode;
-+ mutex_unlock(&ah->lock);
-+ }
-+ break;
-+ default:
-+ return -EOPNOTSUPP;
-+ }
-+ return count;
-+}
-+
-+static const struct file_operations fops_bwmode = {
-+ .read = read_file_bwmode,
-+ .write = write_file_bwmode,
-+ .open = simple_open,
-+ .owner = THIS_MODULE,
-+ .llseek = default_llseek,
-+};
-
- /* debugfs: queues etc */
-
-@@ -1012,6 +1103,9 @@ ath5k_debug_init_device(struct ath5k_hw
- debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, ah,
- &fops_beacon);
-
-+ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah,
-+ &fops_bwmode);
-+
- debugfs_create_file("reset", S_IWUSR, phydir, ah, &fops_reset);
-
- debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, ah,
---- a/drivers/net/wireless/ath/ath5k/ath5k.h
-+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
-@@ -1372,6 +1372,7 @@ struct ath5k_hw {
- u8 ah_coverage_class;
- bool ah_ack_bitrate_high;
- u8 ah_bwmode;
-+ u8 ah_bwmode_debug;
- bool ah_short_slot;
-
- /* Antenna Control */
---- a/drivers/net/wireless/ath/ath5k/base.c
-+++ b/drivers/net/wireless/ath/ath5k/base.c
-@@ -466,6 +466,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru
- return -EINVAL;
- }
-
-+ if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT)
-+ ah->ah_bwmode = ah->ah_bwmode_debug;
-+
- /*
- * To switch channels clear any pending DMA operations;
- * wait long enough for the RX fifo to drain, reset the
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1374,6 +1374,53 @@ void ath9k_deinit_debug(struct ath_softc
- ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
- }
-
-+static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath_softc *sc = file->private_data;
-+ struct ath_hw *ah = sc->sc_ah;
-+ struct ath_common *common = ath9k_hw_common(ah);
-+ int bytes = 0;
-+ int pos = *ppos;
-+ int size = 4096;
-+ u16 val;
-+ int i;
-+
-+ if (AR_SREV_9300_20_OR_LATER(ah))
-+ size = 16384;
-+
-+ if (*ppos < 0)
-+ return -EINVAL;
-+
-+ if (count > size - *ppos)
-+ count = size - *ppos;
-+
-+ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) {
-+ void *from = &val;
-+
-+ if (!common->bus_ops->eeprom_read(common, i, &val))
-+ val = 0xffff;
-+
-+ if (*ppos % 2) {
-+ from++;
-+ bytes = 1;
-+ } else if (count == 1) {
-+ bytes = 1;
-+ } else {
-+ bytes = 2;
-+ }
-+ copy_to_user(user_buf, from, bytes);
-+ user_buf += bytes;
-+ }
-+ return *ppos - pos;
-+}
-+
-+static const struct file_operations fops_eeprom = {
-+ .read = read_file_eeprom,
-+ .open = simple_open,
-+ .owner = THIS_MODULE
-+};
-+
- int ath9k_init_debug(struct ath_hw *ah)
- {
- struct ath_common *common = ath9k_hw_common(ah);
-@@ -1393,6 +1440,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);
-
-+ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
-+ &fops_eeprom);
- debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
- read_file_dma);
- debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -1088,23 +1088,23 @@ static int __init ath9k_init(void)
- {
- int error;
-
-- error = ath_pci_init();
-+ error = ath_ahb_init();
- if (error < 0) {
-- pr_err("No PCI devices found, driver not installed\n");
- error = -ENODEV;
- goto err_out;
- }
-
-- error = ath_ahb_init();
-+ error = ath_pci_init();
- if (error < 0) {
-+ pr_err("No PCI devices found, driver not installed\n");
- error = -ENODEV;
-- goto err_pci_exit;
-+ goto err_ahb_exit;
- }
-
- return 0;
-
-- err_pci_exit:
-- ath_pci_exit();
-+ err_ahb_exit:
-+ ath_ahb_exit();
- err_out:
- return error;
- }
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -390,13 +390,8 @@ static void ath9k_hw_init_config(struct
-
- ah->config.rx_intr_mitigation = true;
-
-- if (AR_SREV_9300_20_OR_LATER(ah)) {
-- ah->config.rimt_last = 500;
-- ah->config.rimt_first = 2000;
-- } else {
-- ah->config.rimt_last = 250;
-- ah->config.rimt_first = 700;
-- }
-+ ah->config.rimt_last = 250;
-+ ah->config.rimt_first = 500;
-
- if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
- ah->config.pll_pwrsave = 7;
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -88,7 +88,7 @@ int ath_descdma_setup(struct ath_softc *
- (_l) &= ((_sz) - 1); \
- } while (0)
-
--#define ATH_RXBUF 512
-+#define ATH_RXBUF 256
- #define ATH_TXBUF 512
- #define ATH_TXBUF_RESERVE 5
- #define ATH_TXMAXTRY 13
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1421,6 +1421,52 @@ static const struct file_operations fops
- .owner = THIS_MODULE
- };
-
-+
-+static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath_softc *sc = file->private_data;
-+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+ char buf[32];
-+ unsigned int len;
-+
-+ len = sprintf(buf, "0x%08x\n", common->chan_bw);
-+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-+}
-+
-+static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath_softc *sc = file->private_data;
-+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-+ unsigned long chan_bw;
-+ char buf[32];
-+ ssize_t len;
-+
-+ len = min(count, sizeof(buf) - 1);
-+ if (copy_from_user(buf, user_buf, len))
-+ return -EFAULT;
-+
-+ buf[len] = '\0';
-+ if (kstrtoul(buf, 0, &chan_bw))
-+ return -EINVAL;
-+
-+ common->chan_bw = chan_bw;
-+ if (!test_bit(ATH_OP_INVALID, &common->op_flags))
-+ ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL);
-+
-+ return count;
-+}
-+
-+static const struct file_operations fops_chanbw = {
-+ .read = read_file_chan_bw,
-+ .write = write_file_chan_bw,
-+ .open = simple_open,
-+ .owner = THIS_MODULE,
-+ .llseek = default_llseek,
-+};
-+
-+
- int ath9k_init_debug(struct ath_hw *ah)
- {
- struct ath_common *common = ath9k_hw_common(ah);
-@@ -1442,6 +1488,8 @@ int ath9k_init_debug(struct ath_hw *ah)
-
- debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
- &fops_eeprom);
-+ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-+ sc, &fops_chanbw);
- debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
- read_file_dma);
- debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
---- a/drivers/net/wireless/ath/ath.h
-+++ b/drivers/net/wireless/ath/ath.h
-@@ -151,6 +151,7 @@ struct ath_common {
- int debug_mask;
- enum ath_device_state state;
- unsigned long op_flags;
-+ u32 chan_bw;
-
- struct ath_ani ani;
-
---- a/drivers/net/wireless/ath/ath9k/common.c
-+++ b/drivers/net/wireless/ath/ath9k/common.c
-@@ -297,11 +297,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke
- /*
- * Update internal channel flags.
- */
--static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
-+static void ath9k_cmn_update_ichannel(struct ath_common *common,
-+ struct ath9k_channel *ichan,
- struct cfg80211_chan_def *chandef)
- {
- struct ieee80211_channel *chan = chandef->chan;
- u16 flags = 0;
-+ int width;
-
- ichan->channel = chan->center_freq;
- ichan->chan = chan;
-@@ -309,7 +311,19 @@ static void ath9k_cmn_update_ichannel(st
- if (chan->band == NL80211_BAND_5GHZ)
- flags |= CHANNEL_5GHZ;
-
-- switch (chandef->width) {
-+ switch (common->chan_bw) {
-+ case 5:
-+ width = NL80211_CHAN_WIDTH_5;
-+ break;
-+ case 10:
-+ width = NL80211_CHAN_WIDTH_10;
-+ break;
-+ default:
-+ width = chandef->width;
-+ break;
-+ }
-+
-+ switch (width) {
- case NL80211_CHAN_WIDTH_5:
- flags |= CHANNEL_QUARTER;
- break;
-@@ -342,10 +356,11 @@ struct ath9k_channel *ath9k_cmn_get_chan
- struct cfg80211_chan_def *chandef)
- {
- struct ieee80211_channel *curchan = chandef->chan;
-+ struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_channel *channel;
-
- channel = &ah->channels[curchan->hw_value];
-- ath9k_cmn_update_ichannel(channel, chandef);
-+ ath9k_cmn_update_ichannel(common, channel, chandef);
-
- return channel;
- }
+++ /dev/null
---- 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)
-
- /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */
- switch (ah->hw_version.devid) {
-+ case AR9300_DEVID_INVALID:
- case AR5416_DEVID_PCI:
- case AR5416_DEVID_PCIE:
- case AR5416_AR9100_DEVID:
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -36,6 +36,7 @@
-
- #define ATHEROS_VENDOR_ID 0x168c
-
-+#define AR9300_DEVID_INVALID 0xabcd
- #define AR5416_DEVID_PCI 0x0023
- #define AR5416_DEVID_PCIE 0x0024
- #define AR9160_DEVID_PCI 0x0027
---- a/drivers/net/wireless/ath/ath9k/pci.c
-+++ b/drivers/net/wireless/ath/ath9k/pci.c
-@@ -773,6 +773,7 @@ static const struct pci_device_id ath_pc
- .driver_data = ATH9K_PCI_BT_ANT_DIV },
- #endif
-
-+ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */
- { 0 }
- };
-
+++ /dev/null
---- a/include/net/cfg80211.h
-+++ b/include/net/cfg80211.h
-@@ -2750,6 +2750,7 @@ struct cfg80211_pmk_conf {
- * (as advertised by the nl80211 feature flag.)
- * @get_tx_power: store the current TX power into the dbm variable;
- * return 0 if successful
-+ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
- *
- * @set_wds_peer: set the WDS peer for a WDS interface
- *
-@@ -3041,6 +3042,7 @@ struct cfg80211_ops {
- enum nl80211_tx_power_setting type, int mbm);
- int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
- int *dbm);
-+ int (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
-
- int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
- const u8 *addr);
---- a/include/net/mac80211.h
-+++ b/include/net/mac80211.h
-@@ -1338,6 +1338,7 @@ enum ieee80211_smps_mode {
- *
- * @power_level: requested transmit power (in dBm), backward compatibility
- * value only that is set to the minimum of all interfaces
-+ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
- *
- * @chandef: the channel definition to tune to
- * @radar_enabled: whether radar detection is enabled
-@@ -1358,6 +1359,7 @@ enum ieee80211_smps_mode {
- struct ieee80211_conf {
- u32 flags;
- int power_level, dynamic_ps_timeout;
-+ int max_antenna_gain;
-
- u16 listen_interval;
- u8 ps_dtim_period;
---- a/include/uapi/linux/nl80211.h
-+++ b/include/uapi/linux/nl80211.h
-@@ -2153,6 +2153,9 @@ enum nl80211_commands {
- * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
- * @NL80211_ATTR_PORT_AUTHORIZED: (reserved)
- *
-+ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
-+ * transmit power to stay within regulatory limits. u32, dBi.
-+ *
- * @NUM_NL80211_ATTR: total number of nl80211_attrs available
- * @NL80211_ATTR_MAX: highest attribute number currently defined
- * @__NL80211_ATTR_AFTER_LAST: internal use
-@@ -2579,6 +2582,8 @@ enum nl80211_attrs {
- NL80211_ATTR_PMKR0_NAME,
- NL80211_ATTR_PORT_AUTHORIZED,
-
-+ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
-+
- /* add attributes here, update the policy in nl80211.c */
-
- __NL80211_ATTR_AFTER_LAST,
---- a/net/mac80211/cfg.c
-+++ b/net/mac80211/cfg.c
-@@ -2447,6 +2447,19 @@ static int ieee80211_get_tx_power(struct
- return 0;
- }
-
-+static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
-+{
-+ struct ieee80211_local *local = wiphy_priv(wiphy);
-+
-+ if (dbi < 0)
-+ return -EINVAL;
-+
-+ local->user_antenna_gain = dbi;
-+ ieee80211_hw_config(local, 0);
-+
-+ return 0;
-+}
-+
- static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
- const u8 *addr)
- {
-@@ -3721,6 +3734,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,
-+ .set_antenna_gain = ieee80211_set_antenna_gain,
- .set_wds_peer = ieee80211_set_wds_peer,
- .rfkill_poll = ieee80211_rfkill_poll,
- CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
---- a/net/mac80211/ieee80211_i.h
-+++ b/net/mac80211/ieee80211_i.h
-@@ -1348,6 +1348,7 @@ struct ieee80211_local {
- int dynamic_ps_forced_timeout;
-
- int user_power_level; /* in dBm, for all interfaces */
-+ int user_antenna_gain; /* in dBi */
-
- enum ieee80211_smps_mode smps_mode;
-
---- a/net/mac80211/main.c
-+++ b/net/mac80211/main.c
-@@ -93,7 +93,7 @@ static u32 ieee80211_hw_conf_chan(struct
- struct ieee80211_sub_if_data *sdata;
- struct cfg80211_chan_def chandef = {};
- u32 changed = 0;
-- int power;
-+ int power, max_power;
- u32 offchannel_flag;
-
- offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
-@@ -150,6 +150,12 @@ static u32 ieee80211_hw_conf_chan(struct
- }
- rcu_read_unlock();
-
-+ max_power = chandef.chan->max_reg_power;
-+ if (local->user_antenna_gain > 0) {
-+ max_power -= local->user_antenna_gain;
-+ power = min(power, max_power);
-+ }
-+
- if (local->hw.conf.power_level != power) {
- changed |= IEEE80211_CONF_CHANGE_POWER;
- local->hw.conf.power_level = power;
-@@ -611,6 +617,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
- IEEE80211_RADIOTAP_MCS_HAVE_BW;
- local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
- IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
-+ local->user_antenna_gain = 0;
- local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
- local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
- local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
---- a/net/wireless/nl80211.c
-+++ b/net/wireless/nl80211.c
-@@ -420,6 +420,7 @@ static const struct nla_policy nl80211_p
- [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
- [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
- [NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
-+ [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
- };
-
- /* policy for the key attributes */
-@@ -2395,6 +2396,20 @@ static int nl80211_set_wiphy(struct sk_b
- if (result)
- return result;
- }
-+
-+ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
-+ int idx, dbi = 0;
-+
-+ if (!rdev->ops->set_antenna_gain)
-+ return -EOPNOTSUPP;
-+
-+ idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
-+ dbi = nla_get_u32(info->attrs[idx]);
-+
-+ result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
-+ if (result)
-+ return result;
-+ }
-
- if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
- info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -850,6 +850,9 @@ static inline int ath9k_dump_btcoex(stru
- #ifdef CPTCFG_MAC80211_LEDS
- void ath_init_leds(struct ath_softc *sc);
- void ath_deinit_leds(struct ath_softc *sc);
-+int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
-+ const char *trigger, bool active_low);
-+
- #else
- static inline void ath_init_leds(struct ath_softc *sc)
- {
-@@ -991,6 +994,13 @@ void ath_ant_comb_scan(struct ath_softc
- #define AIRTIME_USE_NEW_QUEUES BIT(2)
- #define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX)))
-
-+struct ath_led {
-+ struct list_head list;
-+ struct ath_softc *sc;
-+ const struct gpio_led *gpio;
-+ struct led_classdev cdev;
-+};
-+
- struct ath_softc {
- struct ieee80211_hw *hw;
- struct device *dev;
-@@ -1046,9 +1056,8 @@ struct ath_softc {
- spinlock_t chan_lock;
-
- #ifdef CPTCFG_MAC80211_LEDS
-- bool led_registered;
-- char led_name[32];
-- struct led_classdev led_cdev;
-+ const char *led_default_trigger;
-+ struct list_head leds;
- #endif
-
- #ifdef CPTCFG_ATH9K_DEBUGFS
---- a/drivers/net/wireless/ath/ath9k/gpio.c
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -39,61 +39,111 @@ static void ath_fill_led_pin(struct ath_
- else
- ah->led_pin = ATH_LED_PIN_DEF;
- }
-+}
-+
-+static void ath_led_brightness(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
-+{
-+ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev);
-+ struct ath_softc *sc = led->sc;
-+
-+ ath9k_ps_wakeup(sc);
-+ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio,
-+ (brightness != LED_OFF) ^ led->gpio->active_low);
-+ ath9k_ps_restore(sc);
-+}
-+
-+static int ath_add_led(struct ath_softc *sc, struct ath_led *led)
-+{
-+ const struct gpio_led *gpio = led->gpio;
-+ int ret;
-+
-+ led->cdev.name = gpio->name;
-+ led->cdev.default_trigger = gpio->default_trigger;
-+ led->cdev.brightness_set = ath_led_brightness;
-+
-+ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev);
-+ if (ret < 0)
-+ return ret;
-+
-+ led->sc = sc;
-+ list_add(&led->list, &sc->leds);
-
- /* Configure gpio for output */
-- ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led",
-+ ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name,
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-
-- /* LED off, active low */
-- ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1);
-+ /* LED off */
-+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
-+
-+ return 0;
- }
-
--static void ath_led_brightness(struct led_classdev *led_cdev,
-- enum led_brightness brightness)
-+int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name,
-+ const char *trigger, bool active_low)
- {
-- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
-- u32 val = (brightness == LED_OFF);
-+ struct ath_led *led;
-+ struct gpio_led *gpio;
-+ char *_name;
-+ int ret;
-
-- if (sc->sc_ah->config.led_active_high)
-- val = !val;
-+ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1,
-+ GFP_KERNEL);
-+ if (!led)
-+ return -ENOMEM;
-+
-+ led->gpio = gpio = (struct gpio_led *) (led + 1);
-+ _name = (char *) (led->gpio + 1);
-+
-+ strcpy(_name, name);
-+ gpio->name = _name;
-+ gpio->gpio = gpio_num;
-+ gpio->active_low = active_low;
-+ gpio->default_trigger = trigger;
-+
-+ ret = ath_add_led(sc, led);
-+ if (unlikely(ret < 0))
-+ kfree(led);
-
-- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
-+ return ret;
- }
-
- void ath_deinit_leds(struct ath_softc *sc)
- {
-- if (!sc->led_registered)
-- return;
-+ struct ath_led *led;
-
-- ath_led_brightness(&sc->led_cdev, LED_OFF);
-- led_classdev_unregister(&sc->led_cdev);
--
-- ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin);
-+ while (!list_empty(&sc->leds)) {
-+ led = list_first_entry(&sc->leds, struct ath_led, list);
-+ list_del(&led->list);
-+ ath_led_brightness(&led->cdev, LED_OFF);
-+ led_classdev_unregister(&led->cdev);
-+ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
-+ kfree(led);
-+ }
- }
-
- void ath_init_leds(struct ath_softc *sc)
- {
-- int ret;
-+ char led_name[32];
-+ const char *trigger;
-+
-+ INIT_LIST_HEAD(&sc->leds);
-
- if (AR_SREV_9100(sc->sc_ah))
- return;
-
- ath_fill_led_pin(sc);
-
-- if (!ath9k_led_blink)
-- sc->led_cdev.default_trigger =
-- ieee80211_get_radio_led_name(sc->hw);
--
-- snprintf(sc->led_name, sizeof(sc->led_name),
-- "ath9k-%s", wiphy_name(sc->hw->wiphy));
-- sc->led_cdev.name = sc->led_name;
-- sc->led_cdev.brightness_set = ath_led_brightness;
-+ snprintf(led_name, sizeof(led_name), "ath9k-%s",
-+ wiphy_name(sc->hw->wiphy));
-
-- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
-- if (ret < 0)
-- return;
-+ if (ath9k_led_blink)
-+ trigger = sc->led_default_trigger;
-+ else
-+ trigger = ieee80211_get_radio_led_name(sc->hw);
-
-- sc->led_registered = true;
-+ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
-+ !sc->sc_ah->config.led_active_high);
- }
- #endif
-
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -1000,7 +1000,7 @@ int ath9k_init_device(u16 devid, struct
-
- #ifdef CPTCFG_MAC80211_LEDS
- /* must be initialized before ieee80211_register_hw */
-- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
-+ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
- IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
- ARRAY_SIZE(ath9k_tpt_blink));
- #endif
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1466,6 +1466,61 @@ static const struct file_operations fops
- .llseek = default_llseek,
- };
-
-+#ifdef CONFIG_MAC80211_LEDS
-+
-+static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath_softc *sc = file->private_data;
-+ char buf[32], *str, *name, *c;
-+ ssize_t len;
-+ unsigned int gpio;
-+ bool active_low = false;
-+
-+ len = min(count, sizeof(buf) - 1);
-+ if (copy_from_user(buf, ubuf, len))
-+ return -EFAULT;
-+
-+ buf[len] = '\0';
-+ name = strchr(buf, ',');
-+ if (!name)
-+ return -EINVAL;
-+
-+ *(name++) = 0;
-+ if (!*name)
-+ return -EINVAL;
-+
-+ c = strchr(name, '\n');
-+ if (c)
-+ *c = 0;
-+
-+ str = buf;
-+ if (*str == '!') {
-+ str++;
-+ active_low = true;
-+ }
-+
-+ if (kstrtouint(str, 0, &gpio) < 0)
-+ return -EINVAL;
-+
-+ if (gpio >= sc->sc_ah->caps.num_gpio_pins)
-+ return -EINVAL;
-+
-+ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0)
-+ return -EINVAL;
-+
-+ return count;
-+}
-+
-+static const struct file_operations fops_gpio_led = {
-+ .write = write_file_gpio_led,
-+ .open = simple_open,
-+ .owner = THIS_MODULE,
-+ .llseek = default_llseek,
-+};
-+
-+#endif
-+
-
- int ath9k_init_debug(struct ath_hw *ah)
- {
-@@ -1490,6 +1545,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);
-+#ifdef CONFIG_MAC80211_LEDS
-+ debugfs_create_file("gpio_led", S_IWUSR,
-+ sc->debug.debugfs_phy, sc, &fops_gpio_led);
-+#endif
- debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
- read_file_dma);
- debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
+++ /dev/null
---- a/include/linux/ath9k_platform.h
-+++ b/include/linux/ath9k_platform.h
-@@ -46,6 +46,9 @@ struct ath9k_platform_data {
- int (*external_reset)(void);
-
- bool use_eeprom;
-+
-+ int num_leds;
-+ const struct gpio_led *leds;
- };
-
- #endif /* _LINUX_ATH9K_PLATFORM_H */
---- a/drivers/net/wireless/ath/ath9k/gpio.c
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -15,6 +15,7 @@
- */
-
- #include "ath9k.h"
-+#include <linux/ath9k_platform.h>
-
- /********************************/
- /* LED functions */
-@@ -108,6 +109,24 @@ int ath_create_gpio_led(struct ath_softc
- return ret;
- }
-
-+static int ath_create_platform_led(struct ath_softc *sc,
-+ const struct gpio_led *gpio)
-+{
-+ struct ath_led *led;
-+ int ret;
-+
-+ led = kzalloc(sizeof(*led), GFP_KERNEL);
-+ if (!led)
-+ return -ENOMEM;
-+
-+ led->gpio = gpio;
-+ ret = ath_add_led(sc, led);
-+ if (ret < 0)
-+ kfree(led);
-+
-+ return ret;
-+}
-+
- void ath_deinit_leds(struct ath_softc *sc)
- {
- struct ath_led *led;
-@@ -124,8 +143,10 @@ void ath_deinit_leds(struct ath_softc *s
-
- void ath_init_leds(struct ath_softc *sc)
- {
-+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
- char led_name[32];
- const char *trigger;
-+ int i;
-
- INIT_LIST_HEAD(&sc->leds);
-
-@@ -134,6 +155,17 @@ void ath_init_leds(struct ath_softc *sc)
-
- ath_fill_led_pin(sc);
-
-+ if (pdata && pdata->leds && pdata->num_leds)
-+ for (i = 0; i < pdata->num_leds; i++) {
-+ if (pdata->leds[i].gpio == sc->sc_ah->led_pin)
-+ sc->sc_ah->led_pin = -1;
-+
-+ ath_create_platform_led(sc, &pdata->leds[i]);
-+ }
-+
-+ if (sc->sc_ah->led_pin < 0)
-+ return;
-+
- snprintf(led_name, sizeof(led_name), "ath9k-%s",
- wiphy_name(sc->hw->wiphy));
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ani.h
-+++ b/drivers/net/wireless/ath/ath9k/ani.h
-@@ -42,7 +42,7 @@
- #define ATH9K_ANI_PERIOD 300
-
- /* in ms */
--#define ATH9K_ANI_POLLINTERVAL 1000
-+#define ATH9K_ANI_POLLINTERVAL 300
-
- #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0
- #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/debug.c
-+++ b/drivers/net/wireless/ath/ath9k/debug.c
-@@ -1522,6 +1522,50 @@ static const struct file_operations fops
- #endif
-
-
-+static ssize_t read_file_diag(struct file *file, char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath_softc *sc = file->private_data;
-+ struct ath_hw *ah = sc->sc_ah;
-+ char buf[32];
-+ unsigned int len;
-+
-+ len = sprintf(buf, "0x%08lx\n", ah->diag);
-+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-+}
-+
-+static ssize_t write_file_diag(struct file *file, const char __user *user_buf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct ath_softc *sc = file->private_data;
-+ struct ath_hw *ah = sc->sc_ah;
-+ unsigned long diag;
-+ char buf[32];
-+ ssize_t len;
-+
-+ len = min(count, sizeof(buf) - 1);
-+ if (copy_from_user(buf, user_buf, len))
-+ return -EFAULT;
-+
-+ buf[len] = '\0';
-+ if (kstrtoul(buf, 0, &diag))
-+ return -EINVAL;
-+
-+ ah->diag = diag;
-+ ath9k_hw_update_diag(ah);
-+
-+ return count;
-+}
-+
-+static const struct file_operations fops_diag = {
-+ .read = read_file_diag,
-+ .write = write_file_diag,
-+ .open = simple_open,
-+ .owner = THIS_MODULE,
-+ .llseek = default_llseek,
-+};
-+
-+
- int ath9k_init_debug(struct ath_hw *ah)
- {
- struct ath_common *common = ath9k_hw_common(ah);
-@@ -1549,6 +1593,8 @@ int ath9k_init_debug(struct ath_hw *ah)
- debugfs_create_file("gpio_led", S_IWUSR,
- sc->debug.debugfs_phy, sc, &fops_gpio_led);
- #endif
-+ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
-+ sc, &fops_diag);
- debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
- read_file_dma);
- 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
-@@ -520,6 +520,12 @@ enum {
- ATH9K_RESET_COLD,
- };
-
-+enum {
-+ ATH_DIAG_DISABLE_RX,
-+ ATH_DIAG_DISABLE_TX,
-+ ATH_DIAG_TRIGGER_ERROR,
-+};
-+
- struct ath9k_hw_version {
- u32 magic;
- u16 devid;
-@@ -806,6 +812,8 @@ struct ath_hw {
- u32 ah_flags;
- s16 nf_override;
-
-+ unsigned long diag;
-+
- bool reset_power_on;
- bool htc_reset_init;
-
-@@ -1068,6 +1076,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
- bool ath9k_hw_check_alive(struct ath_hw *ah);
-
- bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
-+void ath9k_hw_update_diag(struct ath_hw *ah);
-
- /* Generic hw timer primitives */
- struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -1842,6 +1842,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
- }
- EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
-
-+void ath9k_hw_update_diag(struct ath_hw *ah)
-+{
-+ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag))
-+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
-+ else
-+ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
-+
-+ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag))
-+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
-+ else
-+ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
-+}
-+EXPORT_SYMBOL(ath9k_hw_update_diag);
-+
- int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
- struct ath9k_hw_cal_data *caldata, bool fastcc)
- {
-@@ -2050,6 +2064,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
- ar9003_hw_disable_phy_restart(ah);
-
- ath9k_hw_apply_gpio_override(ah);
-+ ath9k_hw_update_diag(ah);
-
- if (AR_SREV_9565(ah) && common->bt_ant_diversity)
- REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -528,6 +528,11 @@ irqreturn_t ath_isr(int irq, void *dev)
- if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
- return IRQ_HANDLED;
-
-+ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) {
-+ status |= ATH9K_INT_FATAL;
-+ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag);
-+ }
-+
- /*
- * If there are no status bits set, then this interrupt was not
- * for me (should have been caught above).
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/hw.h
-+++ b/drivers/net/wireless/ath/ath9k/hw.h
-@@ -721,6 +721,7 @@ struct ath_spec_scan {
- * @config_pci_powersave:
- * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
- *
-+ * @get_adc_entropy: get entropy from the raw ADC I/Q output
- * @spectral_scan_config: set parameters for spectral scan and enable/disable it
- * @spectral_scan_trigger: trigger a spectral scan run
- * @spectral_scan_wait: wait for a spectral scan run to finish
-@@ -743,6 +744,7 @@ struct ath_hw_ops {
- struct ath_hw_antcomb_conf *antconf);
- void (*antdiv_comb_conf_set)(struct ath_hw *ah,
- struct ath_hw_antcomb_conf *antconf);
-+ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len);
- void (*spectral_scan_config)(struct ath_hw *ah,
- struct ath_spec_scan *param);
- void (*spectral_scan_trigger)(struct ath_hw *ah);
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -1945,6 +1945,26 @@ void ar9003_hw_init_rate_txpower(struct
- }
- }
-
-+static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
-+{
-+ int i, j;
-+
-+ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
-+ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
-+ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0);
-+
-+ memset(buf, 0, len);
-+ for (i = 0; i < len; i++) {
-+ for (j = 0; j < 4; j++) {
-+ u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
-+
-+ buf[i] <<= 2;
-+ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9);
-+ udelay(1);
-+ }
-+ }
-+}
-+
- void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
- {
- struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
-@@ -1981,6 +2001,7 @@ void ar9003_hw_attach_phy_ops(struct ath
- priv_ops->set_radar_params = ar9003_hw_set_radar_params;
- priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
-
-+ ops->get_adc_entropy = ar9003_hw_get_adc_entropy;
- ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
- ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
- ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -765,7 +765,8 @@ static void ath9k_init_txpower_limits(st
- if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
- ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ);
-
-- ah->curchan = curchan;
-+ if (curchan)
-+ ah->curchan = curchan;
- }
-
- static const struct ieee80211_iface_limit if_limits[] = {
-@@ -960,6 +961,18 @@ static void ath9k_set_hw_capab(struct at
- wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
- }
-
-+static void ath_get_initial_entropy(struct ath_softc *sc)
-+{
-+ struct ath_hw *ah = sc->sc_ah;
-+ char buf[256];
-+
-+ /* reuse last channel initialized by the tx power test */
-+ ath9k_hw_reset(ah, ah->curchan, NULL, false);
-+
-+ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf));
-+ add_device_randomness(buf, sizeof(buf));
-+}
-+
- int ath9k_init_device(u16 devid, struct ath_softc *sc,
- const struct ath_bus_ops *bus_ops)
- {
-@@ -1005,6 +1018,8 @@ int ath9k_init_device(u16 devid, struct
- ARRAY_SIZE(ath9k_tpt_blink));
- #endif
-
-+ ath_get_initial_entropy(sc);
-+
- /* Register with mac80211 */
- error = ieee80211_register_hw(hw);
- if (error)
---- a/drivers/net/wireless/ath/ath9k/hw-ops.h
-+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
-@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp
- ath9k_hw_ops(ah)->tx99_set_txpower(ah, power);
- }
-
-+static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah,
-+ u8 *buf, size_t len)
-+{
-+ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len);
-+}
-+
- #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
-
- static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-@@ -1322,9 +1322,30 @@ void ar5008_hw_init_rate_txpower(struct
- }
- }
-
-+static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
-+{
-+ int i, j;
-+
-+ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
-+ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
-+ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0);
-+
-+ memset(buf, 0, len);
-+ for (i = 0; i < len; i++) {
-+ for (j = 0; j < 4; j++) {
-+ u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
-+
-+ buf[i] <<= 2;
-+ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8);
-+ udelay(1);
-+ }
-+ }
-+}
-+
- int ar5008_hw_attach_phy_ops(struct ath_hw *ah)
- {
- struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
-+ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
- static const u32 ar5416_cca_regs[6] = {
- AR_PHY_CCA,
- AR_PHY_CH1_CCA,
-@@ -1339,6 +1360,8 @@ int ar5008_hw_attach_phy_ops(struct ath_
- if (ret)
- return ret;
-
-+ ops->get_adc_entropy = ar5008_hw_get_adc_entropy;
-+
- priv_ops->rf_set_freq = ar5008_hw_set_channel;
- priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
-
---- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
-+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
-@@ -20,6 +20,12 @@
- #define PHY_AGC_CLR 0x10000000
- #define RFSILENT_BB 0x00002000
-
-+#define AR_PHY_TEST_BBB_OBS_SEL 0x780000
-+#define AR_PHY_TEST_BBB_OBS_SEL_S 19
-+
-+#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23
-+#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S)
-+
- #define AR_PHY_TURBO 0x9804
- #define AR_PHY_FC_TURBO_MODE 0x00000001
- #define AR_PHY_FC_TURBO_SHORT 0x00000002
-@@ -36,6 +42,9 @@
-
- #define AR_PHY_TEST2 0x9808
-
-+#define AR_PHY_TEST2_RX_OBS_SEL 0x3C00
-+#define AR_PHY_TEST2_RX_OBS_SEL_S 10
-+
- #define AR_PHY_TIMING2 0x9810
- #define AR_PHY_TIMING3 0x9814
- #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
-@@ -393,6 +402,8 @@
- #define AR_PHY_RFBUS_GRANT 0x9C20
- #define AR_PHY_RFBUS_GRANT_EN 0x00000001
-
-+#define AR_PHY_TST_ADC 0x9C24
-+
- #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
- #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
-
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/hw.c
-+++ b/drivers/net/wireless/ath/ath9k/hw.c
-@@ -246,6 +246,19 @@ void ath9k_hw_get_channel_centers(struct
- centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
- }
-
-+static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah)
-+{
-+ /* On AR9330 and AR9340 devices, some PHY registers must be
-+ * tuned to gain better stability/performance. These registers
-+ * might be changed while doing wlan reset so the registers must
-+ * be reprogrammed after each reset.
-+ */
-+ REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20));
-+ REG_RMW(ah, AR_PHY_USB_CTRL2,
-+ (1 << 21) | (0xf << 22),
-+ (1 << 21) | (0x3 << 22));
-+}
-+
- /******************/
- /* Chip Revisions */
- /******************/
-@@ -1414,6 +1427,9 @@ static bool ath9k_hw_set_reset(struct at
- udelay(50);
- }
-
-+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+ ath9k_hw_disable_pll_lock_detect(ah);
-+
- return true;
- }
-
-@@ -1513,6 +1529,9 @@ static bool ath9k_hw_chip_reset(struct a
- ar9003_hw_internal_regulator_apply(ah);
- ath9k_hw_init_pll(ah, chan);
-
-+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+ ath9k_hw_disable_pll_lock_detect(ah);
-+
- return true;
- }
-
-@@ -1820,8 +1839,14 @@ static int ath9k_hw_do_fastcc(struct ath
- if (AR_SREV_9271(ah))
- ar9002_hw_load_ani_reg(ah, chan);
-
-+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+ ath9k_hw_disable_pll_lock_detect(ah);
-+
- return 0;
- fail:
-+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+ ath9k_hw_disable_pll_lock_detect(ah);
-+
- return -EINVAL;
- }
-
-@@ -2075,6 +2100,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
- ath9k_hw_set_radar_params(ah);
- }
-
-+ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
-+ ath9k_hw_disable_pll_lock_detect(ah);
-+
- return 0;
- }
- EXPORT_SYMBOL(ath9k_hw_reset);
---- a/drivers/net/wireless/ath/ath9k/phy.h
-+++ b/drivers/net/wireless/ath/ath9k/phy.h
-@@ -48,6 +48,9 @@
- #define AR_PHY_PLL_CONTROL 0x16180
- #define AR_PHY_PLL_MODE 0x16184
-
-+#define AR_PHY_USB_CTRL1 0x16c84
-+#define AR_PHY_USB_CTRL2 0x16c88
-+
- enum ath9k_ant_div_comb_lna_conf {
- ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
- ATH_ANT_DIV_COMB_LNA2,
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
-@@ -951,55 +951,6 @@ static bool ar5008_hw_ani_control_new(st
- * on == 0 means more noise imm
- */
- u32 on = param ? 1 : 0;
-- /*
-- * make register setting for default
-- * (weak sig detect ON) come from INI file
-- */
-- int m1ThreshLow = on ?
-- aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
-- int m2ThreshLow = on ?
-- aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
-- int m1Thresh = on ?
-- aniState->iniDef.m1Thresh : m1Thresh_off;
-- int m2Thresh = on ?
-- aniState->iniDef.m2Thresh : m2Thresh_off;
-- int m2CountThr = on ?
-- aniState->iniDef.m2CountThr : m2CountThr_off;
-- int m2CountThrLow = on ?
-- aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
-- int m1ThreshLowExt = on ?
-- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
-- int m2ThreshLowExt = on ?
-- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
-- int m1ThreshExt = on ?
-- aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
-- int m2ThreshExt = on ?
-- aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
--
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-- AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
-- m1ThreshLow);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-- AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
-- m2ThreshLow);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-- AR_PHY_SFCORR_M1_THRESH, m1Thresh);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-- AR_PHY_SFCORR_M2_THRESH, m2Thresh);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-- AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
-- m2CountThrLow);
--
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-- AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-- AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
-
- if (on)
- REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
---- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
-@@ -42,20 +42,6 @@ static const int cycpwrThr1_table[] =
- /* level: 0 1 2 3 4 5 6 7 8 */
- { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */
-
--/*
-- * register values to turn OFDM weak signal detection OFF
-- */
--static const int m1ThreshLow_off = 127;
--static const int m2ThreshLow_off = 127;
--static const int m1Thresh_off = 127;
--static const int m2Thresh_off = 127;
--static const int m2CountThr_off = 31;
--static const int m2CountThrLow_off = 63;
--static const int m1ThreshLowExt_off = 127;
--static const int m2ThreshLowExt_off = 127;
--static const int m1ThreshExt_off = 127;
--static const int m2ThreshExt_off = 127;
--
- static const u8 ofdm2pwr[] = {
- ALL_TARGET_LEGACY_6_24,
- ALL_TARGET_LEGACY_6_24,
-@@ -1095,11 +1081,6 @@ static bool ar9003_hw_ani_control(struct
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath9k_channel *chan = ah->curchan;
- struct ar5416AniState *aniState = &ah->ani;
-- int m1ThreshLow, m2ThreshLow;
-- int m1Thresh, m2Thresh;
-- int m2CountThr, m2CountThrLow;
-- int m1ThreshLowExt, m2ThreshLowExt;
-- int m1ThreshExt, m2ThreshExt;
- s32 value, value2;
-
- switch (cmd & ah->ani_function) {
-@@ -1113,61 +1094,6 @@ static bool ar9003_hw_ani_control(struct
- */
- u32 on = param ? 1 : 0;
-
-- if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
-- goto skip_ws_det;
--
-- m1ThreshLow = on ?
-- aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
-- m2ThreshLow = on ?
-- aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
-- m1Thresh = on ?
-- aniState->iniDef.m1Thresh : m1Thresh_off;
-- m2Thresh = on ?
-- aniState->iniDef.m2Thresh : m2Thresh_off;
-- m2CountThr = on ?
-- aniState->iniDef.m2CountThr : m2CountThr_off;
-- m2CountThrLow = on ?
-- aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
-- m1ThreshLowExt = on ?
-- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
-- m2ThreshLowExt = on ?
-- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
-- m1ThreshExt = on ?
-- aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
-- m2ThreshExt = on ?
-- aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
--
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-- AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
-- m1ThreshLow);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-- AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
-- m2ThreshLow);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-- AR_PHY_SFCORR_M1_THRESH,
-- m1Thresh);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-- AR_PHY_SFCORR_M2_THRESH,
-- m2Thresh);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
-- AR_PHY_SFCORR_M2COUNT_THR,
-- m2CountThr);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
-- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
-- m2CountThrLow);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-- AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
-- m1ThreshLowExt);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-- AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
-- m2ThreshLowExt);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-- AR_PHY_SFCORR_EXT_M1_THRESH,
-- m1ThreshExt);
-- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
-- AR_PHY_SFCORR_EXT_M2_THRESH,
-- m2ThreshExt);
--skip_ws_det:
- if (on)
- REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
- AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+++ /dev/null
-From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
-Date: Sun, 31 Jan 2016 20:48:49 +0100
-Subject: [PATCH v4 2/8] mac80211: ath9k: set default state for platform LEDs
-
-Support default state for platform LEDs connected to ath9k device.
-Now LEDs are correctly set on or off at ath9k module initialization.
-Very useful if power LED is connected to wireless chip.
-
-Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
----
- gpio.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ath/ath9k/gpio.c
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -74,8 +74,11 @@ static int ath_add_led(struct ath_softc
- ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name,
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-
-- /* LED off */
-- ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
-+ /* Set default LED state */
-+ if (gpio->default_state == LEDS_GPIO_DEFSTATE_ON)
-+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, !gpio->active_low);
-+ else
-+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
-
- return 0;
- }
+++ /dev/null
-From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
-Date: Sun, 31 Jan 2016 21:01:31 +0100
-Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO
-
-Enable access to GPIO chip and its pins for Atheros AR92xx
-wireless devices. For now AR9285 and AR9287 are supported.
-
-Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -24,6 +24,7 @@
- #include <linux/completion.h>
- #include <linux/time.h>
- #include <linux/hw_random.h>
-+#include <linux/gpio/driver.h>
-
- #include "common.h"
- #include "debug.h"
-@@ -1001,6 +1002,14 @@ struct ath_led {
- struct led_classdev cdev;
- };
-
-+#ifdef CONFIG_GPIOLIB
-+struct ath9k_gpio_chip {
-+ struct ath_softc *sc;
-+ char label[32];
-+ struct gpio_chip gchip;
-+};
-+#endif
-+
- struct ath_softc {
- struct ieee80211_hw *hw;
- struct device *dev;
-@@ -1058,6 +1067,9 @@ struct ath_softc {
- #ifdef CPTCFG_MAC80211_LEDS
- const char *led_default_trigger;
- struct list_head leds;
-+#ifdef CONFIG_GPIOLIB
-+ struct ath9k_gpio_chip *gpiochip;
-+#endif
- #endif
-
- #ifdef CPTCFG_ATH9K_DEBUGFS
---- a/drivers/net/wireless/ath/ath9k/gpio.c
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -16,13 +16,130 @@
-
- #include "ath9k.h"
- #include <linux/ath9k_platform.h>
-+#include <linux/gpio.h>
-+
-+#ifdef CPTCFG_MAC80211_LEDS
-+
-+#ifdef CONFIG_GPIOLIB
-+
-+/***************/
-+/* GPIO Chip */
-+/***************/
-+
-+/* gpio_chip handler : set GPIO to input */
-+static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
-+{
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
-+ gchip);
-+
-+ ath9k_hw_gpio_request_in(gc->sc->sc_ah, offset, "ath9k-gpio");
-+
-+ return 0;
-+}
-+
-+/* gpio_chip handler : set GPIO to output */
-+static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
-+ int value)
-+{
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
-+ gchip);
-+
-+ ath9k_hw_gpio_request_out(gc->sc->sc_ah, offset, "ath9k-gpio",
-+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
-+
-+ return 0;
-+}
-+
-+/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
-+static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
-+{
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
-+ gchip);
-+ struct ath_hw *ah = gc->sc->sc_ah;
-+
-+ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3);
-+}
-+
-+/* gpio_chip handler : get GPIO pin value */
-+static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
-+{
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
-+ gchip);
-+
-+ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
-+}
-+
-+/* gpio_chip handler : set GPIO pin to value */
-+static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
-+ int value)
-+{
-+ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
-+ gchip);
-+
-+ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
-+}
-+
-+/* register GPIO chip */
-+static void ath9k_register_gpio_chip(struct ath_softc *sc)
-+{
-+ struct ath9k_gpio_chip *gc;
-+ struct ath_hw *ah = sc->sc_ah;
-+
-+ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
-+ if (!gc)
-+ return;
-+
-+ gc->sc = sc;
-+ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
-+ wiphy_name(sc->hw->wiphy));
-+
-+ gc->gchip.label = gc->label;
-+ gc->gchip.base = -1; /* determine base automatically */
-+ gc->gchip.ngpio = ah->caps.num_gpio_pins;
-+ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
-+ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
-+ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
-+ gc->gchip.get = ath9k_gpio_pin_get;
-+ gc->gchip.set = ath9k_gpio_pin_set;
-+
-+ if (gpiochip_add(&gc->gchip)) {
-+ kfree(gc);
-+ return;
-+ }
-+
-+ sc->gpiochip = gc;
-+}
-+
-+/* remove GPIO chip */
-+static void ath9k_unregister_gpio_chip(struct ath_softc *sc)
-+{
-+ struct ath9k_gpio_chip *gc = sc->gpiochip;
-+
-+ if (!gc)
-+ return;
-+
-+ gpiochip_remove(&gc->gchip);
-+ kfree(gc);
-+ sc->gpiochip = NULL;
-+}
-+
-+#else /* CONFIG_GPIOLIB */
-+
-+static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
-+{
-+}
-+
-+static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
-+{
-+}
-+
-+#endif /* CONFIG_GPIOLIB */
-
- /********************************/
- /* LED functions */
- /********************************/
-
--#ifdef CPTCFG_MAC80211_LEDS
--
- static void ath_fill_led_pin(struct ath_softc *sc)
- {
- struct ath_hw *ah = sc->sc_ah;
-@@ -80,6 +197,12 @@ static int ath_add_led(struct ath_softc
- else
- ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
-
-+#ifdef CONFIG_GPIOLIB
-+ /* If there is GPIO chip configured, reserve LED pin */
-+ if (sc->gpiochip)
-+ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
-+#endif
-+
- return 0;
- }
-
-@@ -136,17 +259,24 @@ void ath_deinit_leds(struct ath_softc *s
-
- while (!list_empty(&sc->leds)) {
- led = list_first_entry(&sc->leds, struct ath_led, list);
-+#ifdef CONFIG_GPIOLIB
-+ /* If there is GPIO chip configured, free LED pin */
-+ if (sc->gpiochip)
-+ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
-+#endif
- list_del(&led->list);
- ath_led_brightness(&led->cdev, LED_OFF);
- led_classdev_unregister(&led->cdev);
- ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
- kfree(led);
- }
-+ ath9k_unregister_gpio_chip(sc);
- }
-
- void ath_init_leds(struct ath_softc *sc)
- {
- struct ath9k_platform_data *pdata = sc->dev->platform_data;
-+ struct device_node *np = sc->dev->of_node;
- char led_name[32];
- const char *trigger;
- int i;
-@@ -156,6 +286,15 @@ void ath_init_leds(struct ath_softc *sc)
- if (AR_SREV_9100(sc->sc_ah))
- return;
-
-+ if (!np)
-+ ath9k_register_gpio_chip(sc);
-+
-+ /* setup gpio controller only if requested and skip the led_pin setup */
-+ if (of_property_read_bool(np, "gpio-controller")) {
-+ ath9k_register_gpio_chip(sc);
-+ return;
-+ }
-+
- ath_fill_led_pin(sc);
-
- if (pdata && pdata->leds && pdata->num_leds)
-@@ -180,6 +319,7 @@ void ath_init_leds(struct ath_softc *sc)
- ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
- !sc->sc_ah->config.led_active_high);
- }
-+
- #endif
-
- /*******************/
+++ /dev/null
-From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
-Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons
-
-Enable platform-defined GPIO button support for ath9k device.
-Key poller is activated for attached platform buttons.
-Requires ath9k GPIO chip access.
-
-Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -1069,6 +1069,7 @@ struct ath_softc {
- struct list_head leds;
- #ifdef CONFIG_GPIOLIB
- struct ath9k_gpio_chip *gpiochip;
-+ struct platform_device *btnpdev; /* gpio-keys-polled */
- #endif
- #endif
-
---- a/drivers/net/wireless/ath/ath9k/gpio.c
-+++ b/drivers/net/wireless/ath/ath9k/gpio.c
-@@ -17,6 +17,8 @@
- #include "ath9k.h"
- #include <linux/ath9k_platform.h>
- #include <linux/gpio.h>
-+#include <linux/platform_device.h>
-+#include <linux/gpio_keys.h>
-
- #ifdef CPTCFG_MAC80211_LEDS
-
-@@ -124,6 +126,67 @@ static void ath9k_unregister_gpio_chip(s
- sc->gpiochip = NULL;
- }
-
-+/******************/
-+/* GPIO Buttons */
-+/******************/
-+
-+/* add GPIO buttons */
-+static void ath9k_init_buttons(struct ath_softc *sc)
-+{
-+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
-+ struct platform_device *pdev;
-+ struct gpio_keys_platform_data gkpdata;
-+ struct gpio_keys_button *bt;
-+ int i;
-+
-+ if (!sc->gpiochip)
-+ return;
-+
-+ if (!pdata || !pdata->btns || !pdata->num_btns)
-+ return;
-+
-+ bt = devm_kmemdup(sc->dev, pdata->btns,
-+ pdata->num_btns * sizeof(struct gpio_keys_button),
-+ GFP_KERNEL);
-+ if (!bt)
-+ return;
-+
-+ for (i = 0; i < pdata->num_btns; i++) {
-+ if (pdata->btns[i].gpio == sc->sc_ah->led_pin)
-+ sc->sc_ah->led_pin = -1;
-+
-+ ath9k_hw_gpio_request_in(sc->sc_ah, pdata->btns[i].gpio,
-+ "ath9k-gpio");
-+ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio;
-+ }
-+
-+ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data));
-+ gkpdata.buttons = bt;
-+ gkpdata.nbuttons = pdata->num_btns;
-+ gkpdata.poll_interval = pdata->btn_poll_interval;
-+
-+ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled",
-+ PLATFORM_DEVID_AUTO, &gkpdata,
-+ sizeof(gkpdata));
-+ if (!IS_ERR_OR_NULL(pdev))
-+ sc->btnpdev = pdev;
-+ else {
-+ sc->btnpdev = NULL;
-+ devm_kfree(sc->dev, bt);
-+ }
-+}
-+
-+/* remove GPIO buttons */
-+static void ath9k_deinit_buttons(struct ath_softc *sc)
-+{
-+ if (!sc->gpiochip || !sc->btnpdev)
-+ return;
-+
-+ platform_device_unregister(sc->btnpdev);
-+
-+ sc->btnpdev = NULL;
-+}
-+
- #else /* CONFIG_GPIOLIB */
-
- static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
-@@ -134,6 +197,14 @@ static inline void ath9k_unregister_gpio
- {
- }
-
-+static inline void ath9k_init_buttons(struct ath_softc *sc)
-+{
-+}
-+
-+static inline void ath9k_deinit_buttons(struct ath_softc *sc)
-+{
-+}
-+
- #endif /* CONFIG_GPIOLIB */
-
- /********************************/
-@@ -257,6 +328,7 @@ void ath_deinit_leds(struct ath_softc *s
- {
- struct ath_led *led;
-
-+ ath9k_deinit_buttons(sc);
- while (!list_empty(&sc->leds)) {
- led = list_first_entry(&sc->leds, struct ath_led, list);
- #ifdef CONFIG_GPIOLIB
-@@ -296,6 +368,7 @@ void ath_init_leds(struct ath_softc *sc)
- }
-
- ath_fill_led_pin(sc);
-+ ath9k_init_buttons(sc);
-
- if (pdata && pdata->leds && pdata->num_leds)
- for (i = 0; i < pdata->num_leds; i++) {
---- a/include/linux/ath9k_platform.h
-+++ b/include/linux/ath9k_platform.h
-@@ -49,6 +49,10 @@ struct ath9k_platform_data {
-
- int num_leds;
- const struct gpio_led *leds;
-+
-+ unsigned num_btns;
-+ const struct gpio_keys_button *btns;
-+ unsigned btn_poll_interval;
- };
-
- #endif /* _LINUX_ATH9K_PLATFORM_H */
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/init.c
-+++ b/drivers/net/wireless/ath/ath9k/init.c
-@@ -571,6 +571,12 @@ static int ath9k_of_init(struct ath_soft
-
- ath_dbg(common, CONFIG, "parsing configuration from OF node\n");
-
-+ if (of_property_read_bool(np, "qca,disable-2ghz"))
-+ ah->disable_2ghz = true;
-+
-+ if (of_property_read_bool(np, "qca,disable-5ghz"))
-+ ah->disable_5ghz = true;
-+
- if (of_property_read_bool(np, "qca,no-eeprom")) {
- /* ath9k-eeprom-<bus>-<id>.bin */
- scnprintf(eeprom_name, sizeof(eeprom_name),
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/channel.c
-+++ b/drivers/net/wireless/ath/ath9k/channel.c
-@@ -15,6 +15,8 @@
- */
-
- #include "ath9k.h"
-+#include <linux/ath9k_platform.h>
-+#include "hsr.h"
-
- /* Set/change channels. If the channel is really being changed, it's done
- * by reseting the chip. To accomplish this we must first cleanup any pending
-@@ -22,6 +24,7 @@
- */
- static int ath_set_channel(struct ath_softc *sc)
- {
-+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_hw *hw = sc->hw;
-@@ -42,6 +45,11 @@ static int ath_set_channel(struct ath_so
- ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
- chan->center_freq, chandef->width);
-
-+ if (pdata && pdata->ubnt_hsr) {
-+ ath9k_hsr_enable(ah, chandef->width, chan->center_freq);
-+ ath9k_hsr_status(ah);
-+ }
-+
- /* update survey stats for the old channel before switching */
- spin_lock_irqsave(&common->cc_lock, flags);
- ath_update_survey_stats(sc);
---- /dev/null
-+++ b/drivers/net/wireless/ath/ath9k/hsr.c
-@@ -0,0 +1,247 @@
-+/*
-+ *
-+ * The MIT License (MIT)
-+ *
-+ * Copyright (c) 2015 Kirill Berezin
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to deal
-+ * in the Software without restriction, including without limitation the rights
-+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+ * copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-+ * SOFTWARE.
-+ *
-+ */
-+
-+#include <linux/io.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
-+#include <linux/time.h>
-+#include <linux/bitops.h>
-+#include <linux/etherdevice.h>
-+#include <linux/rtnetlink.h>
-+#include <asm/unaligned.h>
-+
-+#include "hw.h"
-+#include "ath9k.h"
-+
-+#define HSR_GPIO_CSN 8
-+#define HSR_GPIO_CLK 6
-+#define HSR_GPIO_DOUT 7
-+#define HSR_GPIO_DIN 5
-+
-+/* delays are in useconds */
-+#define HSR_DELAY_HALF_TICK 100
-+#define HSR_DELAY_PRE_WRITE 75
-+#define HSR_DELAY_FINAL 20000
-+#define HSR_DELAY_TRAILING 200
-+
-+void ath9k_hsr_init(struct ath_hw *ah)
-+{
-+ ath9k_hw_gpio_request_in(ah, HSR_GPIO_DIN, NULL);
-+ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CSN, NULL,
-+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-+ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CLK, NULL,
-+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-+ ath9k_hw_gpio_request_out(ah, HSR_GPIO_DOUT, NULL,
-+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-+
-+ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
-+ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
-+ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0);
-+
-+ udelay(HSR_DELAY_TRAILING);
-+}
-+
-+static u32 ath9k_hsr_write_byte(struct ath_hw *ah, int delay, u32 value)
-+{
-+ struct ath_common *common = ath9k_hw_common(ah);
-+ int i;
-+ u32 rval = 0;
-+
-+ udelay(delay);
-+
-+ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
-+ udelay(HSR_DELAY_HALF_TICK);
-+
-+ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0);
-+ udelay(HSR_DELAY_HALF_TICK);
-+
-+ for (i = 0; i < 8; ++i) {
-+ rval = rval << 1;
-+
-+ /* pattern is left to right, that is 7-th bit runs first */
-+ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1);
-+ udelay(HSR_DELAY_HALF_TICK);
-+
-+ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1);
-+ udelay(HSR_DELAY_HALF_TICK);
-+
-+ rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN);
-+
-+ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
-+ udelay(HSR_DELAY_HALF_TICK);
-+ }
-+
-+ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
-+ udelay(HSR_DELAY_HALF_TICK);
-+
-+ ath_dbg(common, CONFIG, "ath9k_hsr_write_byte: write byte %d return value is %d %c\n",
-+ value, rval, rval > 32 ? rval : '-');
-+
-+ return rval & 0xff;
-+}
-+
-+static int ath9k_hsr_write_a_chain(struct ath_hw *ah, char *chain, int items)
-+{
-+ int status = 0;
-+ int i = 0;
-+ int err;
-+
-+ /* a preamble */
-+ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
-+ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
-+
-+ /* clear HSR's reply buffer */
-+ if (status) {
-+ int loop = 0;
-+
-+ for (loop = 0; (loop < 42) && status; ++loop)
-+ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE,
-+ 0);
-+
-+ if (loop >= 42) {
-+ ATH_DBG_WARN(1,
-+ "ath9k_hsr_write_a_chain: can't clear an output buffer after a 42 cycles.\n");
-+ return -1;
-+ }
-+ }
-+
-+ for (i = 0; (i < items) && (chain[i] != 0); ++i)
-+ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]);
-+
-+ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
-+ mdelay(HSR_DELAY_FINAL / 1000);
-+
-+ /* reply */
-+ memset(chain, 0, items);
-+
-+ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
-+ udelay(HSR_DELAY_TRAILING);
-+
-+ for (i = 0; i < (items - 1); ++i) {
-+ u32 ret;
-+
-+ ret = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
-+ if (ret != 0)
-+ chain[i] = (char)ret;
-+ else
-+ break;
-+
-+ udelay(HSR_DELAY_TRAILING);
-+ }
-+
-+ if (i <= 1)
-+ return 0;
-+
-+ err = kstrtoint(chain + 1, 10, &i);
-+ if (err)
-+ return err;
-+
-+ return i;
-+}
-+
-+int ath9k_hsr_disable(struct ath_hw *ah)
-+{
-+ char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0};
-+ int ret;
-+
-+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
-+ if ((ret > 0) && (*cmd == 'B'))
-+ return 0;
-+
-+ return -1;
-+}
-+
-+int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq)
-+{
-+ char cmd[10];
-+ int ret;
-+
-+ /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn
-+ * 20MHz on invalid values
-+ */
-+ if ((bw != 5) && (bw != 10) && (bw != 20) && (bw != 40))
-+ bw = 20;
-+
-+ memset(cmd, 0, sizeof(cmd));
-+ *cmd = 'b';
-+ snprintf(cmd + 1, 3, "%02d", bw);
-+
-+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
-+ if ((*cmd != 'B') || (ret != bw)) {
-+ ATH_DBG_WARN(1,
-+ "ath9k_hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d)\n",
-+ 'b', bw, *cmd, ret);
-+ return -1;
-+ }
-+
-+ memset(cmd, 0, sizeof(cmd));
-+ *cmd = 'x';
-+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
-+ if (*cmd != 'X') {
-+ ATH_DBG_WARN(1,
-+ "ath9k_hsr_enable: failed 'x' command -> reply (%d, %d)\n",
-+ *cmd, ret);
-+ return -1;
-+ }
-+
-+ memset(cmd, 0, sizeof(cmd));
-+ *cmd = 'm';
-+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
-+ if (*cmd != 'M') {
-+ ATH_DBG_WARN(1,
-+ "ath9k_hsr_enable: failed 'm' command -> reply (%d, %d)\n",
-+ *cmd, ret);
-+ return -1;
-+ }
-+
-+ memset(cmd, 0, sizeof(cmd));
-+ *cmd = 'f';
-+ snprintf(cmd + 1, 6, "%05d", fq);
-+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
-+ if ((*cmd != 'F') && (ret != fq)) {
-+ ATH_DBG_WARN(1,
-+ "ath9k_hsr_enable: failed set frequency -> reply (%d, %d)\n",
-+ *cmd, ret);
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+int ath9k_hsr_status(struct ath_hw *ah)
-+{
-+ char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0};
-+ int ret;
-+
-+ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
-+ if (*cmd != 'S') {
-+ ATH_DBG_WARN(1, "ath9k_hsr_status: returned %d,%d\n", *cmd,
-+ ret);
-+ return -1;
-+ }
-+
-+ return 0;
-+}
---- /dev/null
-+++ b/drivers/net/wireless/ath/ath9k/hsr.h
-@@ -0,0 +1,48 @@
-+/*
-+ * The MIT License (MIT)
-+ *
-+ * Copyright (c) 2015 Kirill Berezin
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a copy
-+ * of this software and associated documentation files (the "Software"), to deal
-+ * in the Software without restriction, including without limitation the rights
-+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+ * copies of the Software, and to permit persons to whom the Software is
-+ * furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice shall be included in
-+ * all copies or substantial portions of the Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-+ * SOFTWARE.
-+ */
-+
-+#ifndef HSR_H
-+#define HSR_H
-+
-+#ifdef CPTCFG_ATH9K_UBNTHSR
-+
-+void ath9k_hsr_init(struct ath_hw *ah);
-+int ath9k_hsr_disable(struct ath_hw *ah);
-+int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq);
-+int ath9k_hsr_status(struct ath_hw *ah);
-+
-+#else
-+static inline void ath9k_hsr_init(struct ath_hw *ah) {}
-+
-+static inline int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq)
-+{
-+ return 0;
-+}
-+
-+static inline int ath9k_hsr_disable(struct ath_hw *ah) { return 0; }
-+static inline int ath9k_hsr_status(struct ath_hw *ah) { return 0; }
-+
-+#endif
-+
-+#endif /* HSR_H */
---- a/drivers/net/wireless/ath/ath9k/main.c
-+++ b/drivers/net/wireless/ath/ath9k/main.c
-@@ -16,8 +16,10 @@
-
- #include <linux/nl80211.h>
- #include <linux/delay.h>
-+#include <linux/ath9k_platform.h>
- #include "ath9k.h"
- #include "btcoex.h"
-+#include "hsr.h"
-
- u8 ath9k_parse_mpdudensity(u8 mpdudensity)
- {
-@@ -649,6 +651,7 @@ void ath_reset_work(struct work_struct *
- static int ath9k_start(struct ieee80211_hw *hw)
- {
- struct ath_softc *sc = hw->priv;
-+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan;
-@@ -727,6 +730,11 @@ static int ath9k_start(struct ieee80211_
- AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
- }
-
-+ if (pdata && pdata->ubnt_hsr) {
-+ ath9k_hsr_init(ah);
-+ ath9k_hsr_disable(ah);
-+ }
-+
- /*
- * Reset key cache to sane defaults (all entries cleared) instead of
- * semi-random values after suspend/resume.
---- a/drivers/net/wireless/ath/ath9k/Makefile
-+++ b/drivers/net/wireless/ath/ath9k/Makefile
-@@ -16,6 +16,7 @@ ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += d
- ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o
- ath9k-$(CPTCFG_ATH9K_WOW) += wow.o
- ath9k-$(CPTCFG_ATH9K_HWRNG) += rng.o
-+ath9k-$(CPTCFG_ATH9K_UBNTHSR) += hsr.o
-
- ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o
-
---- a/include/linux/ath9k_platform.h
-+++ b/include/linux/ath9k_platform.h
-@@ -53,6 +53,8 @@ struct ath9k_platform_data {
- unsigned num_btns;
- const struct gpio_keys_button *btns;
- unsigned btn_poll_interval;
-+
-+ bool ubnt_hsr;
- };
-
- #endif /* _LINUX_ATH9K_PLATFORM_H */
---- a/local-symbols
-+++ b/local-symbols
-@@ -114,6 +114,7 @@ ATH9K_WOW=
- ATH9K_RFKILL=
- ATH9K_CHANNEL_CONTEXT=
- ATH9K_PCOEM=
-+ATH9K_UBNTHSR=
- ATH9K_HTC=
- ATH9K_HTC_DEBUGFS=
- ATH9K_HWRNG=
---- a/drivers/net/wireless/ath/ath9k/Kconfig
-+++ b/drivers/net/wireless/ath/ath9k/Kconfig
-@@ -59,6 +59,19 @@ config ATH9K_AHB
- Say Y, if you have a SoC with a compatible built-in
- wireless MAC. Say N if unsure.
-
-+config ATH9K_UBNTHSR
-+ bool "Ubiquiti UniFi Outdoor Plus HSR support"
-+ depends on ATH9K
-+ ---help---
-+ This options enables code to control the HSR RF
-+ filter in the receive path of the Ubiquiti UniFi
-+ Outdoor Plus access point.
-+
-+ Say Y if you want to use the access point. The
-+ code will only be used if the device is detected,
-+ so it does not harm other setup other than occupying
-+ a bit of memory.
-+
- config ATH9K_DEBUGFS
- bool "Atheros ath9k debugging"
- depends on ATH9K && DEBUG_FS
+++ /dev/null
---- a/drivers/net/wireless/ath/ath9k/ahb.c
-+++ b/drivers/net/wireless/ath/ath9k/ahb.c
-@@ -19,7 +19,15 @@
- #include <linux/nl80211.h>
- #include <linux/platform_device.h>
- #include <linux/module.h>
-+#include <linux/of_device.h>
- #include "ath9k.h"
-+#include <linux/ath9k_platform.h>
-+
-+#ifdef CONFIG_OF
-+#include <asm/mach-ath79/ath79.h>
-+#include <asm/mach-ath79/ar71xx_regs.h>
-+#include <linux/mtd/mtd.h>
-+#endif
-
- static const struct platform_device_id ath9k_platform_id_table[] = {
- {
-@@ -68,6 +76,235 @@ static const struct ath_bus_ops ath_ahb_
- .eeprom_read = ath_ahb_eeprom_read,
- };
-
-+#ifdef CONFIG_OF
-+
-+#define QCA955X_DDR_CTL_CONFIG 0x108
-+#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23)
-+
-+static int of_get_wifi_cal(struct device_node *np, struct ath9k_platform_data *pdata)
-+{
-+#ifdef CONFIG_MTD
-+ struct device_node *mtd_np = NULL;
-+ size_t retlen;
-+ int size, ret;
-+ struct mtd_info *mtd;
-+ const char *part;
-+ const __be32 *list;
-+ phandle phandle;
-+
-+ list = of_get_property(np, "mtd-cal-data", &size);
-+ if (!list)
-+ return 0;
-+
-+ if (size != (2 * sizeof(*list)))
-+ return 1;
-+
-+ phandle = be32_to_cpup(list++);
-+ if (phandle)
-+ mtd_np = of_find_node_by_phandle(phandle);
-+
-+ if (!mtd_np)
-+ return 1;
-+
-+ part = of_get_property(mtd_np, "label", NULL);
-+ if (!part)
-+ part = mtd_np->name;
-+
-+ mtd = get_mtd_device_nm(part);
-+ if (IS_ERR(mtd))
-+ return 1;
-+
-+ ret = mtd_read(mtd, be32_to_cpup(list), sizeof(pdata->eeprom_data),
-+ &retlen, (u8*)pdata->eeprom_data);
-+ put_mtd_device(mtd);
-+
-+#endif
-+ return 0;
-+}
-+
-+static int ar913x_wmac_reset(void)
-+{
-+ ath79_device_reset_set(AR913X_RESET_AMBA2WMAC);
-+ mdelay(10);
-+
-+ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC);
-+ mdelay(10);
-+
-+ return 0;
-+}
-+
-+static int ar933x_wmac_reset(void)
-+{
-+ int retries = 20;
-+
-+ ath79_device_reset_set(AR933X_RESET_WMAC);
-+ ath79_device_reset_clear(AR933X_RESET_WMAC);
-+
-+ while (1) {
-+ u32 bootstrap;
-+
-+ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
-+ if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0)
-+ return 0;
-+
-+ if (retries-- == 0)
-+ break;
-+
-+ udelay(10000);
-+ }
-+
-+ pr_err("ar933x: WMAC reset timed out");
-+ return -ETIMEDOUT;
-+}
-+
-+static int qca955x_wmac_reset(void)
-+{
-+ int i;
-+
-+ /* Try to wait for WMAC DDR activity to stop */
-+ for (i = 0; i < 10; i++) {
-+ if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) &
-+ QCA955X_DDR_CTL_CONFIG_ACT_WMAC))
-+ break;
-+
-+ udelay(10);
-+ }
-+
-+ ath79_device_reset_set(QCA955X_RESET_RTC);
-+ udelay(10);
-+ ath79_device_reset_clear(QCA955X_RESET_RTC);
-+ udelay(10);
-+
-+ return 0;
-+}
-+
-+enum {
-+ AR913X_WMAC = 0,
-+ AR933X_WMAC,
-+ AR934X_WMAC,
-+ QCA953X_WMAC,
-+ QCA955X_WMAC,
-+ QCA956X_WMAC,
-+};
-+
-+static int ar9330_get_soc_revision(void)
-+{
-+ if (ath79_soc_rev == 1)
-+ return ath79_soc_rev;
-+
-+ return 0;
-+}
-+
-+static int ath79_get_soc_revision(void)
-+{
-+ return ath79_soc_rev;
-+}
-+
-+static const struct of_ath_ahb_data {
-+ u16 dev_id;
-+ u32 bootstrap_reg;
-+ u32 bootstrap_ref;
-+
-+ int (*soc_revision)(void);
-+ int (*wmac_reset)(void);
-+} of_ath_ahb_data[] = {
-+ [AR913X_WMAC] = {
-+ .dev_id = AR5416_AR9100_DEVID,
-+ .wmac_reset = ar913x_wmac_reset,
-+
-+ },
-+ [AR933X_WMAC] = {
-+ .dev_id = AR9300_DEVID_AR9330,
-+ .bootstrap_reg = AR933X_RESET_REG_BOOTSTRAP,
-+ .bootstrap_ref = AR933X_BOOTSTRAP_REF_CLK_40,
-+ .soc_revision = ar9330_get_soc_revision,
-+ .wmac_reset = ar933x_wmac_reset,
-+ },
-+ [AR934X_WMAC] = {
-+ .dev_id = AR9300_DEVID_AR9340,
-+ .bootstrap_reg = AR934X_RESET_REG_BOOTSTRAP,
-+ .bootstrap_ref = AR934X_BOOTSTRAP_REF_CLK_40,
-+ .soc_revision = ath79_get_soc_revision,
-+ },
-+ [QCA953X_WMAC] = {
-+ .dev_id = AR9300_DEVID_AR953X,
-+ .bootstrap_reg = QCA953X_RESET_REG_BOOTSTRAP,
-+ .bootstrap_ref = QCA953X_BOOTSTRAP_REF_CLK_40,
-+ .soc_revision = ath79_get_soc_revision,
-+ },
-+ [QCA955X_WMAC] = {
-+ .dev_id = AR9300_DEVID_QCA955X,
-+ .bootstrap_reg = QCA955X_RESET_REG_BOOTSTRAP,
-+ .bootstrap_ref = QCA955X_BOOTSTRAP_REF_CLK_40,
-+ .wmac_reset = qca955x_wmac_reset,
-+ },
-+ [QCA956X_WMAC] = {
-+ .dev_id = AR9300_DEVID_QCA956X,
-+ .bootstrap_reg = QCA956X_RESET_REG_BOOTSTRAP,
-+ .bootstrap_ref = QCA956X_BOOTSTRAP_REF_CLK_40,
-+ .soc_revision = ath79_get_soc_revision,
-+ },
-+};
-+
-+const struct of_device_id of_ath_ahb_match[] = {
-+ { .compatible = "qca,ar9130-wmac", .data = &of_ath_ahb_data[AR913X_WMAC] },
-+ { .compatible = "qca,ar9330-wmac", .data = &of_ath_ahb_data[AR933X_WMAC] },
-+ { .compatible = "qca,ar9340-wmac", .data = &of_ath_ahb_data[AR934X_WMAC] },
-+ { .compatible = "qca,qca9530-wmac", .data = &of_ath_ahb_data[QCA953X_WMAC] },
-+ { .compatible = "qca,qca9550-wmac", .data = &of_ath_ahb_data[QCA955X_WMAC] },
-+ { .compatible = "qca,qca9560-wmac", .data = &of_ath_ahb_data[QCA956X_WMAC] },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, of_ath_ahb_match);
-+
-+static int of_ath_ahb_probe(struct platform_device *pdev)
-+{
-+ struct ath9k_platform_data *pdata;
-+ const struct of_device_id *match;
-+ const struct of_ath_ahb_data *data;
-+ u8 led_pin;
-+
-+ match = of_match_device(of_ath_ahb_match, &pdev->dev);
-+ data = (const struct of_ath_ahb_data *)match->data;
-+
-+ pdata = dev_get_platdata(&pdev->dev);
-+
-+ if (!of_property_read_u8(pdev->dev.of_node, "qca,led-pin", &led_pin))
-+ pdata->led_pin = led_pin;
-+ else
-+ pdata->led_pin = -1;
-+
-+ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-2ghz"))
-+ pdata->disable_2ghz = true;
-+
-+ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-5ghz"))
-+ pdata->disable_5ghz = true;
-+
-+ if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo"))
-+ pdata->tx_gain_buffalo = true;
-+
-+ if (data->wmac_reset) {
-+ data->wmac_reset();
-+ pdata->external_reset = data->wmac_reset;
-+ }
-+
-+ if (data->bootstrap_reg && data->bootstrap_ref) {
-+ u32 t = ath79_reset_rr(data->bootstrap_reg);
-+ if (t & data->bootstrap_ref)
-+ pdata->is_clk_25mhz = false;
-+ else
-+ pdata->is_clk_25mhz = true;
-+ }
-+
-+ pdata->get_mac_revision = data->soc_revision;
-+
-+ if (of_get_wifi_cal(pdev->dev.of_node, pdata))
-+ dev_err(&pdev->dev, "failed to load calibration data from mtd device\n");
-+
-+ return data->dev_id;
-+}
-+#endif
-+
- static int ath_ahb_probe(struct platform_device *pdev)
- {
- void __iomem *mem;
-@@ -79,6 +316,17 @@ static int ath_ahb_probe(struct platform
- int ret = 0;
- struct ath_hw *ah;
- char hw_name[64];
-+ u16 dev_id;
-+
-+ if (id)
-+ dev_id = id->driver_data;
-+
-+#ifdef CONFIG_OF
-+ if (pdev->dev.of_node)
-+ pdev->dev.platform_data = devm_kzalloc(&pdev->dev,
-+ sizeof(struct ath9k_platform_data),
-+ GFP_KERNEL);
-+#endif
-
- if (!dev_get_platdata(&pdev->dev)) {
- dev_err(&pdev->dev, "no platform data specified\n");
-@@ -121,13 +369,16 @@ static int ath_ahb_probe(struct platform
- sc->mem = mem;
- sc->irq = irq;
-
-+#ifdef CONFIG_OF
-+ dev_id = of_ath_ahb_probe(pdev);
-+#endif
- ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
- if (ret) {
- dev_err(&pdev->dev, "request_irq failed\n");
- goto err_free_hw;
- }
-
-- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
-+ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops);
- if (ret) {
- dev_err(&pdev->dev, "failed to initialize device\n");
- goto err_irq;
-@@ -158,6 +409,9 @@ static int ath_ahb_remove(struct platfor
- free_irq(sc->irq, sc);
- ieee80211_free_hw(sc->hw);
- }
-+#ifdef CONFIG_OF
-+ pdev->dev.platform_data = NULL;
-+#endif
-
- return 0;
- }
-@@ -167,6 +421,9 @@ static struct platform_driver ath_ahb_dr
- .remove = ath_ahb_remove,
- .driver = {
- .name = "ath9k",
-+#ifdef CONFIG_OF
-+ .of_match_table = of_ath_ahb_match,
-+#endif
- },
- .id_table = ath9k_platform_id_table,
- };
---- a/drivers/net/wireless/ath/ath9k/ath9k.h
-+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
-@@ -25,6 +25,7 @@
- #include <linux/time.h>
- #include <linux/hw_random.h>
- #include <linux/gpio/driver.h>
-+#include <linux/reset.h>
-
- #include "common.h"
- #include "debug.h"
-@@ -1023,6 +1024,9 @@ struct ath_softc {
- struct ath_hw *sc_ah;
- void __iomem *mem;
- int irq;
-+#ifdef CONFIG_OF
-+ struct reset_control *reset;
-+#endif
- spinlock_t sc_serial_rw;
- spinlock_t sc_pm_lock;
- spinlock_t sc_pcu_lock;
+++ /dev/null
-From 91094ed065f7794886b4a5490fd6de942f036bb4 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:26 +0100
-Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/Kconfig | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/Kconfig
-+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
-@@ -210,7 +210,7 @@ endif
- config RT2800SOC
- tristate "Ralink WiSoC support"
- depends on m
-- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
-+ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
- select RT2X00_LIB_SOC
- select RT2X00_LIB_MMIO
- select RT2X00_LIB_CRYPTO
-@@ -245,7 +245,7 @@ config RT2X00_LIB_PCI
-
- config RT2X00_LIB_SOC
- tristate "RT2x00 SoC support"
-- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
-+ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
- depends on m
- select RT2X00_LIB
-
+++ /dev/null
-From 4f16582c93a71eba9d389e0f0a8aa9099a9587cd Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:26 +0100
-Subject: [PATCH] rt2x00: rt2800lib: enable support for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -9403,6 +9403,7 @@ static int rt2800_probe_rt(struct rt2x00
- case RT3390:
- case RT3572:
- case RT3593:
-+ case RT3883:
- case RT5350:
- case RT5390:
- case RT5392:
+++ /dev/null
-From ecb394ccf248d8652c463133c4f404458a57a9c1 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:26 +0100
-Subject: [PATCH] rt2x00: rt2800lib: add rf_vals for RF3853
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800.h | 4 +-
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 65 +++++++++++++++++++++++++++++++
- 2 files changed, 68 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
-@@ -48,7 +48,8 @@
- * RF2853 2.4G/5G 3T3R
- * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390)
- * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392)
-- * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
-+ * RF3053 2.4G/5G 3T3R(RT3563/RT3573/RT3593)
-+ * RF3853 2.4G/5G 3T3R(RT3883/RT3662)
- * RF5592 2.4G/5G 2T2R
- * RF3070 2.4G 1T1R
- * RF5360 2.4G 1T1R
-@@ -72,6 +73,7 @@
- #define RF5592 0x000f
- #define RF3070 0x3070
- #define RF3290 0x3290
-+#define RF3853 0x3853
- #define RF5350 0x5350
- #define RF5360 0x5360
- #define RF5362 0x5362
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -8981,6 +8981,66 @@ static const struct rf_channel rf_vals_3
- {14, 0xF0, 2, 0x18},
- };
-
-+static const struct rf_channel rf_vals_3853[] = {
-+ {1, 241, 6, 2},
-+ {2, 241, 6, 7},
-+ {3, 242, 6, 2},
-+ {4, 242, 6, 7},
-+ {5, 243, 6, 2},
-+ {6, 243, 6, 7},
-+ {7, 244, 6, 2},
-+ {8, 244, 6, 7},
-+ {9, 245, 6, 2},
-+ {10, 245, 6, 7},
-+ {11, 246, 6, 2},
-+ {12, 246, 6, 7},
-+ {13, 247, 6, 2},
-+ {14, 248, 6, 4},
-+
-+ {36, 0x56, 8, 4},
-+ {38, 0x56, 8, 6},
-+ {40, 0x56, 8, 8},
-+ {44, 0x57, 8, 0},
-+ {46, 0x57, 8, 2},
-+ {48, 0x57, 8, 4},
-+ {52, 0x57, 8, 8},
-+ {54, 0x57, 8, 10},
-+ {56, 0x58, 8, 0},
-+ {60, 0x58, 8, 4},
-+ {62, 0x58, 8, 6},
-+ {64, 0x58, 8, 8},
-+
-+ {100, 0x5b, 8, 8},
-+ {102, 0x5b, 8, 10},
-+ {104, 0x5c, 8, 0},
-+ {108, 0x5c, 8, 4},
-+ {110, 0x5c, 8, 6},
-+ {112, 0x5c, 8, 8},
-+ {114, 0x5c, 8, 10},
-+ {116, 0x5d, 8, 0},
-+ {118, 0x5d, 8, 2},
-+ {120, 0x5d, 8, 4},
-+ {124, 0x5d, 8, 8},
-+ {126, 0x5d, 8, 10},
-+ {128, 0x5e, 8, 0},
-+ {132, 0x5e, 8, 4},
-+ {134, 0x5e, 8, 6},
-+ {136, 0x5e, 8, 8},
-+ {140, 0x5f, 8, 0},
-+
-+ {149, 0x5f, 8, 9},
-+ {151, 0x5f, 8, 11},
-+ {153, 0x60, 8, 1},
-+ {157, 0x60, 8, 5},
-+ {159, 0x60, 8, 7},
-+ {161, 0x60, 8, 9},
-+ {165, 0x61, 8, 1},
-+ {167, 0x61, 8, 3},
-+ {169, 0x61, 8, 5},
-+ {171, 0x61, 8, 7},
-+ {173, 0x61, 8, 9},
-+};
-+
- static const struct rf_channel rf_vals_5592_xtal20[] = {
- /* Channel, N, K, mod, R */
- {1, 482, 4, 10, 3},
-@@ -9244,6 +9304,11 @@ static int rt2800_probe_hw_mode(struct r
- spec->channels = rf_vals_3x;
- break;
-
-+ case RF3853:
-+ spec->num_channels = ARRAY_SIZE(rf_vals_3853);
-+ spec->channels = rf_vals_3853;
-+ break;
-+
- case RF5592:
- reg = rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX);
- if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
+++ /dev/null
-From f8e3fcf18e1f2d7f9e6a9680c5452da090f33d88 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Thu, 1 Aug 2013 14:40:44 +0200
-Subject: [PATCH] rt2x00: rt2800lib: enable VCO calibration for RF3853
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -4881,6 +4881,7 @@ void rt2800_vco_calibration(struct rt2x0
- case RF3053:
- case RF3070:
- case RF3290:
-+ case RF3853:
- case RF5350:
- case RF5360:
- case RF5362:
-@@ -9426,6 +9427,7 @@ static int rt2800_probe_hw_mode(struct r
- case RF3053:
- case RF3070:
- case RF3290:
-+ case RF3853:
- case RF5350:
- case RF5360:
- case RF5362:
+++ /dev/null
-From 6e3a17190815c6aa4dc53c2cfe9125fb1154f187 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:27 +0100
-Subject: [PATCH] rt2x00: rt2800lib: add channel configuration function for
- RF3853
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 208 +++++++++++++++++++++++++++++++
- 1 file changed, 208 insertions(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -2713,6 +2713,211 @@ static void rt2800_config_channel_rf3053
- }
- }
-
-+static void rt2800_config_channel_rf3853(struct rt2x00_dev *rt2x00dev,
-+ struct ieee80211_conf *conf,
-+ struct rf_channel *rf,
-+ struct channel_info *info)
-+{
-+ u8 rfcsr;
-+ u8 bbp;
-+ u8 pwr1, pwr2, pwr3;
-+
-+ const bool txbf_enabled = false; /* TODO */
-+
-+ /* TODO: add band selection */
-+
-+ if (rf->channel <= 14)
-+ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
-+ else if (rf->channel < 132)
-+ rt2800_rfcsr_write(rt2x00dev, 6, 0x80);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
-+
-+ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
-+ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
-+
-+ if (rf->channel <= 14)
-+ rt2800_rfcsr_write(rt2x00dev, 11, 0x46);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
-+
-+ if (rf->channel <= 14)
-+ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 12, 0x52);
-+
-+ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
-+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
-+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
-+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
-+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
-+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
-+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
-+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
-+ rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
-+
-+ switch (rt2x00dev->default_ant.tx_chain_num) {
-+ case 3:
-+ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
-+ /* fallthrough */
-+ case 2:
-+ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
-+ /* fallthrough */
-+ case 1:
-+ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
-+ break;
-+ }
-+
-+ switch (rt2x00dev->default_ant.rx_chain_num) {
-+ case 3:
-+ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
-+ /* fallthrough */
-+ case 2:
-+ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
-+ /* fallthrough */
-+ case 1:
-+ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
-+ break;
-+ }
-+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-+
-+ rt2800_freq_cal_mode1(rt2x00dev);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
-+ if (!conf_is_ht40(conf))
-+ rfcsr &= ~(0x06);
-+ else
-+ rfcsr |= 0x06;
-+ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-+
-+ if (rf->channel <= 14)
-+ rt2800_rfcsr_write(rt2x00dev, 31, 0xa0);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
-+
-+ if (conf_is_ht40(conf))
-+ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
-+
-+ if (rf->channel <= 14)
-+ rt2800_rfcsr_write(rt2x00dev, 34, 0x3c);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
-+
-+ /* loopback RF_BS */
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 36);
-+ if (rf->channel <= 14)
-+ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
-+ else
-+ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
-+ rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
-+
-+ if (rf->channel <= 14)
-+ rfcsr = 0x23;
-+ else if (rf->channel < 100)
-+ rfcsr = 0x36;
-+ else if (rf->channel < 132)
-+ rfcsr = 0x32;
-+ else
-+ rfcsr = 0x30;
-+
-+ if (txbf_enabled)
-+ rfcsr |= 0x40;
-+
-+ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
-+
-+ if (rf->channel <= 14)
-+ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
-+
-+ if (rf->channel <= 14)
-+ rfcsr = 0xbb;
-+ else if (rf->channel < 100)
-+ rfcsr = 0xeb;
-+ else if (rf->channel < 132)
-+ rfcsr = 0xb3;
-+ else
-+ rfcsr = 0x9b;
-+ rt2800_rfcsr_write(rt2x00dev, 45, rfcsr);
-+
-+ if (rf->channel <= 14)
-+ rfcsr = 0x8e;
-+ else
-+ rfcsr = 0x8a;
-+
-+ if (txbf_enabled)
-+ rfcsr |= 0x20;
-+
-+ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
-+
-+ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 51);
-+ if (rf->channel <= 14)
-+ rt2800_rfcsr_write(rt2x00dev, 51, 0x75);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 52);
-+ if (rf->channel <= 14)
-+ rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
-+
-+ if (rf->channel <= 14) {
-+ pwr1 = info->default_power1 & 0x1f;
-+ pwr2 = info->default_power2 & 0x1f;
-+ pwr3 = info->default_power3 & 0x1f;
-+ } else {
-+ pwr1 = 0x48 | ((info->default_power1 & 0x18) << 1) |
-+ (info->default_power1 & 0x7);
-+ pwr2 = 0x48 | ((info->default_power2 & 0x18) << 1) |
-+ (info->default_power2 & 0x7);
-+ pwr3 = 0x48 | ((info->default_power3 & 0x18) << 1) |
-+ (info->default_power3 & 0x7);
-+ }
-+
-+ rt2800_rfcsr_write(rt2x00dev, 53, pwr1);
-+ rt2800_rfcsr_write(rt2x00dev, 54, pwr2);
-+ rt2800_rfcsr_write(rt2x00dev, 55, pwr3);
-+
-+ rt2x00_dbg(rt2x00dev, "Channel:%d, pwr1:%02x, pwr2:%02x, pwr3:%02x\n",
-+ rf->channel, pwr1, pwr2, pwr3);
-+
-+ bbp = (info->default_power1 >> 5) |
-+ ((info->default_power2 & 0xe0) >> 1);
-+ rt2800_bbp_write(rt2x00dev, 109, bbp);
-+
-+ bbp = rt2800_bbp_read(rt2x00dev, 110);
-+ bbp &= 0x0f;
-+ bbp |= (info->default_power3 & 0xe0) >> 1;
-+ rt2800_bbp_write(rt2x00dev, 110, bbp);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 57);
-+ if (rf->channel <= 14)
-+ rt2800_rfcsr_write(rt2x00dev, 57, 0x6e);
-+ else
-+ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
-+
-+ /* Enable RF tuning */
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
-+ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
-+ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
-+
-+ udelay(2000);
-+
-+ bbp = rt2800_bbp_read(rt2x00dev, 49);
-+ /* clear update flag */
-+ rt2800_bbp_write(rt2x00dev, 49, bbp & 0xfe);
-+ rt2800_bbp_write(rt2x00dev, 49, bbp);
-+
-+ /* TODO: add calibration for TxBF */
-+}
-+
- #define POWER_BOUND 0x27
- #define POWER_BOUND_5G 0x2b
-
-@@ -3570,6 +3775,9 @@ static void rt2800_config_channel(struct
- case RF3322:
- rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
- break;
-+ case RF3853:
-+ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
-+ break;
- case RF3070:
- case RF5350:
- case RF5360:
+++ /dev/null
-From afd38ae82226551bf879b6c7c4b620c271fee9d2 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Thu, 1 Aug 2013 14:42:05 +0200
-Subject: [PATCH] rt2x00: rt2800lib: enable RF3853 support
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -8906,6 +8906,7 @@ static int rt2800_init_eeprom(struct rt2
- case RF3290:
- case RF3320:
- case RF3322:
-+ case RF3853:
- case RF5350:
- case RF5360:
- case RF5362:
+++ /dev/null
-From 0094872a5e8e4664c6ea1b2dfa487063d39ae363 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:26 +0100
-Subject: [PATCH] rt2x00: rt2800lib: add MAC register initialization for
- RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800.h | 14 ++++++++++++++
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 19 ++++++++++++++++---
- 2 files changed, 30 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
-@@ -1727,6 +1727,20 @@
- #define TX_PWR_CFG_9B_STBC_MCS7 FIELD32(0x000000ff)
-
- /*
-+ * TX_TXBF_CFG:
-+ */
-+#define TX_TXBF_CFG_0 0x138c
-+#define TX_TXBF_CFG_1 0x13a4
-+#define TX_TXBF_CFG_2 0x13a8
-+#define TX_TXBF_CFG_3 0x13ac
-+
-+/*
-+ * TX_FBK_CFG_3S:
-+ */
-+#define TX_FBK_CFG_3S_0 0x13c4
-+#define TX_FBK_CFG_3S_1 0x13c8
-+
-+/*
- * RX_FILTER_CFG: RX configuration register.
- */
- #define RX_FILTER_CFG 0x1400
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -5509,6 +5509,12 @@ static int rt2800_init_registers(struct
- rt2800_register_write(rt2x00dev, TX_SW_CFG2,
- 0x00000000);
- }
-+ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
-+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
-+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
-+ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000);
-+ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
-+ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
- } else if (rt2x00_rt(rt2x00dev, RT5390) ||
- rt2x00_rt(rt2x00dev, RT5392) ||
- rt2x00_rt(rt2x00dev, RT6352)) {
-@@ -5722,6 +5728,11 @@ static int rt2800_init_registers(struct
- reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
- rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
-
-+ if (rt2x00_rt(rt2x00dev, RT3883)) {
-+ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
-+ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
-+ }
-+
- reg = rt2800_register_read(rt2x00dev, TX_RTS_CFG);
- rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 7);
- rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES,
+++ /dev/null
-From 6c2d32478159fffff0b85abb6817a21bb2338231 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:27 +0100
-Subject: [PATCH] rt2x00: rt2800soc: fix rt2800soc_disable_radio for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800soc.c | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-@@ -51,9 +51,16 @@ static bool rt2800soc_hwcrypt_disabled(s
-
- static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
- {
-+ u32 reg;
-+
- rt2800_disable_radio(rt2x00dev);
- rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-- rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
-+
-+ reg = 0;
-+ if (rt2x00_rt(rt2x00dev, RT3883))
-+ rt2x00_set_field32(®, TX_PIN_CFG_RFTR_EN, 1);
-+
-+ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, reg);
- }
-
- static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
+++ /dev/null
-From 84833056aa7dd25f5b097e31c78f2a0914c5160c Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:26 +0100
-Subject: [PATCH] rt2x00: rt2800lib: add BBP register initialization for
- RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++
- 1 file changed, 44 insertions(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -6349,6 +6349,47 @@ static void rt2800_init_bbp_3593(struct
- rt2800_bbp_write(rt2x00dev, 103, 0xc0);
- }
-
-+static void rt2800_init_bbp_3883(struct rt2x00_dev *rt2x00dev)
-+{
-+ rt2800_init_bbp_early(rt2x00dev);
-+
-+ rt2800_bbp_write(rt2x00dev, 4, 0x50);
-+ rt2800_bbp_write(rt2x00dev, 47, 0x48);
-+
-+ rt2800_bbp_write(rt2x00dev, 86, 0x46);
-+ rt2800_bbp_write(rt2x00dev, 88, 0x90);
-+
-+ rt2800_bbp_write(rt2x00dev, 92, 0x02);
-+
-+ rt2800_bbp_write(rt2x00dev, 103, 0xc0);
-+ rt2800_bbp_write(rt2x00dev, 104, 0x92);
-+ rt2800_bbp_write(rt2x00dev, 105, 0x34);
-+ rt2800_bbp_write(rt2x00dev, 106, 0x12);
-+ rt2800_bbp_write(rt2x00dev, 120, 0x50);
-+ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
-+ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
-+
-+ /* Set ITxBF timeout to 0x9C40=1000msec */
-+ rt2800_bbp_write(rt2x00dev, 179, 0x02);
-+ rt2800_bbp_write(rt2x00dev, 180, 0x00);
-+ rt2800_bbp_write(rt2x00dev, 182, 0x40);
-+ rt2800_bbp_write(rt2x00dev, 180, 0x01);
-+ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
-+
-+ rt2800_bbp_write(rt2x00dev, 179, 0x00);
-+
-+ /* Reprogram the inband interface to put right values in RXWI */
-+ rt2800_bbp_write(rt2x00dev, 142, 0x04);
-+ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
-+ rt2800_bbp_write(rt2x00dev, 142, 0x06);
-+ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
-+ rt2800_bbp_write(rt2x00dev, 142, 0x07);
-+ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
-+ rt2800_bbp_write(rt2x00dev, 142, 0x08);
-+ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
-+ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
-+}
-+
- static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
- {
- int ant, div_mode;
-@@ -6792,6 +6833,9 @@ static void rt2800_init_bbp(struct rt2x0
- case RT3593:
- rt2800_init_bbp_3593(rt2x00dev);
- return;
-+ case RT3883:
-+ rt2800_init_bbp_3883(rt2x00dev);
-+ return;
- case RT5390:
- case RT5392:
- rt2800_init_bbp_53xx(rt2x00dev);
+++ /dev/null
-From 99c659cf345640fd0f733cbcaf4583cc2c868ec0 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Mon, 29 Apr 2013 13:21:48 +0200
-Subject: [PATCH] rt2x00: rt2800lib: add RFCSR initialization for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800.h | 1 +
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 141 +++++++++++++++++++++++++++++++
- 2 files changed, 142 insertions(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
-@@ -2311,6 +2311,7 @@ struct mac_iveiv_entry {
- /*
- * RFCSR 2:
- */
-+#define RFCSR2_RESCAL_BP FIELD8(0x40)
- #define RFCSR2_RESCAL_EN FIELD8(0x80)
- #define RFCSR2_RX2_EN_MT7620 FIELD8(0x02)
- #define RFCSR2_TX2_EN_MT7620 FIELD8(0x20)
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -7707,6 +7707,144 @@ static void rt2800_init_rfcsr_5350(struc
- rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
- }
-
-+static void rt2800_init_rfcsr_3883(struct rt2x00_dev *rt2x00dev)
-+{
-+ u8 rfcsr;
-+
-+ /* TODO: get the actual ECO value from the SoC */
-+ const unsigned int eco = 5;
-+
-+ rt2800_rf_init_calibration(rt2x00dev, 2);
-+
-+ rt2800_rfcsr_write(rt2x00dev, 0, 0xe0);
-+ rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
-+ rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
-+ rt2800_rfcsr_write(rt2x00dev, 3, 0x20);
-+ rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
-+ rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 8, 0x5b);
-+ rt2800_rfcsr_write(rt2x00dev, 9, 0x08);
-+ rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
-+ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
-+ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
-+ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
-+ rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
-+
-+ /* RFCSR 17 will be initialized later based on the
-+ * frequency offset stored in the EEPROM
-+ */
-+
-+ rt2800_rfcsr_write(rt2x00dev, 18, 0x40);
-+ rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
-+ rt2800_rfcsr_write(rt2x00dev, 23, 0xc0);
-+ rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 25, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 29, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
-+ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
-+ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
-+ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
-+ rt2800_rfcsr_write(rt2x00dev, 35, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 37, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 38, 0x86);
-+ rt2800_rfcsr_write(rt2x00dev, 39, 0x23);
-+ rt2800_rfcsr_write(rt2x00dev, 40, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 41, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 42, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
-+ rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
-+ rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
-+ rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 48, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 49, 0x8e);
-+ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
-+ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
-+ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
-+ rt2800_rfcsr_write(rt2x00dev, 53, 0x76);
-+ rt2800_rfcsr_write(rt2x00dev, 54, 0x76);
-+ rt2800_rfcsr_write(rt2x00dev, 55, 0x76);
-+ rt2800_rfcsr_write(rt2x00dev, 56, 0xdb);
-+ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
-+ rt2800_rfcsr_write(rt2x00dev, 58, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
-+ rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
-+
-+ /* TODO: rx filter calibration? */
-+
-+ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
-+
-+ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
-+
-+ rt2800_bbp_write(rt2x00dev, 105, 0x05);
-+
-+ rt2800_bbp_write(rt2x00dev, 179, 0x02);
-+ rt2800_bbp_write(rt2x00dev, 180, 0x00);
-+ rt2800_bbp_write(rt2x00dev, 182, 0x40);
-+ rt2800_bbp_write(rt2x00dev, 180, 0x01);
-+ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
-+
-+ rt2800_bbp_write(rt2x00dev, 179, 0x00);
-+
-+ rt2800_bbp_write(rt2x00dev, 142, 0x04);
-+ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
-+ rt2800_bbp_write(rt2x00dev, 142, 0x06);
-+ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
-+ rt2800_bbp_write(rt2x00dev, 142, 0x07);
-+ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
-+ rt2800_bbp_write(rt2x00dev, 142, 0x08);
-+ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
-+ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
-+
-+ if (eco == 5) {
-+ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
-+ rt2800_rfcsr_write(rt2x00dev, 33, 0x32);
-+ }
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 2);
-+ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_BP, 0);
-+ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
-+ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
-+ msleep(1);
-+ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0);
-+ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
-+ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
-+ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
-+ rfcsr |= 0xc0;
-+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 22);
-+ rfcsr |= 0x20;
-+ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 46);
-+ rfcsr |= 0x20;
-+ rt2800_rfcsr_write(rt2x00dev, 46, rfcsr);
-+
-+ rfcsr = rt2800_rfcsr_read(rt2x00dev, 20);
-+ rfcsr &= ~0xee;
-+ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
-+}
-+
- static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
- {
- rt2800_rf_init_calibration(rt2x00dev, 2);
-@@ -8549,6 +8687,9 @@ static void rt2800_init_rfcsr(struct rt2
- case RT3390:
- rt2800_init_rfcsr_3390(rt2x00dev);
- break;
-+ case RT3883:
-+ rt2800_init_rfcsr_3883(rt2x00dev);
-+ break;
- case RT3572:
- rt2800_init_rfcsr_3572(rt2x00dev);
- break;
+++ /dev/null
-From 86022438ffeb1b87dfcd018bf477fdbb43076691 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Wed, 8 May 2013 19:35:33 +0200
-Subject: [PATCH] rt2x00: rt2800lib: use the extended EEPROM map for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -381,7 +381,8 @@ static unsigned int rt2800_eeprom_word_i
- wiphy_name(rt2x00dev->hw->wiphy), word))
- return 0;
-
-- if (rt2x00_rt(rt2x00dev, RT3593))
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- map = rt2800_eeprom_map_ext;
- else
- map = rt2800_eeprom_map;
+++ /dev/null
-From 4cf5403f02fa65dc2207f61d223cffa9ae50e907 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Thu, 1 Aug 2013 14:48:21 +0200
-Subject: [PATCH] rt2x00: rt2800lib: force rf type to RF3853 on RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -9083,6 +9083,8 @@ static int rt2800_init_eeprom(struct rt2
- rf = rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID);
- else if (rt2x00_rt(rt2x00dev, RT3352))
- rf = RF3322;
-+ else if (rt2x00_rt(rt2x00dev, RT3883))
-+ rf = RF3853;
- else if (rt2x00_rt(rt2x00dev, RT5350))
- rf = RF5350;
- else
+++ /dev/null
-From 269f19c848a2380db03a3f207cafb88e28d71c53 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:28 +0100
-Subject: [PATCH] rt2x00: rt2800lib: add channel configuration code for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 72 +++++++++++++++++++++++++++++--
- 1 file changed, 69 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -3738,6 +3738,36 @@ static char rt2800_txpower_to_dev(struct
- return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
- }
-
-+static void rt3883_bbp_adjust(struct rt2x00_dev *rt2x00dev,
-+ struct rf_channel *rf)
-+{
-+ u8 bbp;
-+
-+ bbp = (rf->channel > 14) ? 0x48 : 0x38;
-+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp);
-+
-+ rt2800_bbp_write(rt2x00dev, 69, 0x12);
-+
-+ if (rf->channel <= 14) {
-+ rt2800_bbp_write(rt2x00dev, 70, 0x0a);
-+ } else {
-+ /* Disable CCK packet detection */
-+ rt2800_bbp_write(rt2x00dev, 70, 0x00);
-+ }
-+
-+ rt2800_bbp_write(rt2x00dev, 73, 0x10);
-+
-+ if (rf->channel > 14) {
-+ rt2800_bbp_write(rt2x00dev, 62, 0x1d);
-+ rt2800_bbp_write(rt2x00dev, 63, 0x1d);
-+ rt2800_bbp_write(rt2x00dev, 64, 0x1d);
-+ } else {
-+ rt2800_bbp_write(rt2x00dev, 62, 0x2d);
-+ rt2800_bbp_write(rt2x00dev, 63, 0x2d);
-+ rt2800_bbp_write(rt2x00dev, 64, 0x2d);
-+ }
-+}
-+
- static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf,
- struct rf_channel *rf,
-@@ -3756,6 +3786,12 @@ static void rt2800_config_channel(struct
- rt2800_txpower_to_dev(rt2x00dev, rf->channel,
- info->default_power3);
-
-+ switch (rt2x00dev->chip.rt) {
-+ case RT3883:
-+ rt3883_bbp_adjust(rt2x00dev, rf);
-+ break;
-+ }
-+
- switch (rt2x00dev->chip.rf) {
- case RF2020:
- case RF3020:
-@@ -3860,6 +3896,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);
-+ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
-+ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
-+ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
-+ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
-+
-+ if (rt2x00dev->default_ant.rx_chain_num > 1)
-+ rt2800_bbp_write(rt2x00dev, 86, 0x46);
-+ else
-+ rt2800_bbp_write(rt2x00dev, 86, 0);
- } else {
- rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
- rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
-@@ -3873,6 +3918,7 @@ static void rt2800_config_channel(struct
- !rt2x00_rt(rt2x00dev, RT6352)) {
- if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
- rt2800_bbp_write(rt2x00dev, 82, 0x62);
-+ rt2800_bbp_write(rt2x00dev, 82, 0x62);
- rt2800_bbp_write(rt2x00dev, 75, 0x46);
- } else {
- if (rt2x00_rt(rt2x00dev, RT3593))
-@@ -3881,19 +3927,22 @@ static void rt2800_config_channel(struct
- rt2800_bbp_write(rt2x00dev, 82, 0x84);
- rt2800_bbp_write(rt2x00dev, 75, 0x50);
- }
-- if (rt2x00_rt(rt2x00dev, RT3593))
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- rt2800_bbp_write(rt2x00dev, 83, 0x8a);
- }
-
- } else {
- if (rt2x00_rt(rt2x00dev, RT3572))
- rt2800_bbp_write(rt2x00dev, 82, 0x94);
-- else if (rt2x00_rt(rt2x00dev, RT3593))
-+ else if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- rt2800_bbp_write(rt2x00dev, 82, 0x82);
- else if (!rt2x00_rt(rt2x00dev, RT6352))
- rt2800_bbp_write(rt2x00dev, 82, 0xf2);
-
-- if (rt2x00_rt(rt2x00dev, RT3593))
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- rt2800_bbp_write(rt2x00dev, 83, 0x9a);
-
- if (rt2x00_has_cap_external_lna_a(rt2x00dev))
-@@ -4019,6 +4068,23 @@ static void rt2800_config_channel(struct
-
- rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
-
-+ usleep_range(1000, 1500);
-+ }
-+
-+ if (rt2x00_rt(rt2x00dev, RT3883)) {
-+ if (!conf_is_ht40(conf))
-+ rt2800_bbp_write(rt2x00dev, 105, 0x34);
-+ else
-+ rt2800_bbp_write(rt2x00dev, 105, 0x04);
-+
-+ /* AGC init */
-+ if (rf->channel <= 14)
-+ reg = 0x2e + rt2x00dev->lna_gain;
-+ else
-+ reg = 0x20 + ((rt2x00dev->lna_gain * 5) / 3);
-+
-+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
-+
- usleep_range(1000, 1500);
- }
-
+++ /dev/null
-From e37d93abaabe3ab72b0332a18092acc162307274 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Mon, 30 Sep 2013 13:57:26 +0200
-Subject: [PATCH] rt2x00: rt2800lib: fix txpower_to_dev function for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -3725,13 +3725,15 @@ static char rt2800_txpower_to_dev(struct
- unsigned int channel,
- char txpower)
- {
-- if (rt2x00_rt(rt2x00dev, RT3593))
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC);
-
- if (channel <= 14)
- return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER);
-
-- if (rt2x00_rt(rt2x00dev, RT3593))
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- return clamp_t(char, txpower, MIN_A_TXPOWER_3593,
- MAX_A_TXPOWER_3593);
- else
+++ /dev/null
-From c4d79e344bd580d85821390d49f92dced7d8e125 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:29 +0100
-Subject: [PATCH] rt2x00: rt2800lib: use correct txpower calculation function
- for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -5111,7 +5111,8 @@ static void rt2800_config_txpower(struct
- struct ieee80211_channel *chan,
- int power_level)
- {
-- if (rt2x00_rt(rt2x00dev, RT3593))
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level);
- else if (rt2x00_rt(rt2x00dev, RT6352))
- rt2800_config_txpower_rt6352(rt2x00dev, chan, power_level);
+++ /dev/null
-From caea0671cd8fd9ade4f5969cbe0ee545e94ae105 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sat, 24 Aug 2013 11:49:55 +0200
-Subject: [PATCH] rt2x00: rt2800lib: hardcode txmixer gain values to zero for
- RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -8965,7 +8965,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
- {
- u16 word;
-
-- if (rt2x00_rt(rt2x00dev, RT3593))
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- return 0;
-
- word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG);
-@@ -8979,7 +8980,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
- {
- u16 word;
-
-- if (rt2x00_rt(rt2x00dev, RT3593))
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- return 0;
-
- word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A);
+++ /dev/null
-From 11c40fb47c4a4dd6ad060c2ae127ced89ffb9fe1 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Thu, 18 Apr 2013 14:33:33 +0200
-Subject: [PATCH] rt2x00: rt2800lib: use correct [RT]XWI size for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -591,6 +591,7 @@ void rt2800_get_txwi_rxwi_size(struct rt
- {
- switch (rt2x00dev->chip.rt) {
- case RT3593:
-+ case RT3883:
- *txwi_size = TXWI_DESC_SIZE_4WORDS;
- *rxwi_size = RXWI_DESC_SIZE_5WORDS;
- break;
+++ /dev/null
-From fa5ad9c025610c22048add2f0ad03f62b6ca1e74 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Mon, 30 Sep 2013 16:53:33 +0200
-Subject: [PATCH] rt2x00: rt2800lib: fix antenna configuration for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -2017,7 +2017,8 @@ void rt2800_config_ant(struct rt2x00_dev
- rt2800_bbp_write(rt2x00dev, 3, r3);
- rt2800_bbp_write(rt2x00dev, 1, r1);
-
-- if (rt2x00_rt(rt2x00dev, RT3593)) {
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883)) {
- if (ant->rx_chain_num == 1)
- rt2800_bbp_write(rt2x00dev, 86, 0x00);
- else
+++ /dev/null
-From 6d668fef3a1baa60bdd715ee062ddb6333d2647c Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Mon, 30 Sep 2013 16:58:23 +0200
-Subject: [PATCH] rt2x00: rt2800lib: fix LNA gain configuration for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -2040,7 +2040,8 @@ static void rt2800_config_lna_gain(struc
- eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA);
- lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
- } else if (libconf->rf.channel <= 128) {
-- if (rt2x00_rt(rt2x00dev, RT3593)) {
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883)) {
- eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
- lna_gain = rt2x00_get_field16(eeprom,
- EEPROM_EXT_LNA2_A1);
-@@ -2050,7 +2051,8 @@ static void rt2800_config_lna_gain(struc
- EEPROM_RSSI_BG2_LNA_A1);
- }
- } else {
-- if (rt2x00_rt(rt2x00dev, RT3593)) {
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883)) {
- eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
- lna_gain = rt2x00_get_field16(eeprom,
- EEPROM_EXT_LNA2_A2);
+++ /dev/null
-From c49b2d829aa1c816a46a577cdec6d2ff14d9f06e Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Tue, 1 Oct 2013 15:40:08 +0200
-Subject: [PATCH] rt2x00: rt2800lib: fix VGC setup for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 11 +++++++++--
- 1 file changed, 9 insertions(+), 2 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -5364,7 +5364,8 @@ static u8 rt2800_get_default_vgc(struct
- else
- vgc = 0x2e + rt2x00dev->lna_gain;
- } else { /* 5GHZ band */
-- if (rt2x00_rt(rt2x00dev, RT3593))
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883))
- vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
- else if (rt2x00_rt(rt2x00dev, RT5592))
- vgc = 0x24 + (2 * rt2x00dev->lna_gain);
-@@ -5384,7 +5385,8 @@ static inline void rt2800_set_vgc(struct
- {
- if (qual->vgc_level != vgc_level) {
- if (rt2x00_rt(rt2x00dev, RT3572) ||
-- rt2x00_rt(rt2x00dev, RT3593)) {
-+ rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883)) {
- rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
- vgc_level);
- } else if (rt2x00_rt(rt2x00dev, RT5592)) {
-@@ -5431,6 +5433,11 @@ void rt2800_link_tuner(struct rt2x00_dev
- }
- break;
-
-+ case RT3883:
-+ if (qual->rssi > -65)
-+ vgc += 0x10;
-+ break;
-+
- case RT5592:
- if (qual->rssi > -65)
- vgc += 0x20;
+++ /dev/null
-From 1616650aea676541d4dc8adc6f4219856d193c8b Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Tue, 1 Oct 2013 17:27:57 +0200
-Subject: [PATCH] rt2x00: rt2800lib: fix EEPROM LNA validation for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -9098,7 +9098,8 @@ static int rt2800_validate_eeprom(struct
- word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2);
- if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
- rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
-- if (!rt2x00_rt(rt2x00dev, RT3593)) {
-+ if (!rt2x00_rt(rt2x00dev, RT3593) &&
-+ !rt2x00_rt(rt2x00dev, RT3883)) {
- 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,
-@@ -9118,7 +9119,8 @@ static int rt2800_validate_eeprom(struct
- word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2);
- if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
- rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
-- if (!rt2x00_rt(rt2x00dev, RT3593)) {
-+ if (!rt2x00_rt(rt2x00dev, RT3593) &&
-+ !rt2x00_rt(rt2x00dev, RT3883)) {
- 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,
-@@ -9126,7 +9128,8 @@ static int rt2800_validate_eeprom(struct
- }
- rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
-
-- if (rt2x00_rt(rt2x00dev, RT3593)) {
-+ if (rt2x00_rt(rt2x00dev, RT3593) ||
-+ rt2x00_rt(rt2x00dev, RT3883)) {
- word = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
- if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 ||
- rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
+++ /dev/null
-From e3871034a0e7c8a95152dc3eafbcc4535398cbdc Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Wed, 2 Oct 2013 10:11:59 +0200
-Subject: [PATCH] rt2x00: rt2800lib: fix txpower compensation for RT3883
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -4354,6 +4354,9 @@ static u8 rt2800_compensate_txpower(stru
- if (rt2x00_rt(rt2x00dev, RT3593))
- return min_t(u8, txpower, 0xc);
-
-+ if (rt2x00_rt(rt2x00dev, RT3883))
-+ return min_t(u8, txpower, 0xf);
-+
- if (rt2x00_has_cap_power_limit(rt2x00dev)) {
- /*
- * Check if eirp txpower exceed txpower_limit.
+++ /dev/null
-From 5e67d4f8a46d19748b501c2ef86de3f50d3cfd51 Mon Sep 17 00:00:00 2001
-From: Gabor Juhos <juhosg@openwrt.org>
-Date: Sun, 24 Mar 2013 19:26:27 +0100
-Subject: [PATCH] rt2x00: rt2800mmio: add a workaround for spurious
- TX_FIFO_STATUS interrupts
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 72 +++++++++++++++++++++++++-----
- drivers/net/wireless/ralink/rt2x00/rt2x00.h | 5 +++
- 2 files changed, 65 insertions(+), 12 deletions(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
-@@ -424,9 +424,9 @@ void rt2800mmio_autowake_tasklet(unsigne
- }
- EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
-
--static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
-+static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev,
-+ u32 status)
- {
-- u32 status;
- int i;
-
- /*
-@@ -447,29 +447,77 @@ static void rt2800mmio_txstatus_interrup
- * Since we have only one producer and one consumer we don't
- * need to lock the kfifo.
- */
-- for (i = 0; i < rt2x00dev->tx->limit; i++) {
-- status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
--
-- if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
-- break;
--
-+ i = 0;
-+ do {
- if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
-- rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
-+ rt2x00_warn(rt2x00dev,
-+ "TX status FIFO overrun, drop TX status report\n");
- break;
- }
-- }
-+
-+ if (++i >= rt2x00dev->tx->limit)
-+ break;
-+
-+ status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
-+ } while (rt2x00_get_field32(status, TX_STA_FIFO_VALID));
-
- /* Schedule the tasklet for processing the tx status. */
- tasklet_schedule(&rt2x00dev->txstatus_tasklet);
- }
-
-+#define RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES 4
-+
-+static bool rt2800mmio_txstatus_is_spurious(struct rt2x00_dev *rt2x00dev,
-+ u32 txstatus)
-+{
-+ if (likely(rt2x00_get_field32(txstatus, TX_STA_FIFO_VALID))) {
-+ rt2x00dev->txstatus_irq_retries = 0;
-+ return false;
-+ }
-+
-+ rt2x00dev->txstatus_irq_retries++;
-+
-+ /* Ensure that we don't go into an infinite IRQ loop. */
-+ if (rt2x00dev->txstatus_irq_retries >=
-+ RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES) {
-+ rt2x00_warn(rt2x00dev,
-+ "%u spurious TX_FIFO_STATUS interrupt(s)\n",
-+ rt2x00dev->txstatus_irq_retries);
-+ rt2x00dev->txstatus_irq_retries = 0;
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
- irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
- {
- struct rt2x00_dev *rt2x00dev = dev_instance;
- u32 reg, mask;
-+ u32 txstatus = 0;
-
-- /* Read status and ACK all interrupts */
-+ /* Read status */
- reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
-+
-+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
-+ /* Due to unknown reason the hardware generates a
-+ * TX_FIFO_STATUS interrupt before the TX_STA_FIFO
-+ * register contain valid data. Read the TX status
-+ * here to see if we have to process the actual
-+ * request.
-+ */
-+ txstatus = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
-+ if (rt2800mmio_txstatus_is_spurious(rt2x00dev, txstatus)) {
-+ /* Remove the TX_FIFO_STATUS bit so it won't be
-+ * processed in this turn. The hardware will
-+ * generate another IRQ for us.
-+ */
-+ rt2x00_set_field32(®,
-+ INT_SOURCE_CSR_TX_FIFO_STATUS, 0);
-+ }
-+ }
-+
-+ /* ACK interrupts */
- rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
- if (!reg)
-@@ -486,7 +534,7 @@ irqreturn_t rt2800mmio_interrupt(int irq
- mask = ~reg;
-
- if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
-- rt2800mmio_txstatus_interrupt(rt2x00dev);
-+ rt2800mmio_txstatus_interrupt(rt2x00dev, txstatus);
- /*
- * Never disable the TX_FIFO_STATUS interrupt.
- */
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -1000,6 +1000,11 @@ struct rt2x00_dev {
- int rf_channel;
-
- /*
-+ * Counter for tx status irq retries (rt2800pci).
-+ */
-+ unsigned int txstatus_irq_retries;
-+
-+ /*
- * Protect the interrupt mask register.
- */
- spinlock_t irqmask_lock;
+++ /dev/null
---- /dev/null
-+++ b/include/linux/rt2x00_platform.h
-@@ -0,0 +1,19 @@
-+/*
-+ * Platform data definition for the rt2x00 driver
-+ *
-+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ *
-+ */
-+
-+#ifndef _RT2X00_PLATFORM_H
-+#define _RT2X00_PLATFORM_H
-+
-+struct rt2x00_platform_data {
-+ char *eeprom_file_name;
-+};
-+
-+#endif /* _RT2X00_PLATFORM_H */
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -40,6 +40,7 @@
- #include <linux/average.h>
- #include <linux/usb.h>
- #include <linux/clk.h>
-+#include <linux/rt2x00_platform.h>
-
- #include <net/mac80211.h>
-
+++ /dev/null
---- a/local-symbols
-+++ b/local-symbols
-@@ -299,6 +299,7 @@ RT2X00_LIB_FIRMWARE=
- RT2X00_LIB_CRYPTO=
- RT2X00_LIB_LEDS=
- RT2X00_LIB_DEBUGFS=
-+RT2X00_LIB_EEPROM=
- RT2X00_DEBUG=
- WLAN_VENDOR_REALTEK=
- RTL8180=
---- a/drivers/net/wireless/ralink/rt2x00/Kconfig
-+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
-@@ -69,6 +69,7 @@ config RT2800PCI
- select RT2X00_LIB_MMIO
- select RT2X00_LIB_PCI
- select RT2X00_LIB_FIRMWARE
-+ select RT2X00_LIB_EEPROM
- select RT2X00_LIB_CRYPTO
- depends on CRC_CCITT
- depends on EEPROM_93CX6
-@@ -215,6 +216,7 @@ config RT2800SOC
- select RT2X00_LIB_MMIO
- select RT2X00_LIB_CRYPTO
- select RT2X00_LIB_FIRMWARE
-+ select RT2X00_LIB_EEPROM
- select RT2800_LIB
- select RT2800_LIB_MMIO
- ---help---
-@@ -265,6 +267,9 @@ config RT2X00_LIB_FIRMWARE
- config RT2X00_LIB_CRYPTO
- bool
-
-+config RT2X00_LIB_EEPROM
-+ boolean
-+
- config RT2X00_LIB_LEDS
- bool
- default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
---- a/drivers/net/wireless/ralink/rt2x00/Makefile
-+++ b/drivers/net/wireless/ralink/rt2x00/Makefile
-@@ -7,6 +7,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) +
- rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
- rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
- rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS) += rt2x00leds.o
-+rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o
-
- obj-$(CPTCFG_RT2X00_LIB) += rt2x00lib.o
- obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
-@@ -48,6 +48,8 @@ struct rt2800_drv_data {
- struct ieee80211_sta *wcid_to_sta[STA_IDS_SIZE];
- };
-
-+#include "rt2800.h"
-+
- struct rt2800_ops {
- u32 (*register_read)(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset);
-@@ -145,6 +147,15 @@ static inline int rt2800_read_eeprom(str
- {
- const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
-
-+ if (rt2x00dev->eeprom_file) {
-+ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data,
-+ EEPROM_SIZE);
-+ return 0;
-+ }
-+
-+ if (!rt2800ops->read_eeprom)
-+ return -EINVAL;
-+
- return rt2800ops->read_eeprom(rt2x00dev);
- }
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-@@ -102,19 +102,6 @@ static int rt2800soc_set_device_state(st
- return retval;
- }
-
--static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
--{
-- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
--
-- if (!base_addr)
-- return -ENOMEM;
--
-- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
--
-- iounmap(base_addr);
-- return 0;
--}
--
- /* Firmware functions */
- static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
- {
-@@ -178,7 +165,6 @@ static const struct rt2800_ops rt2800soc
- .register_multiread = rt2x00mmio_register_multiread,
- .register_multiwrite = rt2x00mmio_register_multiwrite,
- .regbusy_read = rt2x00mmio_regbusy_read,
-- .read_eeprom = rt2800soc_read_eeprom,
- .hwcrypt_disabled = rt2800soc_hwcrypt_disabled,
- .drv_write_firmware = rt2800soc_write_firmware,
- .drv_init_registers = rt2800mmio_init_registers,
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -702,6 +702,7 @@ enum rt2x00_capability_flags {
- REQUIRE_HT_TX_DESC,
- REQUIRE_PS_AUTOWAKE,
- REQUIRE_DELAYED_RFKILL,
-+ REQUIRE_EEPROM_FILE,
-
- /*
- * Capabilities
-@@ -977,6 +978,11 @@ struct rt2x00_dev {
- const struct firmware *fw;
-
- /*
-+ * EEPROM image.
-+ */
-+ const struct firmware *eeprom_file;
-+
-+ /*
- * FIFO for storing tx status reports between isr and tasklet.
- */
- DECLARE_KFIFO_PTR(txstatus_fifo, u32);
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -1421,6 +1421,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
- INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
- INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
-
-+ retval = rt2x00lib_load_eeprom_file(rt2x00dev);
-+ if (retval)
-+ goto exit;
-+
- /*
- * Let the driver probe the device to detect the capabilities.
- */
-@@ -1562,6 +1566,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
- * Free the driver data.
- */
- kfree(rt2x00dev->drv_data);
-+
-+ /*
-+ * Free EEPROM image.
-+ */
-+ rt2x00lib_free_eeprom_file(rt2x00dev);
- }
- EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
-
---- /dev/null
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-@@ -0,0 +1,105 @@
-+/*
-+ Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
-+ Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
-+ <http://rt2x00.serialmonkey.com>
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the
-+ Free Software Foundation, Inc.,
-+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-+ */
-+
-+/*
-+ Module: rt2x00lib
-+ Abstract: rt2x00 eeprom file loading routines.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+
-+#include "rt2x00.h"
-+#include "rt2x00lib.h"
-+
-+static const char *
-+rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
-+{
-+ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
-+
-+ if (pdata && pdata->eeprom_file_name)
-+ return pdata->eeprom_file_name;
-+
-+ return NULL
-+}
-+
-+static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
-+{
-+ const struct firmware *ee;
-+ const char *ee_name;
-+ int retval;
-+
-+ ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
-+ if (!ee_name && test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags)) {
-+ rt2x00_err(rt2x00dev, "Required EEPROM name is missing.");
-+ return -EINVAL;
-+ }
-+
-+ if (!ee_name)
-+ return 0;
-+
-+ rt2x00_info(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name);
-+
-+ retval = request_firmware(&ee, ee_name, rt2x00dev->dev);
-+ if (retval) {
-+ rt2x00_err(rt2x00dev, "Failed to request EEPROM.\n");
-+ return retval;
-+ }
-+
-+ if (!ee || !ee->size || !ee->data) {
-+ rt2x00_err(rt2x00dev, "Failed to read EEPROM file.\n");
-+ retval = -ENOENT;
-+ goto err_exit;
-+ }
-+
-+ if (ee->size != rt2x00dev->ops->eeprom_size) {
-+ rt2x00_err(rt2x00dev,
-+ "EEPROM file size is invalid, it should be %d bytes\n",
-+ rt2x00dev->ops->eeprom_size);
-+ retval = -EINVAL;
-+ goto err_release_ee;
-+ }
-+
-+ rt2x00dev->eeprom_file = ee;
-+ return 0;
-+
-+err_release_ee:
-+ release_firmware(ee);
-+err_exit:
-+ return retval;
-+}
-+
-+int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
-+{
-+ int retval;
-+
-+ retval = rt2x00lib_request_eeprom_file(rt2x00dev);
-+ if (retval)
-+ return retval;
-+
-+ return 0;
-+}
-+
-+void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
-+{
-+ release_firmware(rt2x00dev->eeprom_file);
-+ rt2x00dev->eeprom_file = NULL;
-+}
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h
-@@ -297,6 +297,22 @@ static inline void rt2x00lib_free_firmwa
- #endif /* CPTCFG_RT2X00_LIB_FIRMWARE */
-
- /*
-+ * EEPROM file handlers.
-+ */
-+#ifdef CPTCFG_RT2X00_LIB_EEPROM
-+int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev);
-+void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev);
-+#else
-+static inline int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
-+{
-+ return 0;
-+}
-+static inline void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
-+{
-+}
-+#endif /* CPTCFG_RT2X00_LIB_EEPROM */
-+
-+/*
- * Debugfs handlers.
- */
- #ifdef CPTCFG_RT2X00_LIB_DEBUGFS
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
-@@ -97,6 +97,7 @@ int rt2x00soc_probe(struct platform_devi
- if (IS_ERR(rt2x00dev->clk))
- rt2x00dev->clk = NULL;
-
-+ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
- rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
-
- retval = rt2x00soc_alloc_reg(rt2x00dev);
+++ /dev/null
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-@@ -26,6 +26,7 @@
-
- #include <linux/kernel.h>
- #include <linux/module.h>
-+#include <linux/of.h>
-
- #include "rt2x00.h"
- #include "rt2x00lib.h"
-@@ -34,11 +35,21 @@ static const char *
- rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
- {
- struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
-+#ifdef CONFIG_OF
-+ struct device_node *np;
-+ const char *eep;
-+#endif
-
- if (pdata && pdata->eeprom_file_name)
- return pdata->eeprom_file_name;
-
-- return NULL
-+#ifdef CONFIG_OF
-+ np = rt2x00dev->dev->of_node;
-+ if (np && of_property_read_string(np, "ralink,eeprom", &eep) == 0)
-+ return eep;
-+#endif
-+
-+ return NULL;
- }
-
- static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
+++ /dev/null
-From 339fe73f340161a624cc08e738d2244814852c3e Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 17 Mar 2013 00:55:04 +0100
-Subject: [PATCH] rt2x00: load eeprom on SoC from a mtd device defines inside
- OF
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/Kconfig | 1 +
- drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c | 65 +++++++++++++++++++++++
- 2 files changed, 66 insertions(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/Kconfig
-+++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
-@@ -219,6 +219,7 @@ config RT2800SOC
- select RT2X00_LIB_EEPROM
- select RT2800_LIB
- select RT2800_LIB_MMIO
-+ select MTD if SOC_RT288X || SOC_RT305X
- ---help---
- This adds support for Ralink WiSoC devices.
- Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
-@@ -26,11 +26,73 @@
-
- #include <linux/kernel.h>
- #include <linux/module.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/partitions.h>
- #include <linux/of.h>
-
- #include "rt2x00.h"
- #include "rt2x00lib.h"
-
-+static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
-+{
-+ int ret = -EINVAL;
-+#ifdef CONFIG_OF
-+ static struct firmware mtd_fw;
-+ struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
-+ size_t retlen, len = rt2x00dev->ops->eeprom_size;
-+ int i, size, offset = 0;
-+ struct mtd_info *mtd;
-+ const char *part;
-+ const __be32 *list;
-+ phandle phandle;
-+
-+ list = of_get_property(np, "ralink,mtd-eeprom", &size);
-+ if (!list)
-+ return -ENOENT;
-+
-+ phandle = be32_to_cpup(list++);
-+ if (phandle)
-+ mtd_np = of_find_node_by_phandle(phandle);
-+ if (!mtd_np) {
-+ dev_err(rt2x00dev->dev, "failed to load mtd phandle\n");
-+ return -EINVAL;
-+ }
-+
-+ part = of_get_property(mtd_np, "label", NULL);
-+ if (!part)
-+ part = mtd_np->name;
-+
-+ mtd = get_mtd_device_nm(part);
-+ if (IS_ERR(mtd)) {
-+ dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part);
-+ return PTR_ERR(mtd);
-+ }
-+
-+ if (size > sizeof(*list))
-+ offset = be32_to_cpup(list);
-+
-+ ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom);
-+ put_mtd_device(mtd);
-+
-+ if ((retlen != rt2x00dev->ops->eeprom_size) || ret) {
-+ dev_err(rt2x00dev->dev, "failed to load eeprom from device \"%s\"\n", part);
-+ return ret;
-+ }
-+
-+ if (of_find_property(np, "ralink,mtd-eeprom-swap", NULL))
-+ for (i = 0; i < len/sizeof(u16); i++)
-+ rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]);
-+
-+ rt2x00dev->eeprom_file = &mtd_fw;
-+ mtd_fw.size = len;
-+ mtd_fw.data = (const u8 *) rt2x00dev->eeprom;
-+
-+ dev_info(rt2x00dev->dev, "loaded eeprom from mtd device \"%s\"\n", part);
-+#endif
-+
-+ return ret;
-+}
-+
- static const char *
- rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
- {
-@@ -58,6 +120,9 @@ static int rt2x00lib_request_eeprom_file
- const char *ee_name;
- int retval;
-
-+ if (!rt2800lib_read_eeprom_mtd(rt2x00dev))
-+ return 0;
-+
- ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
- if (!ee_name && test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags)) {
- rt2x00_err(rt2x00dev, "Required EEPROM name is missing.");
+++ /dev/null
---- a/include/linux/rt2x00_platform.h
-+++ b/include/linux/rt2x00_platform.h
-@@ -14,6 +14,9 @@
-
- struct rt2x00_platform_data {
- char *eeprom_file_name;
-+
-+ int disable_2ghz;
-+ int disable_5ghz;
- };
-
- #endif /* _RT2X00_PLATFORM_H */
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -1026,6 +1026,22 @@ static int rt2x00lib_probe_hw_modes(stru
- unsigned int num_rates;
- unsigned int i;
-
-+ if (rt2x00dev->dev->platform_data) {
-+ struct rt2x00_platform_data *pdata;
-+
-+ pdata = rt2x00dev->dev->platform_data;
-+ if (pdata->disable_2ghz)
-+ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
-+ if (pdata->disable_5ghz)
-+ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
-+ }
-+
-+ if ((spec->supported_bands & SUPPORT_BAND_BOTH) == 0) {
-+ rt2x00_err(rt2x00dev, "No supported bands\n");
-+ return -EINVAL;
-+ }
-+
-+
- num_rates = 0;
- if (spec->supported_rates & SUPPORT_RATE_CCK)
- num_rates += 4;
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
-@@ -409,6 +409,7 @@ struct hw_mode_spec {
- unsigned int supported_bands;
- #define SUPPORT_BAND_2GHZ 0x00000001
- #define SUPPORT_BAND_5GHZ 0x00000002
-+#define SUPPORT_BAND_BOTH (SUPPORT_BAND_2GHZ | SUPPORT_BAND_5GHZ)
-
- unsigned int supported_rates;
- #define SUPPORT_RATE_CCK 0x00000001
+++ /dev/null
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -1004,8 +1004,13 @@ static void rt2x00lib_rate(struct ieee80
-
- void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr)
- {
-+ struct rt2x00_platform_data *pdata;
- const char *mac_addr;
-
-+ pdata = rt2x00dev->dev->platform_data;
-+ if (pdata && pdata->mac_address)
-+ ether_addr_copy(eeprom_mac_addr, pdata->mac_address);
-+
- mac_addr = of_get_mac_address(rt2x00dev->dev->of_node);
- if (mac_addr)
- ether_addr_copy(eeprom_mac_addr, mac_addr);
---- a/include/linux/rt2x00_platform.h
-+++ b/include/linux/rt2x00_platform.h
-@@ -14,6 +14,7 @@
-
- struct rt2x00_platform_data {
- char *eeprom_file_name;
-+ const u8 *mac_address;
-
- int disable_2ghz;
- int disable_5ghz;
+++ /dev/null
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -1030,6 +1030,16 @@ static int rt2x00lib_probe_hw_modes(stru
- struct ieee80211_rate *rates;
- unsigned int num_rates;
- unsigned int i;
-+#ifdef CONFIG_OF
-+ struct device_node *np = rt2x00dev->dev->of_node;
-+ unsigned int enabled;
-+ if (!of_property_read_u32(np, "ralink,2ghz",
-+ &enabled) && !enabled)
-+ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
-+ if (!of_property_read_u32(np, "ralink,5ghz",
-+ &enabled) && !enabled)
-+ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
-+#endif /* CONFIG_OF */
-
- if (rt2x00dev->dev->platform_data) {
- struct rt2x00_platform_data *pdata;
+++ /dev/null
-From 04dbd87265f6ba4a373b211ba324b437d224fb2d Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 17 Mar 2013 00:03:31 +0100
-Subject: [PATCH 21/38] rt2x00: make wmac loadable via OF on rt288x/305x SoC
-
-This patch ads the match table to allow loading the wmac support from a
-devicetree.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800pci.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
-@@ -234,10 +234,17 @@ static int rt2800soc_probe(struct platfo
- return rt2x00soc_probe(pdev, &rt2800soc_ops);
- }
-
-+static const struct of_device_id rt2880_wmac_match[] = {
-+ { .compatible = "ralink,rt2880-wmac" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, rt2880_wmac_match);
-+
- static struct platform_driver rt2800soc_driver = {
- .driver = {
- .name = "rt2800_wmac",
- .mod_name = KBUILD_MODNAME,
-+ .of_match_table = rt2880_wmac_match,
- },
- .probe = rt2800soc_probe,
- .remove = rt2x00soc_remove,
+++ /dev/null
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -36,6 +36,7 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/slab.h>
-+#include <linux/of.h>
-
- #include "rt2x00.h"
- #include "rt2800lib.h"
-@@ -9285,6 +9286,17 @@ static int rt2800_init_eeprom(struct rt2
- rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
- rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
-
-+ {
-+ struct device_node *np = rt2x00dev->dev->of_node;
-+ unsigned int led_polarity;
-+
-+ /* Allow overriding polarity from OF */
-+ if (!of_property_read_u32(np, "ralink,led-polarity",
-+ &led_polarity))
-+ rt2x00_set_field16(&eeprom, EEPROM_FREQ_LED_POLARITY,
-+ led_polarity);
-+ }
-+
- rt2x00dev->led_mcu_reg = eeprom;
- #endif /* CPTCFG_RT2X00_LIB_LEDS */
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
-@@ -109,6 +109,9 @@ static int rt2x00leds_register_led(struc
- led->led_dev.name = name;
- led->led_dev.brightness = LED_OFF;
-
-+ if (rt2x00_is_soc(rt2x00dev))
-+ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
-+
- retval = led_classdev_register(device, &led->led_dev);
- if (retval) {
- rt2x00_err(rt2x00dev, "Failed to register led handler\n");
+++ /dev/null
---- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
-@@ -1361,7 +1361,7 @@ static inline void rt2x00lib_set_if_comb
- */
- if_limit = &rt2x00dev->if_limits_ap;
- if_limit->max = rt2x00dev->ops->max_ap_intf;
-- if_limit->types = BIT(NL80211_IFTYPE_AP);
-+ if_limit->types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION);
- #ifdef CPTCFG_MAC80211_MESH
- if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
- #endif
+++ /dev/null
-From 9782a7f7488443568fa4d6088b73c9aff7eb8510 Mon Sep 17 00:00:00 2001
-From: Daniel Golle <daniel@makrotopia.org>
-Date: Wed, 19 Apr 2017 16:14:53 +0200
-Subject: [PATCH] rt2x00: add support for external PA on MT7620
-To: Stanislaw Gruszka <sgruszka@redhat.com>
-Cc: Helmut Schaa <helmut.schaa@googlemail.com>,
- linux-wireless@vger.kernel.org,
- Kalle Valo <kvalo@codeaurora.org>
-
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
----
- drivers/net/wireless/ralink/rt2x00/rt2800.h | 1 +
- drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 70 +++++++++++++++++++++++++-
- 2 files changed, 70 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
-@@ -2749,6 +2749,7 @@ enum rt2800_eeprom_word {
- #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f)
- #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0)
- #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600)
-+#define EEPROM_NIC_CONF2_EXTERNAL_PA FIELD16(0xc000)
-
- /*
- * EEPROM LNA
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -4120,6 +4120,61 @@ static void rt2800_config_channel(struct
- rt2800_iq_calibrate(rt2x00dev, rf->channel);
- }
-
-+ if (rt2x00_rt(rt2x00dev, RT6352)) {
-+ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0,
-+ &rt2x00dev->cap_flags)) {
-+ rt2x00_warn(rt2x00dev, "Using incomplete support for " \
-+ "external PA\n");
-+ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
-+ reg |= 0x00000101;
-+ rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
-+
-+ reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
-+ reg |= 0x00000101;
-+ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
-+
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 43, 0x73);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 43, 0x73);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 44, 0x73);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 44, 0x73);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 45, 0x73);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0x73);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 46, 0x27);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 46, 0x27);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0xC8);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0xC8);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 48, 0xA4);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 48, 0xA4);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 49, 0x05);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 49, 0x05);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x27);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 55, 0xC8);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 55, 0xC8);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 56, 0xA4);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 56, 0xA4);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 57, 0x05);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 57, 0x05);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 58, 0x27);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 58, 0x27);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 59, 0xC8);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 59, 0xC8);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 60, 0xA4);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 60, 0xA4);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 4, 61, 0x05);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 6, 61, 0x05);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 5, 05, 0x00);
-+ rt2800_rfcsr_write_bank(rt2x00dev, 7, 05, 0x00);
-+
-+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
-+ 0x36303636);
-+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN,
-+ 0x6C6C6B6C);
-+ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
-+ 0x6C6C6B6C);
-+ }
-+ }
-+
- bbp = rt2800_bbp_read(rt2x00dev, 4);
- rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
- rt2800_bbp_write(rt2x00dev, 4, bbp);
-@@ -9314,7 +9369,8 @@ static int rt2800_init_eeprom(struct rt2
- */
- eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
-
-- if (rt2x00_rt(rt2x00dev, RT3352)) {
-+ if (rt2x00_rt(rt2x00dev, RT3352) ||
-+ rt2x00_rt(rt2x00dev, RT6352)) {
- if (rt2x00_get_field16(eeprom,
- EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352))
- __set_bit(CAPABILITY_EXTERNAL_PA_TX0,
-@@ -9325,6 +9381,18 @@ static int rt2800_init_eeprom(struct rt2
- &rt2x00dev->cap_flags);
- }
-
-+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF2);
-+
-+ if (rt2x00_rt(rt2x00dev, RT6352) && eeprom != 0 && eeprom != 0xffff) {
-+ if (rt2x00_get_field16(eeprom,
-+ EEPROM_NIC_CONF2_EXTERNAL_PA)) {
-+ __set_bit(CAPABILITY_EXTERNAL_PA_TX0,
-+ &rt2x00dev->cap_flags);
-+ __set_bit(CAPABILITY_EXTERNAL_PA_TX1,
-+ &rt2x00dev->cap_flags);
-+ }
-+ }
-+
- return 0;
- }
-
+++ /dev/null
-From pozega.tomislav@gmail.com Thu May 18 12:42:27 2017
-Return-path: <pozega.tomislav@gmail.com>
-Envelope-to: daniel@makrotopia.org
-Delivery-date: Thu, 18 May 2017 12:42:27 +0200
-Received: from mail by fudo.makrotopia.org with sa-checked (Exim 4.88)
- (envelope-from <pozega.tomislav@gmail.com>)
- id 1dBIsy-00088b-PU
- for daniel@makrotopia.org; Thu, 18 May 2017 12:42:27 +0200
-X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on fudo.makrotopia.org
-X-Spam-Level:
-X-Spam-Status: No, score=-0.8 required=2.5 tests=DKIM_SIGNED,DKIM_VALID,
- DKIM_VALID_AU,FREEMAIL_FROM,HTML_MESSAGE,RCVD_IN_DNSWL_LOW shortcircuit=no
- autolearn=ham autolearn_force=no version=3.4.1
-Received: from mail-oi0-x22a.google.com ([2607:f8b0:4003:c06::22a])
- by fudo.makrotopia.org with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128)
- (Exim 4.88)
- (envelope-from <pozega.tomislav@gmail.com>)
- id 1dBIsv-00088Q-Dq
- for daniel@makrotopia.org; Thu, 18 May 2017 12:42:24 +0200
-Received: by mail-oi0-x22a.google.com with SMTP id w10so48782189oif.0
- for <daniel@makrotopia.org>; Thu, 18 May 2017 03:42:21 -0700 (PDT)
-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=gmail.com; s=20161025;
- h=mime-version:from:date:message-id:subject:to;
- bh=9dF7PHDassYY74+N6dAhmsL/B9i5oG3SEuMzHuazhJo=;
- b=cBGJ44v+o4ASyCPmHCBRMmRYnJCv4Gx6lzDiScKn0XqYmNHYpZTPg5cAY1GZFUhHdz
- 9QT5fzhJKFikBliSuJc/7/pI8KzvyEAdvawiWA7/5fbeiTZ+zjJnzRVGezqkYDKxjR6u
- 7TsoJxR2/oFwo7bOFlThhee+Nwf7qaX8AVal7JdkqovekX79JQ5vsKAa4LapDp7Cl0wr
- KCh0WRUHGEgpTLJFyQ3ThPmLqc8bhmu+6/V/LJ53VOY7uksZHMhvaKkk9vDCoOuPnBMK
- Cj2/c7z9RTErz/xlHg6HxnBe/pPc31XUsuPJUleOEdZASczPsreEEKacKCONVlP1wjAB
- iOkA==
-X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
- d=1e100.net; s=20161025;
- h=x-gm-message-state:mime-version:from:date:message-id:subject:to;
- bh=9dF7PHDassYY74+N6dAhmsL/B9i5oG3SEuMzHuazhJo=;
- b=LJAe4ZwS9aNJypROW7j+I9aNfRBWyDYy0c8ABnDbLrIoF9P2AA/Vs/Cli5f7GjaAxr
- 1JCx602ach+7R7QjQq/nqNmLuhRCfSvB0TGrq4R4v+CJ4ADO541+PddnFiU1dlIXQRP2
- TE2FOydSO0FGJBMg+kY0eFiidBtYj1T5x7IHAhQzufiuiF6/1xZS8h61CYJjLzt/aR5y
- JxOxsVvu3W2YQ0T5wKmAPlKtarFH6ZZgs446bRYt1MX5KAWzIoBM1+IPMMv7lSCpCaDR
- fwH05aDyaJW2IzXH5R9Tq7gGYycYjx/SnO7JupJXJVvOzKgBJxp60JwJhCfqCwESDuuD
- 8nNA==
-X-Gm-Message-State: AODbwcDOpdFZgbxAxFsVsqFdCBN3pRGDvEclZ1heVg2byNZ9BuG5kqJg
- GvZ9x4NGt0v8lVGa3esDw0N1KiJENg==
-X-Received: by 10.157.17.217 with SMTP id y25mr1310632oty.137.1495104134863;
- Thu, 18 May 2017 03:42:14 -0700 (PDT)
-MIME-Version: 1.0
-Received: by 10.157.0.105 with HTTP; Thu, 18 May 2017 03:42:14 -0700 (PDT)
-From: Tom Psyborg <pozega.tomislav@gmail.com>
-Date: Thu, 18 May 2017 12:42:14 +0200
-Message-ID: <CAKR_QVJBSKw2uCY4RbHZPvbGkMcvnBh+j6F+9t93mG3BakjX3Q@mail.gmail.com>
-Subject: [PATCH] rt2x00: remove unneccesary code
-To: linux-wireless <linux-wireless@vger.kernel.org>,
- Linux Kernel Mailing List <linux-kernel@vger.kernel.org>, Arnd Bergmann <arnd@arndb.de>,
- Jes Sorensen <jes.sorensen@gmail.com>, Stanislaw Gruszka <sgruszka@redhat.com>,
- David Miller <davem@davemloft.net>, Helmut Schaa <helmut.schaa@googlemail.com>,
- Kalle Valo <kvalo@codeaurora.org>, Daniel Golle <daniel@makrotopia.org>,
- Mathias Kresin <dev@kresin.me>, Johannes Berg <johannes.berg@intel.com>,
- Serge Vasilugin <vasilugin@yandex.ru>, Roman Yeryomin <roman@advem.lv>,
- Networking <netdev@vger.kernel.org>
-Content-Type: multipart/alternative; boundary="94eb2c1905d2dc6361054fca0e62"
-Status: RO
-Content-Length: 11079
-Lines: 178
-
---94eb2c1905d2dc6361054fca0e62
-Content-Type: text/plain; charset="UTF-8"
-Content-Transfer-Encoding: quoted-printable
-
-Use chanreg and dccal helpers to reduce the size of ePA code.
-
-Signed-off-by: Tomislav Po=C5=BEega <pozega.tomislav@gmail.com>
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
-[daniel@makrotopia.org: fixed white-space so patch applies]
----
-
---- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
-@@ -4133,38 +4133,22 @@ static void rt2800_config_channel(struct
- reg |= 0x00000101;
- rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
-
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 43, 0x73);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 43, 0x73);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 44, 0x73);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 44, 0x73);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 45, 0x73);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0x73);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 46, 0x27);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 46, 0x27);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0xC8);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0xC8);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 48, 0xA4);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 48, 0xA4);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 49, 0x05);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 49, 0x05);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x27);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 55, 0xC8);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 55, 0xC8);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 56, 0xA4);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 56, 0xA4);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 57, 0x05);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 57, 0x05);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 58, 0x27);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 58, 0x27);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 59, 0xC8);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 59, 0xC8);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 60, 0xA4);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 60, 0xA4);
-- rt2800_rfcsr_write_bank(rt2x00dev, 4, 61, 0x05);
-- rt2800_rfcsr_write_bank(rt2x00dev, 6, 61, 0x05);
-- rt2800_rfcsr_write_bank(rt2x00dev, 5, 05, 0x00);
-- rt2800_rfcsr_write_bank(rt2x00dev, 7, 05, 0x00);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4);
-+ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05);
-+ rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00);
-
- rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
- 0x36303636);
+++ /dev/null
---- a/drivers/net/wireless/marvell/mwl8k.c
-+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -5681,6 +5681,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
- MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
-
- static const struct pci_device_id mwl8k_pci_id_table[] = {
-+ { PCI_VDEVICE(MARVELL, 0x2a02), .driver_data = MWL8363, },
- { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, },
- { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, },
- { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, },
+++ /dev/null
---- a/drivers/net/wireless/marvell/libertas/cfg.c
-+++ b/drivers/net/wireless/marvell/libertas/cfg.c
-@@ -2040,6 +2040,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
- goto err_wiphy_new;
- }
-
-+ set_wiphy_dev(wdev->wiphy, dev);
-+
- return wdev;
-
- err_wiphy_new:
---- a/drivers/net/wireless/marvell/libertas/main.c
-+++ b/drivers/net/wireless/marvell/libertas/main.c
-@@ -930,6 +930,7 @@ struct lbs_private *lbs_add_card(void *c
- goto err_adapter;
- }
-
-+ dev_net_set(dev, wiphy_net(wdev->wiphy));
- dev->ieee80211_ptr = wdev;
- dev->ml_priv = priv;
- SET_NETDEV_DEV(dev, dmdev);
+++ /dev/null
---- a/drivers/net/wireless/marvell/libertas/cfg.c
-+++ b/drivers/net/wireless/marvell/libertas/cfg.c
-@@ -2116,6 +2116,8 @@ int lbs_cfg_register(struct lbs_private
- wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
- wdev->wiphy->reg_notifier = lbs_reg_notifier;
-
-+ memcpy(wdev->wiphy->perm_addr, priv->current_addr, ETH_ALEN);
-+
- ret = wiphy_register(wdev->wiphy);
- if (ret < 0)
- pr_err("cannot register wiphy device\n");
+++ /dev/null
---- a/drivers/net/wireless/broadcom/b43/b43.h
-+++ b/drivers/net/wireless/broadcom/b43/b43.h
-@@ -839,6 +839,7 @@ struct b43_wldev {
- bool qos_enabled; /* TRUE, if QoS is used. */
- bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
- bool use_pio; /* TRUE if next init should use PIO */
-+ int gpiomask; /* GPIO LED mask as a module parameter */
-
- /* PHY/Radio device. */
- struct b43_phy phy;
---- a/drivers/net/wireless/broadcom/b43/main.c
-+++ b/drivers/net/wireless/broadcom/b43/main.c
-@@ -85,6 +85,11 @@ MODULE_FIRMWARE("b43/ucode40.fw");
- MODULE_FIRMWARE("b43/ucode42.fw");
- MODULE_FIRMWARE("b43/ucode9.fw");
-
-+static int modparam_gpiomask = 0x000F;
-+module_param_named(gpiomask, modparam_gpiomask, int, 0444);
-+MODULE_PARM_DESC(gpiomask,
-+ "GPIO mask for LED control (default 0x000F)");
-+
- static int modparam_bad_frames_preempt;
- module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
- MODULE_PARM_DESC(bad_frames_preempt,
-@@ -2892,10 +2897,10 @@ static int b43_gpio_init(struct b43_wlde
- u32 mask, set;
-
- b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
-- b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF);
-+ b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, modparam_gpiomask);
-
- mask = 0x0000001F;
-- set = 0x0000000F;
-+ set = modparam_gpiomask;
- if (dev->dev->chip_id == 0x4301) {
- mask |= 0x0060;
- set |= 0x0060;
+++ /dev/null
---- a/drivers/net/wireless/broadcom/b43/Makefile
-+++ b/drivers/net/wireless/broadcom/b43/Makefile
-@@ -17,7 +17,7 @@ b43-$(CPTCFG_B43_PHY_AC) += phy_ac.o
- b43-y += sysfs.o
- b43-y += xmit.o
- b43-y += dma.o
--b43-y += pio.o
-+b43-$(CPTCFG_B43_PIO) += pio.o
- b43-y += rfkill.o
- b43-y += ppr.o
- b43-$(CPTCFG_B43_LEDS) += leds.o
---- a/drivers/net/wireless/broadcom/b43/main.c
-+++ b/drivers/net/wireless/broadcom/b43/main.c
-@@ -2018,10 +2018,12 @@ static void b43_do_interrupt_thread(stru
- dma_reason[0], dma_reason[1],
- dma_reason[2], dma_reason[3],
- dma_reason[4], dma_reason[5]);
-+#ifdef CPTCFG_B43_PIO
- b43err(dev->wl, "This device does not support DMA "
- "on your system. It will now be switched to PIO.\n");
- /* Fall back to PIO transfers if we get fatal DMA errors! */
- dev->use_pio = true;
-+#endif
- b43_controller_restart(dev, "DMA error");
- return;
- }
---- a/drivers/net/wireless/broadcom/b43/pio.h
-+++ b/drivers/net/wireless/broadcom/b43/pio.h
-@@ -150,7 +150,7 @@ static inline void b43_piorx_write32(str
- b43_write32(q->dev, q->mmio_base + offset, value);
- }
-
--
-+#ifdef CPTCFG_B43_PIO
- int b43_pio_init(struct b43_wldev *dev);
- void b43_pio_free(struct b43_wldev *dev);
-
-@@ -161,5 +161,37 @@ void b43_pio_rx(struct b43_pio_rxqueue *
-
- void b43_pio_tx_suspend(struct b43_wldev *dev);
- void b43_pio_tx_resume(struct b43_wldev *dev);
-+#else
-+static inline int b43_pio_init(struct b43_wldev *dev)
-+{
-+ return 0;
-+}
-+
-+static inline void b43_pio_free(struct b43_wldev *dev)
-+{
-+}
-+
-+static inline int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
-+{
-+ return 0;
-+}
-+
-+static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
-+ const struct b43_txstatus *status)
-+{
-+}
-+
-+static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
-+{
-+}
-+
-+static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
-+{
-+}
-+
-+static inline void b43_pio_tx_resume(struct b43_wldev *dev)
-+{
-+}
-+#endif /* CPTCFG_B43_PIO */
-
- #endif /* B43_PIO_H_ */
---- a/drivers/net/wireless/broadcom/b43/Kconfig
-+++ b/drivers/net/wireless/broadcom/b43/Kconfig
-@@ -98,7 +98,7 @@ config B43_BCMA_PIO
- default y
-
- config B43_PIO
-- bool
-+ bool "Broadcom 43xx PIO support"
- depends on B43 && B43_SSB
- select SSB_BLOCKIO
- default y
+++ /dev/null
---- a/drivers/net/wireless/broadcom/b43/main.c
-+++ b/drivers/net/wireless/broadcom/b43/main.c
-@@ -1658,7 +1658,7 @@ static void b43_write_beacon_template(st
- len, ram_offset, shm_size_offset, rate);
-
- /* Write the PHY TX control parameters. */
-- antenna = B43_ANTENNA_DEFAULT;
-+ antenna = dev->tx_antenna;
- 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. */
-@@ -3307,8 +3307,8 @@ static int b43_chip_init(struct b43_wlde
-
- /* Select the antennae */
- if (phy->ops->set_rx_antenna)
-- phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
-- b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
-+ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
-+ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
-
- if (phy->type == B43_PHYTYPE_B) {
- value16 = b43_read16(dev, 0x005E);
-@@ -4008,7 +4008,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;
-- int antenna;
- int err = 0;
-
- mutex_lock(&wl->mutex);
-@@ -4051,11 +4050,9 @@ static int b43_op_config(struct ieee8021
- }
-
- /* Antennas for RX and management frame TX. */
-- antenna = B43_ANTENNA_DEFAULT;
-- b43_mgmtframe_txantenna(dev, antenna);
-- antenna = B43_ANTENNA_DEFAULT;
-+ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
- if (phy->ops->set_rx_antenna)
-- phy->ops->set_rx_antenna(dev, antenna);
-+ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
-
- if (wl->radio_enabled != phy->radio_on) {
- if (wl->radio_enabled) {
-@@ -5199,6 +5196,47 @@ static int b43_op_get_survey(struct ieee
- return 0;
- }
-
-+static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
-+{
-+ struct b43_wl *wl = hw_to_b43_wl(hw);
-+ struct b43_wldev *dev = wl->current_dev;
-+
-+ if (tx_ant == 1 && rx_ant == 1) {
-+ dev->tx_antenna = B43_ANTENNA0;
-+ dev->rx_antenna = B43_ANTENNA0;
-+ }
-+ else if (tx_ant == 2 && rx_ant == 2) {
-+ dev->tx_antenna = B43_ANTENNA1;
-+ dev->rx_antenna = B43_ANTENNA1;
-+ }
-+ else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) {
-+ dev->tx_antenna = B43_ANTENNA_DEFAULT;
-+ dev->rx_antenna = B43_ANTENNA_DEFAULT;
-+ }
-+ else {
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
-+{
-+ struct b43_wl *wl = hw_to_b43_wl(hw);
-+ struct b43_wldev *dev = wl->current_dev;
-+
-+ switch (dev->tx_antenna) {
-+ case B43_ANTENNA0:
-+ *tx_ant = 1; *rx_ant = 1; break;
-+ case B43_ANTENNA1:
-+ *tx_ant = 2; *rx_ant = 2; break;
-+ case B43_ANTENNA_DEFAULT:
-+ *tx_ant = 3; *rx_ant = 3; break;
-+ }
-+ return 0;
-+}
-+
- static const struct ieee80211_ops b43_hw_ops = {
- .tx = b43_op_tx,
- .conf_tx = b43_op_conf_tx,
-@@ -5220,6 +5258,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,
-+ .set_antenna = b43_op_set_antenna,
-+ .get_antenna = b43_op_get_antenna,
- };
-
- /* Hard-reset the chip. Do not call this directly.
-@@ -5523,6 +5563,8 @@ static int b43_one_core_attach(struct b4
- if (!wldev)
- goto out;
-
-+ wldev->rx_antenna = B43_ANTENNA_DEFAULT;
-+ wldev->tx_antenna = B43_ANTENNA_DEFAULT;
- wldev->use_pio = b43_modparam_pio;
- wldev->dev = dev;
- wldev->wl = wl;
-@@ -5617,6 +5659,9 @@ static struct b43_wl *b43_wireless_init(
-
- wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
-
-+ hw->wiphy->available_antennas_rx = 0x3;
-+ hw->wiphy->available_antennas_tx = 0x3;
-+
- wl->hw_registred = false;
- hw->max_rates = 2;
- SET_IEEE80211_DEV(hw, dev->dev);
---- a/drivers/net/wireless/broadcom/b43/b43.h
-+++ b/drivers/net/wireless/broadcom/b43/b43.h
-@@ -840,6 +840,8 @@ struct b43_wldev {
- bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
- bool use_pio; /* TRUE if next init should use PIO */
- int gpiomask; /* GPIO LED mask as a module parameter */
-+ int rx_antenna; /* Used RX antenna (B43_ANTENNAxxx) */
-+ int tx_antenna; /* Used TX antenna (B43_ANTENNAxxx) */
-
- /* PHY/Radio device. */
- struct b43_phy phy;
+++ /dev/null
---- a/drivers/net/wireless/broadcom/b43/dma.h
-+++ b/drivers/net/wireless/broadcom/b43/dma.h
-@@ -169,7 +169,7 @@ struct b43_dmadesc_generic {
-
- /* DMA engine tuning knobs */
- #define B43_TXRING_SLOTS 256
--#define B43_RXRING_SLOTS 256
-+#define B43_RXRING_SLOTS 32
- #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
- #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
-
+++ /dev/null
---- a/drivers/net/wireless/broadcom/b43/main.c
-+++ b/drivers/net/wireless/broadcom/b43/main.c
-@@ -2909,6 +2909,14 @@ static int b43_gpio_init(struct b43_wlde
- } else if (dev->dev->chip_id == 0x5354) {
- /* Don't allow overtaking buttons GPIOs */
- set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */
-+ } else if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
-+ dev->dev->chip_id == BCMA_CHIP_ID_BCM47162 ||
-+ dev->dev->chip_id == BCMA_CHIP_ID_BCM5356 ||
-+ dev->dev->chip_id == BCMA_CHIP_ID_BCM5357 ||
-+ dev->dev->chip_id == BCMA_CHIP_ID_BCM53572) {
-+ /* just use gpio 0 and 1 for 2.4 GHz wifi led */
-+ set &= 0x3;
-+ mask &= 0x3;
- }
-
- if (0 /* FIXME: conditional unknown */ ) {
+++ /dev/null
---- a/drivers/net/wireless/broadcom/b43/main.c
-+++ b/drivers/net/wireless/broadcom/b43/main.c
-@@ -127,7 +127,7 @@ static int b43_modparam_pio = 0;
- module_param_named(pio, b43_modparam_pio, int, 0644);
- MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
-
--static int modparam_allhwsupport = !IS_ENABLED(CPTCFG_BRCMSMAC);
-+static int modparam_allhwsupport = 1;
- module_param_named(allhwsupport, modparam_allhwsupport, int, 0444);
- MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)");
-
+++ /dev/null
---- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
-@@ -58,19 +58,12 @@
- (((c) < 149) ? 3 : 4))))
-
- #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
--#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
-- NL80211_RRF_NO_IR)
-+#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, 0)
-
--#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
-- NL80211_RRF_NO_IR)
--#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
-- NL80211_RRF_DFS | \
-- NL80211_RRF_NO_IR)
--#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
-- NL80211_RRF_DFS | \
-- NL80211_RRF_NO_IR)
--#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
-- NL80211_RRF_NO_IR)
-+#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, 0)
-+#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, 0)
-+#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, 0)
-+#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, 0)
-
- static const struct ieee80211_regdomain brcms_regdom_x2 = {
- .n_reg_rules = 6,
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
-Date: Mon, 8 Jun 2015 16:11:40 +0200
-Subject: [PATCH] brcmfmac: register wiphy(s) during module_init
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This is needed by OpenWrt which expects all PHYs to be created after
-module loads successfully.
-
-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
----
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1347,6 +1347,7 @@ int __init brcmf_core_init(void)
- {
- if (!schedule_work(&brcmf_driver_work))
- return -EBUSY;
-+ flush_work(&brcmf_driver_work);
-
- return 0;
- }
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
-@@ -441,6 +441,7 @@ struct brcmf_fw {
- struct brcmf_fw_request *req;
- u32 curpos;
- void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
-+ struct completion *completion;
- };
-
- static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
-@@ -589,6 +590,8 @@ fail:
- fwctx->req = NULL;
- done:
- fwctx->done(fwctx->dev, ret, fwctx->req);
-+ if (fwctx->completion)
-+ complete(fwctx->completion);
- kfree(fwctx);
- }
-
-@@ -612,6 +615,8 @@ int brcmf_fw_get_firmwares(struct device
- struct brcmf_fw_request *req))
- {
- struct brcmf_fw *fwctx;
-+ struct completion completion;
-+ int err;
-
- brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
- if (!fw_cb)
-@@ -628,7 +633,14 @@ int brcmf_fw_get_firmwares(struct device
- fwctx->req = req;
- fwctx->done = fw_cb;
-
-+ init_completion(&completion);
-+ fwctx->completion = &completion;
-+
- brcmf_fw_request_next_item(fwctx, true);
-+
-+ wait_for_completion_timeout(fwctx->completion, msecs_to_jiffies(5000));
-+ fwctx->completion = NULL;
-+
- return 0;
- }
-
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
-Date: Thu, 9 Jul 2015 00:07:59 +0200
-Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
----
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -614,9 +614,37 @@ static struct wireless_dev *brcmf_cfg802
- enum nl80211_iftype type,
- struct vif_params *params)
- {
-+ struct net_device *dev;
- struct wireless_dev *wdev;
- int err;
-
-+ /*
-+ * There is a bug with in-firmware BSS management. When adding virtual
-+ * interface brcmfmac first tells firmware to create new BSS and then
-+ * it creates new struct net_device.
-+ *
-+ * If creating/registering netdev(ice) fails, BSS remains in some bugged
-+ * state. It conflicts with existing BSSes by overtaking their auth
-+ * requests.
-+ *
-+ * It results in one BSS (addresss X) sending beacons and another BSS
-+ * (address Y) replying to authentication requests. This makes interface
-+ * unusable as AP.
-+ *
-+ * To workaround this bug we may try to guess if register_netdev(ice)
-+ * will fail. The most obvious case is using interface name that already
-+ * exists. This is actually quite likely with brcmfmac & some user space
-+ * scripts as brcmfmac doesn't allow deleting virtual interfaces.
-+ * So this bug can be triggered even by something trivial like:
-+ * iw dev wlan0 delete
-+ * iw phy phy0 interface add wlan0 type __ap
-+ */
-+ dev = dev_get_by_name(&init_net, name);
-+ if (dev) {
-+ dev_put(dev);
-+ return ERR_PTR(-ENFILE);
-+ }
-+
- brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
- err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
- if (err) {
+++ /dev/null
-From 66ae1b1750720a33e29792a177b1e696f4f005fb Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 9 Mar 2016 17:25:59 +0000
-Subject: [PATCH] brcmfmac: Disable power management
-
-Disable wireless power saving in the brcmfmac WLAN driver. This is a
-temporary measure until the connectivity loss resulting from power
-saving is resolved.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
-@@ -2725,6 +2725,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
- * preference in cfg struct to apply this to
- * FW later while initializing the dongle
- */
-+#if defined(CONFIG_ARCH_BCM2835)
-+ brcmf_dbg(INFO, "power management disabled\n");
-+ enabled = false;
-+#endif
- cfg->pwr_save = enabled;
- if (!check_vif_up(ifp->vif)) {
-
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Subject: [PATCH] brcmfmac: add in-driver tables with country codes
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This adds early support for changing region. Ideally this data should
-be stored in DT as all these mappings are devices specific.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
----
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
-@@ -23,6 +23,36 @@
- #include "common.h"
- #include "of.h"
-
-+/* TODO: FIXME: Use DT */
-+static void brcmf_of_probe_cc(struct device *dev,
-+ struct brcmf_mp_device *settings)
-+{
-+ static struct brcmfmac_pd_cc_entry netgear_r8000_cc_ent[] = {
-+ { "JP", "JP", 78 },
-+ { "US", "Q2", 86 },
-+ };
-+ struct brcmfmac_pd_cc_entry *cc_ent = NULL;
-+ int table_size = 0;
-+
-+ if (of_machine_is_compatible("netgear,r8000")) {
-+ cc_ent = netgear_r8000_cc_ent;
-+ table_size = ARRAY_SIZE(netgear_r8000_cc_ent);
-+ }
-+
-+ if (cc_ent && table_size) {
-+ struct brcmfmac_pd_cc *cc;
-+ size_t memsize;
-+
-+ memsize = table_size * sizeof(struct brcmfmac_pd_cc_entry);
-+ cc = devm_kzalloc(dev, sizeof(*cc) + memsize, GFP_KERNEL);
-+ if (!cc)
-+ return;
-+ cc->table_size = table_size;
-+ memcpy(cc->table, cc_ent, memsize);
-+ settings->country_codes = cc;
-+ }
-+}
-+
- void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
- struct brcmf_mp_device *settings)
- {
-@@ -32,6 +62,8 @@ void brcmf_of_probe(struct device *dev,
- u32 irqf;
- u32 val;
-
-+ brcmf_of_probe_cc(dev, settings);
-+
- if (!np || bus_type != BRCMF_BUSTYPE_SDIO ||
- !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
- return;
+++ /dev/null
-brcmfmac: do not use internal roaming engine by default
-
-Some evidence of curing disconnects with this disabled, so make it a default.
-Can be overridden with module parameter roamoff=0
-See: http://projectable.me/optimize-my-pi-wi-fi/
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
-
---- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
-@@ -70,7 +70,11 @@ static int brcmf_fcmode;
- module_param_named(fcmode, brcmf_fcmode, int, 0);
- MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control");
-
-+#if defined(CONFIG_ARCH_BCM2835)
-+static int brcmf_roamoff = 1;
-+#else
- static int brcmf_roamoff;
-+#endif
- module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
- MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
-
+++ /dev/null
-From: Sven Eckelmann <sven@open-mesh.com>
-Date: Tue, 18 Nov 2014 12:29:28 +0100
-Subject: [PATCH] ath10k: Don't initialize devices asynchronously
-
-OpenWrt requires all PHYs to be initialized to create the configuration files
-during bootup. ath10k violates this because it delays the creation of the PHY
-to a not well defined point in the future.
-
-Forcing the work to be done immediately works around this problem but may also
-delay the boot when firmware images cannot be found.
-
-Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
----
-
---- a/drivers/net/wireless/ath/ath10k/core.c
-+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -2507,6 +2507,16 @@ int ath10k_core_register(struct ath10k *
- ar->chip_id = chip_id;
- queue_work(ar->workqueue, &ar->register_work);
-
-+ /* OpenWrt requires all PHYs to be initialized to create the
-+ * configuration files during bootup. ath10k violates this
-+ * because it delays the creation of the PHY to a not well defined
-+ * point in the future.
-+ *
-+ * Forcing the work to be done immediately works around this problem
-+ * but may also delay the boot when firmware images cannot be found.
-+ */
-+ flush_workqueue(ar->workqueue);
-+
- return 0;
- }
- EXPORT_SYMBOL(ath10k_core_register);
+++ /dev/null
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -8122,6 +8122,21 @@ static int ath10k_mac_init_rd(struct ath
- return 0;
- }
-
-+#ifdef CPTCFG_MAC80211_LEDS
-+static const struct ieee80211_tpt_blink ath10k_tpt_blink[] = {
-+ { .throughput = 0 * 1024, .blink_time = 334 },
-+ { .throughput = 1 * 1024, .blink_time = 260 },
-+ { .throughput = 2 * 1024, .blink_time = 220 },
-+ { .throughput = 5 * 1024, .blink_time = 190 },
-+ { .throughput = 10 * 1024, .blink_time = 170 },
-+ { .throughput = 25 * 1024, .blink_time = 150 },
-+ { .throughput = 54 * 1024, .blink_time = 130 },
-+ { .throughput = 120 * 1024, .blink_time = 110 },
-+ { .throughput = 265 * 1024, .blink_time = 80 },
-+ { .throughput = 586 * 1024, .blink_time = 50 },
-+};
-+#endif
-+
- int ath10k_mac_register(struct ath10k *ar)
- {
- static const u32 cipher_suites[] = {
-@@ -8397,6 +8412,12 @@ int ath10k_mac_register(struct ath10k *a
-
- wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
-
-+#ifdef CPTCFG_MAC80211_LEDS
-+ ieee80211_create_tpt_led_trigger(ar->hw,
-+ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink,
-+ ARRAY_SIZE(ath10k_tpt_blink));
-+#endif
-+
- ret = ieee80211_register_hw(ar->hw);
- if (ret) {
- ath10k_err(ar, "failed to register ieee80211: %d\n", ret);
+++ /dev/null
---- a/drivers/net/wireless/ath/ath10k/core.c
-+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -783,7 +783,7 @@ static int ath10k_core_get_board_id_from
- if (ret) {
- ath10k_err(ar, "could not execute otp for board id check: %d\n",
- ret);
-- return ret;
-+ return -EOPNOTSUPP;
- }
-
- board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP);
+++ /dev/null
---- a/drivers/net/wireless/marvell/mwl8k.c
-+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -6266,6 +6266,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:
-@@ -6299,8 +6301,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;
+++ /dev/null
-From 4628257bf3006c18e0037459922624f02a138aed Mon Sep 17 00:00:00 2001
-From: Weixiao Zhang <waveletboy@gmail.com>
-Date: Thu, 16 Nov 2017 01:59:55 -0600
-Subject: [PATCH] mwl8k: Expand non-DFS 5G channels
-
-Add non-DFS 5G upper channels (149-165) besides existed 4 lower channels
-(36, 40, 44, 48).
-
-Signed-off-by: Weixiao Zhang <waveletboy@gmail.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/marvell/mwl8k.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/marvell/mwl8k.c
-+++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -199,7 +199,7 @@ struct mwl8k_priv {
- struct ieee80211_channel channels_24[14];
- struct ieee80211_rate rates_24[13];
- struct ieee80211_supported_band band_50;
-- struct ieee80211_channel channels_50[4];
-+ struct ieee80211_channel channels_50[9];
- struct ieee80211_rate rates_50[8];
- u32 ap_macids_supported;
- u32 sta_macids_supported;
-@@ -383,6 +383,11 @@ static const struct ieee80211_channel mw
- { .band = NL80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, },
- { .band = NL80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, },
- { .band = NL80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, },
-+ { .band = NL80211_BAND_5GHZ, .center_freq = 5745, .hw_value = 149, },
-+ { .band = NL80211_BAND_5GHZ, .center_freq = 5765, .hw_value = 153, },
-+ { .band = NL80211_BAND_5GHZ, .center_freq = 5785, .hw_value = 157, },
-+ { .band = NL80211_BAND_5GHZ, .center_freq = 5805, .hw_value = 161, },
-+ { .band = NL80211_BAND_5GHZ, .center_freq = 5825, .hw_value = 165, },
- };
-
- static const struct ieee80211_rate mwl8k_rates_50[] = {
+++ /dev/null
---- a/drivers/net/wireless/ath/ath10k/htt.h
-+++ b/drivers/net/wireless/ath/ath10k/htt.h
-@@ -200,7 +200,7 @@ enum htt_rx_ring_flags {
- };
-
- #define HTT_RX_RING_SIZE_MIN 128
--#define HTT_RX_RING_SIZE_MAX 2048
-+#define HTT_RX_RING_SIZE_MAX 512
-
- struct htt_rx_ring_setup_ring {
- __le32 fw_idx_shadow_reg_paddr;
+++ /dev/null
---- a/drivers/net/wireless/ath/ath10k/pci.c
-+++ b/drivers/net/wireless/ath/ath10k/pci.c
-@@ -128,7 +128,7 @@ static struct ce_attr host_ce_config_wla
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
-- .dest_nentries = 512,
-+ .dest_nentries = 128,
- .recv_cb = ath10k_pci_htt_htc_rx_cb,
- },
-
-@@ -137,7 +137,7 @@ static struct ce_attr host_ce_config_wla
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
-- .dest_nentries = 128,
-+ .dest_nentries = 64,
- .recv_cb = ath10k_pci_htc_rx_cb,
- },
-
-@@ -164,7 +164,7 @@ static struct ce_attr host_ce_config_wla
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 512,
-- .dest_nentries = 512,
-+ .dest_nentries = 128,
- .recv_cb = ath10k_pci_htt_rx_cb,
- },
-
-@@ -189,7 +189,7 @@ static struct ce_attr host_ce_config_wla
- .flags = CE_ATTR_FLAGS,
- .src_nentries = 0,
- .src_sz_max = 2048,
-- .dest_nentries = 128,
-+ .dest_nentries = 96,
- .recv_cb = ath10k_pci_pktlog_rx_cb,
- },
-
+++ /dev/null
-From e6b3b2ed3d270b3c7080c9cf7d28636dc74b0387 Mon Sep 17 00:00:00 2001
-From: Amitkumar Karwar <amit.karwar@redpinesignals.com>
-Date: Wed, 1 Nov 2017 17:42:45 +0530
-Subject: rsi: fix kbuild reported build errors with CONFIG_PM off
-
-Some wowlan related code was outside CONFIG_PM flag which caused these
-build errors. They are fixed by moving that code under CONFIG_PM flag.
-
-Reported-by: kbuild test robot <fengguang.wu@intel.com>
-Fixes: ef71ed0608c ("rsi: sdio: Add WOWLAN support for S5 shutdown state")
-Fixes: a24e35fcee0 ("rsi: sdio: Add WOWLAN support for S4 hibernate state")
-Fixes: e1ced6422a3 ("rsi: sdio: add WOWLAN support for S3 suspend state")
-Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 5 ++++-
- drivers/net/wireless/rsi/rsi_91x_mgmt.c | 2 ++
- drivers/net/wireless/rsi/rsi_common.h | 2 ++
- drivers/net/wireless/rsi/rsi_mgmt.h | 2 ++
- 4 files changed, 10 insertions(+), 1 deletion(-)
-
---- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
-+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
-@@ -1752,6 +1752,7 @@ static int rsi_mac80211_cancel_roc(struc
- return 0;
- }
-
-+#ifdef CONFIG_PM
- static const struct wiphy_wowlan_support rsi_wowlan_support = {
- .flags = WIPHY_WOWLAN_ANY |
- WIPHY_WOWLAN_MAGIC_PKT |
-@@ -1824,7 +1825,6 @@ int rsi_config_wowlan(struct rsi_hw *ada
- }
- EXPORT_SYMBOL(rsi_config_wowlan);
-
--#ifdef CONFIG_PM
- static int rsi_mac80211_suspend(struct ieee80211_hw *hw,
- struct cfg80211_wowlan *wowlan)
- {
-@@ -1977,7 +1977,10 @@ int rsi_mac80211_attach(struct rsi_commo
- wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
- wiphy->reg_notifier = rsi_reg_notify;
-
-+#ifdef CONFIG_PM
- wiphy->wowlan = &rsi_wowlan_support;
-+#endif
-+
- wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
-
- /* Wi-Fi direct parameters */
---- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
-+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
-@@ -1597,6 +1597,7 @@ static int rsi_send_beacon(struct rsi_co
- return 0;
- }
-
-+#ifdef CONFIG_PM
- int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
- u16 sleep_status)
- {
-@@ -1630,6 +1631,7 @@ int rsi_send_wowlan_request(struct rsi_c
-
- return rsi_send_internal_mgmt_frame(common, skb);
- }
-+#endif
-
- /**
- * rsi_handle_ta_confirm_type() - This function handles the confirm frames.
---- a/drivers/net/wireless/rsi/rsi_common.h
-+++ b/drivers/net/wireless/rsi/rsi_common.h
-@@ -83,7 +83,9 @@ u16 rsi_get_connected_channel(struct iee
- struct rsi_hw *rsi_91x_init(void);
- void rsi_91x_deinit(struct rsi_hw *adapter);
- int rsi_read_pkt(struct rsi_common *common, s32 rcv_pkt_len);
-+#ifdef CONFIG_PM
- int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan);
-+#endif
- struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr);
- struct ieee80211_vif *rsi_get_vif(struct rsi_hw *adapter, u8 *mac);
- void rsi_roc_timeout(struct timer_list *t);
---- a/drivers/net/wireless/rsi/rsi_mgmt.h
-+++ b/drivers/net/wireless/rsi/rsi_mgmt.h
-@@ -668,8 +668,10 @@ int rsi_band_check(struct rsi_common *co
- int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word);
- int rsi_send_radio_params_update(struct rsi_common *common);
- int rsi_set_antenna(struct rsi_common *common, u8 antenna);
-+#ifdef CONFIG_PM
- int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
- u16 sleep_status);
-+#endif
- int rsi_send_ps_request(struct rsi_hw *adapter, bool enable,
- struct ieee80211_vif *vif);
- #endif
+++ /dev/null
-From 39f1332c526cd9d6de59a72520e8334e54b62cda Mon Sep 17 00:00:00 2001
-From: Amitkumar Karwar <amit.karwar@redpinesignals.com>
-Date: Wed, 1 Nov 2017 17:42:44 +0530
-Subject: rsi: move rsi_sdio_reinit_device() out of CONFIG_PM
-
-This function is generic. It doesn't contain wowlan specific code.
-It should not be under CONFIG_PM. This patch resolves compilation
-errors observed when CONFIG_PM flag is disabled.
-
-Reported-by: kbuild test robot <fengguang.wu@intel.com>
-Fixes: ef71ed0608c ("rsi: sdio: Add WOWLAN support for S5 shutdown state")
-Fixes: a24e35fcee0 ("rsi: sdio: Add WOWLAN support for S4 hibernate state")
-Fixes: e1ced6422a3 ("rsi: sdio: add WOWLAN support for S3 suspend state")
-Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com>
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
----
- drivers/net/wireless/rsi/rsi_91x_sdio.c | 52 ++++++++++++++++-----------------
- drivers/net/wireless/rsi/rsi_sdio.h | 1 -
- 2 files changed, 26 insertions(+), 27 deletions(-)
-
---- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
-+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
-@@ -871,6 +871,32 @@ fail:
- return status;
- }
-
-+static int rsi_sdio_reinit_device(struct rsi_hw *adapter)
-+{
-+ struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
-+ struct sdio_func *pfunction = sdev->pfunction;
-+ int ii;
-+
-+ for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
-+ skb_queue_purge(&adapter->priv->tx_queue[ii]);
-+
-+ /* Initialize device again */
-+ sdio_claim_host(pfunction);
-+
-+ sdio_release_irq(pfunction);
-+ rsi_reset_card(pfunction);
-+
-+ sdio_enable_func(pfunction);
-+ rsi_setupcard(adapter);
-+ rsi_init_sdio_slave_regs(adapter);
-+ sdio_claim_irq(pfunction, rsi_handle_interrupt);
-+ rsi_hal_device_init(adapter);
-+
-+ sdio_release_host(pfunction);
-+
-+ return 0;
-+}
-+
- static struct rsi_host_intf_ops sdio_host_intf_ops = {
- .write_pkt = rsi_sdio_host_intf_write_pkt,
- .read_pkt = rsi_sdio_host_intf_read_pkt,
-@@ -1281,32 +1307,6 @@ static void rsi_shutdown(struct device *
- rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n");
- }
-
--int rsi_sdio_reinit_device(struct rsi_hw *adapter)
--{
-- struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
-- struct sdio_func *pfunction = sdev->pfunction;
-- int ii;
--
-- for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
-- skb_queue_purge(&adapter->priv->tx_queue[ii]);
--
-- /* Initialize device again */
-- sdio_claim_host(pfunction);
--
-- sdio_release_irq(pfunction);
-- rsi_reset_card(pfunction);
--
-- sdio_enable_func(pfunction);
-- rsi_setupcard(adapter);
-- rsi_init_sdio_slave_regs(adapter);
-- sdio_claim_irq(pfunction, rsi_handle_interrupt);
-- rsi_hal_device_init(adapter);
--
-- sdio_release_host(pfunction);
--
-- return 0;
--}
--
- static int rsi_restore(struct device *dev)
- {
- struct sdio_func *pfunction = dev_to_sdio_func(dev);
---- a/drivers/net/wireless/rsi/rsi_sdio.h
-+++ b/drivers/net/wireless/rsi/rsi_sdio.h
-@@ -131,5 +131,4 @@ int rsi_sdio_master_access_msword(struct
- void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
- int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
- int rsi_sdio_check_buffer_status(struct rsi_hw *adapter, u8 q_num);
--int rsi_sdio_reinit_device(struct rsi_hw *adapter);
- #endif
+++ /dev/null
-From: Sebastian Gottschall <s.gottschall@dd-wrt.com>
-
-current handling of peer_bw_rxnss_override parameter is based on guessing the VHT160/8080 capability by rx rate. this is wrong and may lead
-to a non initialized peer_bw_rxnss_override parameter which is required since VHT160 operation mode only supports 2x2 chainmasks in addition the original code
-initialized the parameter with wrong masked values.
-This patch uses the peer phymode and peer nss information for correct initialisation of the peer_bw_rxnss_override parameter.
-if this peer information is not available, we initialize the parameter by minimum nss which is suggested by QCA as temporary workaround according
-to the QCA sourcecodes.
-
-Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
-
-v2: remove debug messages
-v3: apply some cosmetics, update documentation
-v4: fix compile warning and truncate nss to maximum of 2x2 since current chipsets only support 2x2 at vht160
-v5: handle maximum nss for chipsets supportig vht160 with 1x1 only
-v7: use more simple code variant and take care about hw/sw chainmask configuration
-v8: fix some code style issues
-v9: use SM/MS macros from code.h to simplify shift/mask handling
----
- drivers/net/wireless/ath/ath10k/mac.c | 54 +++++++++++++++++++--------
- drivers/net/wireless/ath/ath10k/wmi.c | 7 +---
- drivers/net/wireless/ath/ath10k/wmi.h | 14 ++++++-
- 3 files changed, 52 insertions(+), 23 deletions(-)
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -2466,7 +2466,7 @@ static void ath10k_peer_assoc_h_vht(stru
- const u16 *vht_mcs_mask;
- u8 ampdu_factor;
- u8 max_nss, vht_mcs;
-- int i;
-+ int i, nss160;
-
- if (WARN_ON(ath10k_mac_vif_chan(vif, &def)))
- return;
-@@ -2526,23 +2526,45 @@ static void ath10k_peer_assoc_h_vht(stru
- __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
- arg->peer_vht_rates.tx_mcs_set = ath10k_peer_assoc_h_vht_limit(
- __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask);
-+ arg->peer_bw_rxnss_override = 0;
-+ nss160 = 1; /* 1x1 default config for VHT160 */
-
-- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
-- sta->addr, arg->peer_max_mpdu, arg->peer_flags);
-+ /* only local 4x4 configuration do support 2x2 for VHT160,
-+ * everything else must use 1x1
-+ */
-
-- if (arg->peer_vht_rates.rx_max_rate &&
-- (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) {
-- switch (arg->peer_vht_rates.rx_max_rate) {
-- case 1560:
-- /* Must be 2x2 at 160Mhz is all it can do. */
-- arg->peer_bw_rxnss_override = 2;
-- break;
-- case 780:
-- /* Can only do 1x1 at 160Mhz (Long Guard Interval) */
-- arg->peer_bw_rxnss_override = 1;
-- break;
-- }
-+ if (ar->cfg_rx_chainmask == 15)
-+ nss160 = arg->peer_num_spatial_streams <= 2 ? 1 : 2;
-+
-+ /* if peer provides 1x1 nss160 information using max rate
-+ * vht information, we reduce local nss160 to 1x1.
-+ * consider that it has been observed that some client
-+ * devices provide zero here, no matter which transmission
-+ * rate is possible. in that case the local nss configuration
-+ * will be used at maxmimum configuration possible. (see above)
-+ */
-+
-+ if (arg->peer_vht_rates.rx_max_rate == 780)
-+ nss160 = 1;
-+
-+ /* in case if peer is connected with vht160 or vht80+80,
-+ * we need to properly adjust rxnss parameters otherwise
-+ * firmware will raise a assert
-+ */
-+ switch (arg->peer_phymode) {
-+ case MODE_11AC_VHT80_80:
-+ arg->peer_bw_rxnss_override = BW_NSS_FWCONF_80_80(nss160);
-+ /* fall through */
-+ case MODE_11AC_VHT160:
-+ arg->peer_bw_rxnss_override |= BW_NSS_FWCONF_160(nss160);
-+ break;
-+ default:
-+ break;
- }
-+
-+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x peer_bw_rxnss_override 0x%x\n",
-+ sta->addr, arg->peer_max_mpdu, arg->peer_flags,
-+ arg->peer_bw_rxnss_override);
- }
-
- static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
-@@ -2694,9 +2716,9 @@ static int ath10k_peer_assoc_prepare(str
- ath10k_peer_assoc_h_crypto(ar, vif, sta, arg);
- ath10k_peer_assoc_h_rates(ar, vif, sta, arg);
- ath10k_peer_assoc_h_ht(ar, vif, sta, arg);
-+ ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
- ath10k_peer_assoc_h_vht(ar, vif, sta, arg);
- ath10k_peer_assoc_h_qos(ar, vif, sta, arg);
-- ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
-
- return 0;
- }
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -7231,12 +7231,7 @@ ath10k_wmi_peer_assoc_fill_10_4(struct a
- struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
-
- ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
-- if (arg->peer_bw_rxnss_override)
-- cmd->peer_bw_rxnss_override =
-- __cpu_to_le32((arg->peer_bw_rxnss_override - 1) |
-- BIT(PEER_BW_RXNSS_OVERRIDE_OFFSET));
-- else
-- cmd->peer_bw_rxnss_override = 0;
-+ cmd->peer_bw_rxnss_override = __cpu_to_le32(arg->peer_bw_rxnss_override);
- }
-
- static int
---- a/drivers/net/wireless/ath/ath10k/wmi.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -6306,7 +6306,19 @@ struct wmi_10_2_peer_assoc_complete_cmd
- __le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
- } __packed;
-
--#define PEER_BW_RXNSS_OVERRIDE_OFFSET 31
-+#define BW_NSS_FWCONF_MAP_ENABLE BIT(31)
-+#define BW_NSS_FWCONF_MAP_160MHZ_LSB (0)
-+#define BW_NSS_FWCONF_MAP_160MHZ_MASK (0x00000007)
-+#define BW_NSS_FWCONF_MAP_80_80MHZ_LSB (3)
-+#define BW_NSS_FWCONF_MAP_80_80MHZ_MASK (0x00000038)
-+#define BW_NSS_FWCONF_MAP_MASK (0x0000003F)
-+
-+#define GET_BW_NSS_FWCONF_160(x) (MS(x, BW_NSS_FWCONF_MAP_160MHZ) + 1)
-+#define GET_BW_NSS_FWCONF_80_80(x) (MS(x, BW_NSS_FWCONF_MAP_80_80MHZ) + 1)
-+
-+/* Values defined to set 160 MHz Bandwidth NSS Mapping into FW*/
-+#define BW_NSS_FWCONF_160(x) (BW_NSS_FWCONF_MAP_ENABLE | SM(x - 1, BW_NSS_FWCONF_MAP_160MHZ))
-+#define BW_NSS_FWCONF_80_80(x) (BW_NSS_FWCONF_MAP_ENABLE | SM(x - 1, BW_NSS_FWCONF_MAP_80_80MHZ))
-
- struct wmi_10_4_peer_assoc_complete_cmd {
- struct wmi_10_2_peer_assoc_complete_cmd cmd;
+++ /dev/null
-From: Sebastian Gottschall <s.gottschall@dd-wrt.com>
-
-starting with firmware 10.4.3.4.x series QCA changed the handling of the channel property band_center_freq1 and band_center_freq2 in vht160 operation mode
-likelly for backward compatiblity with vht80 only capable clients.
-this patch adjusts the handling to get vht160 to work again with official qca firmwares newer than 3.3
-consider that this patch will not work with older firmwares anymore. to avoid undefined behaviour this we disable vht160 capability for outdated firmwares
-Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
-
-v2: fix trailing whitespace issue and fix some typos within the commit note
----
- drivers/net/wireless/ath/ath10k/mac.c | 7 -------
- drivers/net/wireless/ath/ath10k/wmi.c | 11 ++++++++---
- 2 files changed, 8 insertions(+), 10 deletions(-)
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -4445,13 +4445,6 @@ static struct ieee80211_sta_vht_cap ath1
- vht_cap.cap |= val;
- }
-
-- /* Currently the firmware seems to be buggy, don't enable 80+80
-- * mode until that's resolved.
-- */
-- if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) &&
-- (ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == 0)
-- vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
--
- mcs_map = 0;
- for (i = 0; i < 8; i++) {
- if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -1672,13 +1672,18 @@ void ath10k_wmi_put_wmi_channel(struct w
- flags |= WMI_CHAN_FLAG_HT40_PLUS;
- if (arg->chan_radar)
- flags |= WMI_CHAN_FLAG_DFS;
--
-+ ch->band_center_freq2 = 0;
- ch->mhz = __cpu_to_le32(arg->freq);
- ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
- if (arg->mode == MODE_11AC_VHT80_80)
- ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq2);
-- else
-- ch->band_center_freq2 = 0;
-+ if (arg->mode == MODE_11AC_VHT160) {
-+ if (arg->freq < arg->band_center_freq1)
-+ ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1 - 40);
-+ else
-+ ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1 + 40);
-+ ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq1);
-+ }
- ch->min_power = arg->min_power;
- ch->max_power = arg->max_power;
- ch->reg_power = arg->max_reg_power;
+++ /dev/null
-From: Sebastian Gottschall <s.gottschall@newmedia-net.de>
-
-Adds LED and GPIO Control support for 988x, 9887, 9888, 99x0, 9984 based
-chipsets with on chipset connected led's using WMI Firmware API. The LED
-device will get available named as "ath10k-phyX" at sysfs and can be controlled
-with various triggers. adds also debugfs interface for gpio control.
-
-This patch is specific for OpenWRt base, as is use old backported package
-with old wireless source. Support for QCA9984 is removed and a simbol
-is added to local-simbol file to export the actually compile the code
-with the ATH10K_LEDS simbol.
-
-
-Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
-Reviewed-by: Steve deRosier <derosier@cal-sierra.com>
-[kvalo: major reorg and cleanup]
-Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
----
-
-v13:
-
-* only compile tested!
-
-* fix all checkpatch warnings
-
-* fix commit log
-
-* sizeof(struct ath10k_gpiocontrol) -> sizeof(*gpio)
-
-* unsigned -> unsigned int
-
-* remove GPIOLIB code, that should be added in a separate patch
-
-* rename gpio.c to leds.c
-
-* add leds.h
-
-* rename some functions:
-
- ath10k_attach_led() -> ath10k_leds_register()
- ath10k_unregister_led() -> ath10k_leds_unregister()
- ath10k_reset_led_pin() -> ath10k_leds_start()
-
-* call ath10k_leds_unregister() before ath10k_thermal_unregister() to preserve ordering
-
-* call ath10k_leds_start() only from ath10k_core_start() and not from mac.c
-
-* rename struct ath10k_gpiocontrol as anonymous function under struct
- ath10k::leds, no need for memory allocation
-
-* merge ath10k_add_led() to ath10k_attach_led(), which is it's only caller
-
-* remove #if IS_ENABLED() checks from most of places, memory savings from those were not worth it
-
-* Kconfig help text improvement and move it lower in the menu, also don't enable it by default
-
-* switch to set_brightness_blocking() so that the callback can sleep,
- then no need to use ath10k_wmi_cmd_send_nowait() and can take mutex
- to access ar->state
-
-* don't touch ath10k_wmi_pdev_get_temperature()
-
-* as QCA6174/QCA9377 are not (yet) supported don't add the command to WMI-TLV interface
-
-* remove debugfs interface, that should be added in another patch
-
-* cleanup includes
-
-
- drivers/net/wireless/ath/ath10k/Kconfig | 10 +++
- drivers/net/wireless/ath/ath10k/Makefile | 1 +
- drivers/net/wireless/ath/ath10k/core.c | 22 +++++++
- drivers/net/wireless/ath/ath10k/core.h | 9 ++-
- drivers/net/wireless/ath/ath10k/hw.h | 1 +
- drivers/net/wireless/ath/ath10k/leds.c | 103 ++++++++++++++++++++++++++++++
- drivers/net/wireless/ath/ath10k/leds.h | 45 +++++++++++++
- drivers/net/wireless/ath/ath10k/mac.c | 1 +
- drivers/net/wireless/ath/ath10k/wmi-ops.h | 32 ++++++++++
- drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 +
- drivers/net/wireless/ath/ath10k/wmi.c | 54 ++++++++++++++++
- drivers/net/wireless/ath/ath10k/wmi.h | 35 ++++++++++
- 12 files changed, 314 insertions(+), 1 deletion(-)
- create mode 100644 drivers/net/wireless/ath/ath10k/leds.c
- create mode 100644 drivers/net/wireless/ath/ath10k/leds.h
---- a/drivers/net/wireless/ath/ath10k/Kconfig
-+++ b/drivers/net/wireless/ath/ath10k/Kconfig
-@@ -56,6 +56,16 @@ config ATH10K_DEBUGFS
-
- If unsure, say Y to make it easier to debug problems.
-
-+config ATH10K_LEDS
-+ bool "Atheros ath10k LED support"
-+ depends on ATH10K
-+ select MAC80211_LEDS
-+ select LEDS_CLASS
-+ select NEW_LEDS
-+ default y
-+ ---help---
-+ This option is necessary, if you want LED support for chipset connected led pins. If unsure, say N.
-+
- config ATH10K_SPECTRAL
- bool "Atheros ath10k spectral scan support"
- depends on ATH10K_DEBUGFS
---- a/drivers/net/wireless/ath/ath10k/Makefile
-+++ b/drivers/net/wireless/ath/ath10k/Makefile
-@@ -18,6 +18,7 @@ ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) +=
- ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o
- ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
- ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
-+ath10k_core-$(CPTCFG_ATH10K_LEDS) += leds.o
- ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o
- ath10k_core-$(CONFIG_PM) += wow.o
-
---- a/local-symbols
-+++ b/local-symbols
-@@ -144,6 +144,7 @@ ATH10K_DEBUG=
- ATH10K_DEBUGFS=
- ATH10K_SPECTRAL=
- ATH10K_THERMAL=
-+ATH10K_LEDS=
- ATH10K_TRACING=
- ATH10K_DFS_CERTIFIED=
- WCN36XX=
---- a/drivers/net/wireless/ath/ath10k/core.c
-+++ b/drivers/net/wireless/ath/ath10k/core.c
-@@ -32,6 +32,7 @@
- #include "htt.h"
- #include "testmode.h"
- #include "wmi-ops.h"
-+#include "leds.h"
-
- unsigned int ath10k_debug_mask;
- static unsigned int ath10k_cryptmode_param;
-@@ -56,6 +57,7 @@ static const struct ath10k_hw_params ath
- .id = QCA988X_HW_2_0_VERSION,
- .dev_id = QCA988X_2_0_DEVICE_ID,
- .name = "qca988x hw2.0",
-+ .led_pin = 1,
- .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
-@@ -81,6 +83,7 @@ static const struct ath10k_hw_params ath
- .id = QCA9887_HW_1_0_VERSION,
- .dev_id = QCA9887_1_0_DEVICE_ID,
- .name = "qca9887 hw1.0",
-+ .led_pin = 1,
- .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
-@@ -206,6 +209,7 @@ static const struct ath10k_hw_params ath
- .id = QCA99X0_HW_2_0_DEV_VERSION,
- .dev_id = QCA99X0_2_0_DEVICE_ID,
- .name = "qca99x0 hw2.0",
-+ .led_pin = 17,
- .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
- .otp_exe_param = 0x00000700,
-@@ -236,6 +240,7 @@ static const struct ath10k_hw_params ath
- .id = QCA9984_HW_1_0_DEV_VERSION,
- .dev_id = QCA9984_1_0_DEVICE_ID,
- .name = "qca9984/qca9994 hw1.0",
-+ .led_pin = 17,
- .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
-@@ -271,6 +276,7 @@ static const struct ath10k_hw_params ath
- .id = QCA9888_HW_2_0_DEV_VERSION,
- .dev_id = QCA9888_2_0_DEVICE_ID,
- .name = "qca9888 hw2.0",
-+ .led_pin = 17,
- .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
- .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
-@@ -2267,6 +2273,10 @@ int ath10k_core_start(struct ath10k *ar,
- if (status)
- goto err_hif_stop;
-
-+ status = ath10k_leds_start(ar);
-+ if (status)
-+ goto err_hif_stop;
-+
- return 0;
-
- err_hif_stop:
-@@ -2484,9 +2494,18 @@ static void ath10k_core_register_work(st
- goto err_spectral_destroy;
- }
-
-+ status = ath10k_leds_register(ar);
-+ if (status) {
-+ ath10k_err(ar, "could not register leds: %d\n",
-+ status);
-+ goto err_thermal_unregister;
-+ }
-+
- set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
- return;
-
-+err_thermal_unregister:
-+ ath10k_thermal_unregister(ar);
- err_spectral_destroy:
- ath10k_spectral_destroy(ar);
- err_debug_destroy:
-@@ -2528,6 +2547,8 @@ void ath10k_core_unregister(struct ath10
- if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
- return;
-
-+ ath10k_leds_unregister(ar);
-+
- ath10k_thermal_unregister(ar);
- /* Stop spectral before unregistering from mac80211 to remove the
- * relayfs debugfs file cleanly. Otherwise the parent debugfs tree
---- a/drivers/net/wireless/ath/ath10k/core.h
-+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -24,6 +24,7 @@
- #include <linux/pci.h>
- #include <linux/uuid.h>
- #include <linux/time.h>
-+#include <linux/leds.h>
-
- #include "htt.h"
- #include "htc.h"
-@@ -829,7 +830,6 @@ struct ath10k {
- u32 low_5ghz_chan;
- u32 high_5ghz_chan;
- bool ani_enabled;
--
- bool p2p;
-
- struct {
-@@ -1012,6 +1012,13 @@ struct ath10k {
- } testmode;
-
- struct {
-+ struct gpio_led wifi_led;
-+ struct led_classdev cdev;
-+ char label[48];
-+ u32 gpio_state_pin;
-+ } leds;
-+
-+ struct {
- /* protected by data_lock */
- u32 fw_crash_counter;
- u32 fw_warm_reset_counter;
---- a/drivers/net/wireless/ath/ath10k/hw.h
-+++ b/drivers/net/wireless/ath/ath10k/hw.h
-@@ -490,6 +490,7 @@ struct ath10k_hw_params {
- const char *name;
- u32 patch_load_addr;
- int uart_pin;
-+ int led_pin;
- u32 otp_exe_param;
-
- /* Type of hw cycle counter wraparound logic, for more info
---- /dev/null
-+++ b/drivers/net/wireless/ath/ath10k/leds.c
-@@ -0,0 +1,103 @@
-+/*
-+ * Copyright (c) 2005-2011 Atheros Communications Inc.
-+ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
-+ * Copyright (c) 2018 Sebastian Gottschall <s.gottschall@dd-wrt.com>
-+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+
-+#include <linux/leds.h>
-+
-+#include "core.h"
-+#include "wmi.h"
-+#include "wmi-ops.h"
-+
-+#include "leds.h"
-+
-+static int ath10k_leds_set_brightness_blocking(struct led_classdev *led_cdev,
-+ enum led_brightness brightness)
-+{
-+ struct ath10k *ar = container_of(led_cdev, struct ath10k,
-+ leds.cdev);
-+ struct gpio_led *led = &ar->leds.wifi_led;
-+
-+ mutex_lock(&ar->conf_mutex);
-+
-+ if (ar->state != ATH10K_STATE_ON)
-+ goto out;
-+
-+ ar->leds.gpio_state_pin = (brightness != LED_OFF) ^ led->active_low;
-+ ath10k_wmi_gpio_output(ar, led->gpio, ar->leds.gpio_state_pin);
-+
-+out:
-+ mutex_unlock(&ar->conf_mutex);
-+
-+ return 0;
-+}
-+
-+int ath10k_leds_start(struct ath10k *ar)
-+{
-+ if (ar->hw_params.led_pin == 0)
-+ /* leds not supported */
-+ return 0;
-+
-+ /* under some circumstances, the gpio pin gets reconfigured
-+ * to default state by the firmware, so we need to
-+ * reconfigure it this behaviour has only ben seen on
-+ * QCA9984 and QCA99XX devices so far
-+ */
-+ ath10k_wmi_gpio_config(ar, ar->hw_params.led_pin, 0,
-+ WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE);
-+ ath10k_wmi_gpio_output(ar, ar->hw_params.led_pin, 1);
-+
-+ return 0;
-+}
-+
-+int ath10k_leds_register(struct ath10k *ar)
-+{
-+ int ret;
-+
-+ if (ar->hw_params.led_pin == 0)
-+ /* leds not supported */
-+ return 0;
-+
-+ snprintf(ar->leds.label, sizeof(ar->leds.label), "ath10k-%s",
-+ wiphy_name(ar->hw->wiphy));
-+ ar->leds.wifi_led.active_low = 1;
-+ ar->leds.wifi_led.gpio = ar->hw_params.led_pin;
-+ ar->leds.wifi_led.name = ar->leds.label;
-+ ar->leds.wifi_led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
-+
-+ ar->leds.cdev.name = ar->leds.label;
-+ ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking;
-+
-+ /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */
-+ ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger;
-+
-+ ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev);
-+ if (ret)
-+ return ret;
-+
-+ return 0;
-+}
-+
-+void ath10k_leds_unregister(struct ath10k *ar)
-+{
-+ if (ar->hw_params.led_pin == 0)
-+ /* leds not supported */
-+ return;
-+
-+ led_classdev_unregister(&ar->leds.cdev);
-+}
-+
---- /dev/null
-+++ b/drivers/net/wireless/ath/ath10k/leds.h
-@@ -0,0 +1,41 @@
-+/*
-+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
-+ *
-+ * Permission to use, copy, modify, and/or distribute this software for any
-+ * purpose with or without fee is hereby granted, provided that the above
-+ * copyright notice and this permission notice appear in all copies.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-+ */
-+#ifndef _LEDS_H_
-+#define _LEDS_H_
-+
-+#include "core.h"
-+
-+#ifdef CPTCFG_ATH10K_LEDS
-+void ath10k_leds_unregister(struct ath10k *ar);
-+int ath10k_leds_start(struct ath10k *ar);
-+int ath10k_leds_register(struct ath10k *ar);
-+#else
-+static inline void ath10k_leds_unregister(struct ath10k *ar)
-+{
-+}
-+
-+static inline int ath10k_leds_start(struct ath10k *ar)
-+{
-+ return 0;
-+}
-+
-+static inline int ath10k_leds_register(struct ath10k *ar)
-+{
-+ return 0;
-+}
-+
-+#endif
-+#endif /* _LEDS_H_ */
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -32,6 +32,7 @@
- #include "wmi-tlv.h"
- #include "wmi-ops.h"
- #include "wow.h"
-+#include "leds.h"
-
- /*********/
- /* Rates */
---- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
-@@ -204,7 +204,10 @@ struct wmi_ops {
- struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value);
- struct sk_buff *(*gen_pdev_get_tpc_table_cmdid)(struct ath10k *ar,
- u32 param);
-+ struct sk_buff *(*gen_gpio_config)(struct ath10k *ar, u32 gpio_num,
-+ u32 input, u32 pull_type, u32 intr_mode);
-
-+ struct sk_buff *(*gen_gpio_output)(struct ath10k *ar, u32 gpio_num, u32 set);
- };
-
- int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
-@@ -969,6 +972,35 @@ ath10k_wmi_force_fw_hang(struct ath10k *
- return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid);
- }
-
-+static inline int ath10k_wmi_gpio_config(struct ath10k *ar, u32 gpio_num,
-+ u32 input, u32 pull_type, u32 intr_mode)
-+{
-+ struct sk_buff *skb;
-+
-+ if (!ar->wmi.ops->gen_gpio_config)
-+ return -EOPNOTSUPP;
-+
-+ skb = ar->wmi.ops->gen_gpio_config(ar, gpio_num, input, pull_type, intr_mode);
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_config_cmdid);
-+}
-+
-+static inline int ath10k_wmi_gpio_output(struct ath10k *ar, u32 gpio_num, u32 set)
-+{
-+ struct sk_buff *skb;
-+
-+ if (!ar->wmi.ops->gen_gpio_config)
-+ return -EOPNOTSUPP;
-+
-+ skb = ar->wmi.ops->gen_gpio_output(ar, gpio_num, set);
-+ if (IS_ERR(skb))
-+ return PTR_ERR(skb);
-+
-+ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_output_cmdid);
-+}
-+
- static inline int
- ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level)
- {
---- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
-@@ -3652,6 +3652,8 @@ static const struct wmi_ops wmi_tlv_ops
- .gen_echo = ath10k_wmi_tlv_op_gen_echo,
- .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
- .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
-+ /* .gen_gpio_config not implemented */
-+ /* .gen_gpio_output not implemented */
- };
-
- static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
---- a/drivers/net/wireless/ath/ath10k/wmi.c
-+++ b/drivers/net/wireless/ath/ath10k/wmi.c
-@@ -7051,6 +7051,49 @@ ath10k_wmi_op_gen_peer_set_param(struct
- return skb;
- }
-
-+static struct sk_buff *ath10k_wmi_op_gen_gpio_config(struct ath10k *ar,
-+ u32 gpio_num, u32 input,
-+ u32 pull_type, u32 intr_mode)
-+{
-+ struct wmi_gpio_config_cmd *cmd;
-+ struct sk_buff *skb;
-+
-+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ if (!skb)
-+ return ERR_PTR(-ENOMEM);
-+
-+ cmd = (struct wmi_gpio_config_cmd *)skb->data;
-+ cmd->pull_type = __cpu_to_le32(pull_type);
-+ cmd->gpio_num = __cpu_to_le32(gpio_num);
-+ cmd->input = __cpu_to_le32(input);
-+ cmd->intr_mode = __cpu_to_le32(intr_mode);
-+
-+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_config gpio_num 0x%08x input 0x%08x pull_type 0x%08x intr_mode 0x%08x\n",
-+ gpio_num, input, pull_type, intr_mode);
-+
-+ return skb;
-+}
-+
-+static struct sk_buff *ath10k_wmi_op_gen_gpio_output(struct ath10k *ar,
-+ u32 gpio_num, u32 set)
-+{
-+ struct wmi_gpio_output_cmd *cmd;
-+ struct sk_buff *skb;
-+
-+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
-+ if (!skb)
-+ return ERR_PTR(-ENOMEM);
-+
-+ cmd = (struct wmi_gpio_output_cmd *)skb->data;
-+ cmd->gpio_num = __cpu_to_le32(gpio_num);
-+ cmd->set = __cpu_to_le32(set);
-+
-+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_output gpio_num 0x%08x set 0x%08x\n",
-+ gpio_num, set);
-+
-+ return skb;
-+}
-+
- static struct sk_buff *
- ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
- enum wmi_sta_ps_mode psmode)
-@@ -8596,6 +8639,9 @@ static const struct wmi_ops wmi_ops = {
- .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
- .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
- .gen_echo = ath10k_wmi_op_gen_echo,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
-+
- /* .gen_bcn_tmpl not implemented */
- /* .gen_prb_tmpl not implemented */
- /* .gen_p2p_go_bcn_ie not implemented */
-@@ -8666,6 +8712,8 @@ static const struct wmi_ops wmi_10_1_ops
- .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
- .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
- .gen_echo = ath10k_wmi_op_gen_echo,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
- /* .gen_bcn_tmpl not implemented */
- /* .gen_prb_tmpl not implemented */
- /* .gen_p2p_go_bcn_ie not implemented */
-@@ -8737,6 +8785,8 @@ static const struct wmi_ops wmi_10_2_ops
- .gen_delba_send = ath10k_wmi_op_gen_delba_send,
- .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
- .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
- /* .gen_pdev_enable_adaptive_cca not implemented */
- };
-
-@@ -8807,6 +8857,8 @@ static const struct wmi_ops wmi_10_2_4_o
- .gen_pdev_enable_adaptive_cca =
- ath10k_wmi_op_gen_pdev_enable_adaptive_cca,
- .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
- /* .gen_bcn_tmpl not implemented */
- /* .gen_prb_tmpl not implemented */
- /* .gen_p2p_go_bcn_ie not implemented */
-@@ -8886,6 +8938,8 @@ static const struct wmi_ops wmi_10_4_ops
- .gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
- .gen_echo = ath10k_wmi_op_gen_echo,
- .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
-+ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
-+ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
- };
-
- int ath10k_wmi_attach(struct ath10k *ar)
---- a/drivers/net/wireless/ath/ath10k/wmi.h
-+++ b/drivers/net/wireless/ath/ath10k/wmi.h
-@@ -2930,6 +2930,41 @@ enum wmi_10_4_feature_mask {
-
- };
-
-+/* WMI_GPIO_CONFIG_CMDID */
-+enum {
-+ WMI_GPIO_PULL_NONE,
-+ WMI_GPIO_PULL_UP,
-+ WMI_GPIO_PULL_DOWN,
-+};
-+
-+enum {
-+ WMI_GPIO_INTTYPE_DISABLE,
-+ WMI_GPIO_INTTYPE_RISING_EDGE,
-+ WMI_GPIO_INTTYPE_FALLING_EDGE,
-+ WMI_GPIO_INTTYPE_BOTH_EDGE,
-+ WMI_GPIO_INTTYPE_LEVEL_LOW,
-+ WMI_GPIO_INTTYPE_LEVEL_HIGH
-+};
-+
-+/* WMI_GPIO_CONFIG_CMDID */
-+struct wmi_gpio_config_cmd {
-+ __le32 gpio_num; /* GPIO number to be setup */
-+ __le32 input; /* 0 - Output/ 1 - Input */
-+ __le32 pull_type; /* Pull type defined above */
-+ __le32 intr_mode; /* Interrupt mode defined above (Input) */
-+} __packed;
-+
-+/* WMI_GPIO_OUTPUT_CMDID */
-+struct wmi_gpio_output_cmd {
-+ __le32 gpio_num; /* GPIO number to be setup */
-+ __le32 set; /* Set the GPIO pin*/
-+} __packed;
-+
-+/* WMI_GPIO_INPUT_EVENTID */
-+struct wmi_gpio_input_event {
-+ __le32 gpio_num; /* GPIO number which changed state */
-+} __packed;
-+
- struct wmi_ext_resource_config_10_4_cmd {
- /* contains enum wmi_host_platform_type */
- __le32 host_platform_config;
+++ /dev/null
-From 79c9d7aabae1d1da9eea97d83b61e1517a8a2221 Mon Sep 17 00:00:00 2001
-From: Mathias Kresin <dev@kresin.me>
-Date: Fri, 22 Jun 2018 18:59:44 +0200
-Subject: [PATCH] ath10k: use tpt LED trigger by default
-
-Use the tpt LED trigger for each created phy led. Ths way LEDs attached
-to the ath10k GPIO pins are indicating the phy status and blink on
-traffic.
-
-Signed-off-by: Mathias Kresin <dev@kresin.me>
----
- drivers/net/wireless/ath/ath10k/core.h | 4 ++++
- drivers/net/wireless/ath/ath10k/leds.c | 4 +---
- drivers/net/wireless/ath/ath10k/mac.c | 2 +-
- 3 files changed, 6 insertions(+), 4 deletions(-)
-
---- a/drivers/net/wireless/ath/ath10k/core.h
-+++ b/drivers/net/wireless/ath/ath10k/core.h
-@@ -1055,6 +1055,10 @@ struct ath10k {
- struct ath10k_radar_found_info last_radar_info;
- struct work_struct radar_confirmation_work;
-
-+#ifdef CPTCFG_MAC80211_LEDS
-+ const char *led_default_trigger;
-+#endif
-+
- /* must be last */
- u8 drv_priv[0] __aligned(sizeof(void *));
- };
---- a/drivers/net/wireless/ath/ath10k/leds.c
-+++ b/drivers/net/wireless/ath/ath10k/leds.c
-@@ -81,9 +81,7 @@ int ath10k_leds_register(struct ath10k *
-
- ar->leds.cdev.name = ar->leds.label;
- ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking;
--
-- /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */
-- ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger;
-+ ar->leds.cdev.default_trigger = ar->led_default_trigger;
-
- ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev);
- if (ret)
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -8429,7 +8429,7 @@ int ath10k_mac_register(struct ath10k *a
- wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
-
- #ifdef CPTCFG_MAC80211_LEDS
-- ieee80211_create_tpt_led_trigger(ar->hw,
-+ ar->led_default_trigger = ieee80211_create_tpt_led_trigger(ar->hw,
- IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink,
- ARRAY_SIZE(ath10k_tpt_blink));
- #endif
+++ /dev/null
-From bbf0a8af2261bc7ae39b227ff6a1e9f45a008c27 Mon Sep 17 00:00:00 2001
-From: Sven Eckelmann <sven.eckelmann@openmesh.com>
-Date: Mon, 30 Jul 2018 17:31:41 +0200
-Subject: [PATCH] ath10k: Limit available channels via DT ieee80211-freq-limit
-
-Tri-band devices (1x 2.4GHz + 2x 5GHz) often incorporate special filters in
-the RX and TX path. These filtered channel can in theory still be used by
-the hardware but the signal strength is reduced so much that it makes no
-sense.
-
-There is already a DT property to limit the available channels but ath10k
-has to manually call this functionality to limit the currrently set wiphy
-channels further.
-
-Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
-
-Forwarded: https://patchwork.kernel.org/patch/10549245/
----
- drivers/net/wireless/ath/ath10k/mac.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/drivers/net/wireless/ath/ath10k/mac.c
-+++ b/drivers/net/wireless/ath/ath10k/mac.c
-@@ -17,6 +17,7 @@
-
- #include "mac.h"
-
-+#include <net/cfg80211.h>
- #include <net/mac80211.h>
- #include <linux/etherdevice.h>
- #include <linux/acpi.h>
-@@ -8230,6 +8231,7 @@ int ath10k_mac_register(struct ath10k *a
- ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band;
- }
-
-+ wiphy_read_of_freq_limits(ar->hw->wiphy);
- ath10k_mac_setup_ht_vht_cap(ar);
-
- ar->hw->wiphy->interface_modes =
--- /dev/null
+--- a/drivers/net/wireless/ath/Kconfig
++++ b/drivers/net/wireless/ath/Kconfig
+@@ -1,5 +1,5 @@
+ config ATH_COMMON
+- tristate
++ tristate "ath.ko"
+ depends on m
+
+ config WLAN_VENDOR_ATH
--- /dev/null
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/Kconfig
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/Kconfig
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/Kconfig
+@@ -85,6 +85,12 @@ config ATH10K_TRACING
+ ---help---
+ Select this to ath10k use tracing infrastructure.
+
++config ATH10K_THERMAL
++ bool "Atheros ath10k thermal monitoring support"
++ depends on THERMAL
++ ---help---
++ Select this to ath10k use hwmon for thermal measurement.
++
+ config ATH10K_DFS_CERTIFIED
+ bool "Atheros DFS support for certified platforms"
+ depends on ATH10K && CFG80211_CERTIFICATION_ONUS
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/Makefile
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/Makefile
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/Makefile
+@@ -18,7 +18,7 @@ ath10k_core-y += mac.o \
+ ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) += spectral.o
+ ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o
+ ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
+-ath10k_core-$(CONFIG_THERMAL) += thermal.o
++ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
+ ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o
+ ath10k_core-$(CONFIG_PM) += wow.o
+ ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/thermal.h
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/thermal.h
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/thermal.h
+@@ -36,7 +36,7 @@ struct ath10k_thermal {
+ int temperature;
+ };
+
+-#if IS_REACHABLE(CONFIG_THERMAL)
++#if IS_REACHABLE(CPTCFG_ATH10K_THERMAL)
+ int ath10k_thermal_register(struct ath10k *ar);
+ void ath10k_thermal_unregister(struct ath10k *ar);
+ void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
+Index: backports-v4.18-rc7/local-symbols
+===================================================================
+--- backports-v4.18-rc7.orig/local-symbols
++++ backports-v4.18-rc7/local-symbols
+@@ -144,6 +144,7 @@ ATH10K_SNOC=
+ ATH10K_DEBUG=
+ ATH10K_DEBUGFS=
+ ATH10K_SPECTRAL=
++ATH10K_THERMAL=
+ ATH10K_TRACING=
+ ATH10K_DFS_CERTIFIED=
+ WCN36XX=
--- /dev/null
+--- a/drivers/net/wireless/ath/ath5k/initvals.c
++++ b/drivers/net/wireless/ath/ath5k/initvals.c
+@@ -62,8 +62,14 @@ static const struct ath5k_ini ar5210_ini
+ { AR5K_IMR, 0 },
+ { AR5K_IER, AR5K_IER_DISABLE },
+ { AR5K_BSR, 0, AR5K_INI_READ },
++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
+ { AR5K_RXCFG, AR5K_DMASIZE_128B },
++#else
++ /* WAR for AR71xx PCI bug */
++ { AR5K_TXCFG, AR5K_DMASIZE_128B },
++ { AR5K_RXCFG, AR5K_DMASIZE_4B },
++#endif
+ { AR5K_CFG, AR5K_INIT_CFG },
+ { AR5K_TOPS, 8 },
+ { AR5K_RXNOFRM, 8 },
+--- a/drivers/net/wireless/ath/ath5k/dma.c
++++ b/drivers/net/wireless/ath/ath5k/dma.c
+@@ -869,10 +869,18 @@ ath5k_hw_dma_init(struct ath5k_hw *ah)
+ * guess we can tweak it and see how it goes ;-)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
++#if !defined(CONFIG_ATHEROS_AR71XX) && !defined(CONFIG_ATH79)
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
+ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B);
++#else
++ /* WAR for AR71xx PCI bug */
++ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
++ AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B);
++ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG,
++ AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_4B);
++#endif
+ }
+
+ /* Pre-enable interrupts on 5211/5212*/
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sat, 9 Jul 2016 15:25:24 +0200
+Subject: [PATCH] ath9k_hw: reset AHB-WMAC interface on AR91xx
+
+Should fix a few stability issues
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1394,8 +1394,12 @@ static bool ath9k_hw_set_reset(struct at
+ if (!AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_RC, 0);
+
+- if (AR_SREV_9100(ah))
++ if (AR_SREV_9100(ah)) {
++ /* Reset the AHB-WMAC interface */
++ if (ah->external_reset)
++ ah->external_reset();
+ udelay(50);
++ }
+
+ return true;
+ }
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sat, 9 Jul 2016 15:26:44 +0200
+Subject: [PATCH] ath9k_hw: issue external reset for QCA955x
+
+The RTC interface on the SoC needs to be reset along with the rest of
+the WMAC.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1271,39 +1271,56 @@ void ath9k_hw_get_delta_slope_vals(struc
+ *coef_exponent = coef_exp - 16;
+ }
+
+-/* AR9330 WAR:
+- * call external reset function to reset WMAC if:
+- * - doing a cold reset
+- * - we have pending frames in the TX queues.
+- */
+-static bool ath9k_hw_ar9330_reset_war(struct ath_hw *ah, int type)
++static bool ath9k_hw_need_external_reset(struct ath_hw *ah, int type)
+ {
+- int i, npend = 0;
++ int i;
+
+- for (i = 0; i < AR_NUM_QCU; i++) {
+- npend = ath9k_hw_numtxpending(ah, i);
+- if (npend)
+- break;
+- }
+-
+- if (ah->external_reset &&
+- (npend || type == ATH9K_RESET_COLD)) {
+- int reset_err = 0;
+-
+- ath_dbg(ath9k_hw_common(ah), RESET,
+- "reset MAC via external reset\n");
+-
+- reset_err = ah->external_reset();
+- if (reset_err) {
+- ath_err(ath9k_hw_common(ah),
+- "External reset failed, err=%d\n",
+- reset_err);
+- return false;
++ if (type == ATH9K_RESET_COLD)
++ return true;
++
++ if (AR_SREV_9550(ah))
++ return true;
++
++ /* AR9330 WAR:
++ * call external reset function to reset WMAC if:
++ * - doing a cold reset
++ * - we have pending frames in the TX queues.
++ */
++ if (AR_SREV_9330(ah)) {
++ for (i = 0; i < AR_NUM_QCU; i++) {
++ if (ath9k_hw_numtxpending(ah, i))
++ return true;
+ }
++ }
++
++ return false;
++}
++
++static bool ath9k_hw_external_reset(struct ath_hw *ah, int type)
++{
++ int err;
++
++ if (!ah->external_reset || !ath9k_hw_need_external_reset(ah, type))
++ return true;
++
++ ath_dbg(ath9k_hw_common(ah), RESET,
++ "reset MAC via external reset\n");
+
+- REG_WRITE(ah, AR_RTC_RESET, 1);
++ err = ah->external_reset();
++ if (err) {
++ ath_err(ath9k_hw_common(ah),
++ "External reset failed, err=%d\n", err);
++ return false;
+ }
+
++ if (AR_SREV_9550(ah)) {
++ REG_WRITE(ah, AR_RTC_RESET, 0);
++ udelay(10);
++ }
++
++ REG_WRITE(ah, AR_RTC_RESET, 1);
++ udelay(10);
++
+ return true;
+ }
+
+@@ -1356,24 +1373,24 @@ static bool ath9k_hw_set_reset(struct at
+ rst_flags |= AR_RTC_RC_MAC_COLD;
+ }
+
+- if (AR_SREV_9330(ah)) {
+- if (!ath9k_hw_ar9330_reset_war(ah, type))
+- return false;
+- }
+-
+ if (ath9k_hw_mci_is_enabled(ah))
+ ar9003_mci_check_gpm_offset(ah);
+
+ /* DMA HALT added to resolve ar9300 and ar9580 bus error during
+- * RTC_RC reg read
++ * RTC_RC reg read. Also needed for AR9550 external reset
+ */
+- if (AR_SREV_9300(ah) || AR_SREV_9580(ah)) {
++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
+ REG_SET_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
+ ath9k_hw_wait(ah, AR_CFG, AR_CFG_HALT_ACK, AR_CFG_HALT_ACK,
+ 20 * AH_WAIT_TIMEOUT);
+- REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
+ }
+
++ if (!AR_SREV_9100(ah))
++ ath9k_hw_external_reset(ah, type);
++
++ if (AR_SREV_9300(ah) || AR_SREV_9580(ah))
++ REG_CLR_BIT(ah, AR_CFG, AR_CFG_HALT_REQ);
++
+ REG_WRITE(ah, AR_RTC_RC, rst_flags);
+
+ REGWRITE_BUFFER_FLUSH(ah);
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 11 Jul 2016 12:07:40 +0200
+Subject: [PATCH] ath9k_hw: set spectral scan enable bit on trigger for
+ AR9003+
+
+AR9002 code and QCA AR9003+ code do the same.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -1800,6 +1800,8 @@ static void ar9003_hw_spectral_scan_conf
+
+ static void ar9003_hw_spectral_scan_trigger(struct ath_hw *ah)
+ {
++ REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
++ AR_PHY_SPECTRAL_SCAN_ENABLE);
+ /* Activate spectral scan */
+ REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
+ AR_PHY_SPECTRAL_SCAN_ACTIVE);
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 27 Dec 2016 23:16:23 +0100
+Subject: [PATCH] ath9k: don't run periodic and nf calibation at the same
+ time
+
+The checks already prevents periodic cal from being started while noise
+floor calibration runs. It is missing checks for the other way around.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+@@ -676,10 +676,10 @@ static int ar9002_hw_calibrate(struct at
+ return 0;
+
+ ah->cal_list_curr = currCal = currCal->calNext;
+- if (currCal->calState == CAL_WAITING) {
++ if (currCal->calState == CAL_WAITING)
+ ath9k_hw_reset_calibration(ah, currCal);
+- return 0;
+- }
++
++ return 0;
+ }
+
+ /* Do NF cal only at longer intervals */
--- /dev/null
+From: Felix Fietkau <nbd@openwrt.org>
+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. Don't use rx_clear in TX99 mode.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/mac.c
++++ b/drivers/net/wireless/ath/ath9k/mac.c
+@@ -678,13 +678,18 @@ 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);
++ u32 reg = AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT;
++
++ if (!IS_ENABLED(CPTCFG_ATH9K_TX99))
++ reg |= AR_DIAG_FORCE_RX_CLEAR;
++ REG_SET_BIT(ah, AR_DIAG_SW, reg);
+
+ ath9k_hw_disable_mib_counters(ah);
+ }
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sat, 14 May 2016 14:51:02 +0200
+Subject: [PATCH] Revert "ath9k: interpret requested txpower in EIRP
+ domain"
+
+This reverts commit 71f5137bf010c6faffab50c0ec15374c59c4a411.
+---
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2935,7 +2935,8 @@ void ath9k_hw_apply_txpower(struct ath_h
+ {
+ struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+ struct ieee80211_channel *channel;
+- int chan_pwr, new_pwr;
++ int chan_pwr, new_pwr, max_gain;
++ int ant_gain, ant_reduction = 0;
+
+ if (!chan)
+ return;
+@@ -2943,10 +2944,15 @@ void ath9k_hw_apply_txpower(struct ath_h
+ channel = chan->chan;
+ chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
+ new_pwr = min_t(int, chan_pwr, reg->power_limit);
++ max_gain = chan_pwr - new_pwr + channel->max_antenna_gain * 2;
++
++ ant_gain = get_antenna_gain(ah, chan);
++ if (ant_gain > max_gain)
++ ant_reduction = ant_gain - max_gain;
+
+ ah->eep_ops->set_txpower(ah, chan,
+ ath9k_regd_get_ctl(reg, chan),
+- get_antenna_gain(ah, chan), new_pwr, test);
++ ant_reduction, new_pwr, test);
+ }
+
+ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sun, 28 Aug 2016 13:13:01 +0200
+Subject: [PATCH] ath9k: fix moredata bit in PS buffered frame release
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1659,6 +1659,22 @@ void ath_tx_aggr_wakeup(struct ath_softc
+ }
+ }
+
++
++static void
++ath9k_set_moredata(struct ath_softc *sc, struct ath_buf *bf, bool val)
++{
++ struct ieee80211_hdr *hdr;
++ u16 mask = cpu_to_le16(IEEE80211_FCTL_MOREDATA);
++ u16 mask_val = mask * val;
++
++ hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
++ if ((hdr->frame_control & mask) != mask_val) {
++ hdr->frame_control = (hdr->frame_control & ~mask) | mask_val;
++ dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
++ sizeof(*hdr), DMA_TO_DEVICE);
++ }
++}
++
+ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ u16 tids, int nframes,
+@@ -1689,6 +1705,7 @@ void ath9k_release_buffered_frames(struc
+ if (!bf)
+ break;
+
++ ath9k_set_moredata(sc, bf, true);
+ list_add_tail(&bf->list, &bf_q);
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
+ if (bf_isampdu(bf)) {
+@@ -1712,6 +1729,9 @@ void ath9k_release_buffered_frames(struc
+ if (list_empty(&bf_q))
+ return;
+
++ if (!more_data)
++ ath9k_set_moredata(sc, bf_tail, false);
++
+ info = IEEE80211_SKB_CB(bf_tail->bf_mpdu);
+ info->flags |= IEEE80211_TX_STATUS_EOSP;
+
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sun, 28 Aug 2016 13:13:42 +0200
+Subject: [PATCH] ath9k: clear potentially stale EOSP status bit in
+ intermediate queues
+
+Prevents spurious ieee80211_sta_eosp calls.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -969,7 +969,8 @@ ath_tx_get_tid_subframe(struct ath_softc
+ bf->bf_lastbf = bf;
+
+ tx_info = IEEE80211_SKB_CB(skb);
+- tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
++ tx_info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT |
++ IEEE80211_TX_STATUS_EOSP);
+
+ /*
+ * No aggregation session is running, but there may be frames
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sun, 28 Aug 2016 13:23:27 +0200
+Subject: [PATCH] ath9k: report tx status on EOSP
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -86,7 +86,8 @@ static void ath_tx_status(struct ieee802
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_sta *sta = info->status.status_driver_data[0];
+
+- if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
++ if (info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
++ IEEE80211_TX_STATUS_EOSP)) {
+ ieee80211_tx_status(hw, skb);
+ return;
+ }
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Tue, 30 Aug 2016 12:44:08 +0200
+Subject: [PATCH] ath9k: fix block-ack window tracking issues
+
+Ensure that a buffer gets tracked as part of the block-ack window as
+soon as it's dequeued from the tid for the first time. Ensure that
+double calls to ath_tx_addto_baw (e.g. on retransmission) don't cause
+any issues.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -62,7 +62,7 @@ static void ath_tx_rc_status(struct ath_
+ struct ath_tx_status *ts, int nframes, int nbad,
+ int txok);
+ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+- int seqno);
++ struct ath_buf *bf);
+ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc,
+ struct ath_txq *txq,
+ struct ath_atx_tid *tid,
+@@ -296,7 +296,7 @@ static void ath_tx_flush_tid(struct ath_
+ }
+
+ if (fi->baw_tracked) {
+- ath_tx_update_baw(sc, tid, bf->bf_state.seqno);
++ ath_tx_update_baw(sc, tid, bf);
+ sendbar = true;
+ }
+
+@@ -312,10 +312,15 @@ static void ath_tx_flush_tid(struct ath_
+ }
+
+ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+- int seqno)
++ struct ath_buf *bf)
+ {
++ struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu);
++ u16 seqno = bf->bf_state.seqno;
+ int index, cindex;
+
++ if (!fi->baw_tracked)
++ return;
++
+ index = ATH_BA_INDEX(tid->seq_start, seqno);
+ cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+
+@@ -336,6 +341,9 @@ static void ath_tx_addto_baw(struct ath_
+ u16 seqno = bf->bf_state.seqno;
+ int index, cindex;
+
++ if (fi->baw_tracked)
++ return;
++
+ index = ATH_BA_INDEX(tid->seq_start, seqno);
+ cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
+ __set_bit(cindex, tid->tx_buf);
+@@ -612,7 +620,7 @@ static void ath_tx_complete_aggr(struct
+ * complete the acked-ones/xretried ones; update
+ * block-ack window
+ */
+- ath_tx_update_baw(sc, tid, seqno);
++ ath_tx_update_baw(sc, tid, bf);
+
+ if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+ memcpy(tx_info->control.rates, rates, sizeof(rates));
+@@ -642,7 +650,7 @@ static void ath_tx_complete_aggr(struct
+ * run out of tx buf.
+ */
+ if (!tbf) {
+- ath_tx_update_baw(sc, tid, seqno);
++ ath_tx_update_baw(sc, tid, bf);
+
+ ath_tx_complete_buf(sc, bf, txq,
+ &bf_head, NULL, ts,
+@@ -1011,11 +1019,14 @@ ath_tx_get_tid_subframe(struct ath_softc
+
+ INIT_LIST_HEAD(&bf_head);
+ list_add(&bf->list, &bf_head);
+- ath_tx_update_baw(sc, tid, seqno);
++ ath_tx_update_baw(sc, tid, bf);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, NULL, &ts, 0);
+ continue;
+ }
+
++ if (bf_isampdu(bf))
++ ath_tx_addto_baw(sc, tid, bf);
++
+ return bf;
+ }
+
+@@ -1073,8 +1084,6 @@ ath_tx_form_aggr(struct ath_softc *sc, s
+ bf->bf_next = NULL;
+
+ /* link buffers of this frame to the aggregate */
+- if (!fi->baw_tracked)
+- ath_tx_addto_baw(sc, tid, bf);
+ bf->bf_state.ndelim = ndelim;
+
+ list_add_tail(&bf->list, bf_q);
+@@ -1710,10 +1719,8 @@ void ath9k_release_buffered_frames(struc
+ ath9k_set_moredata(sc, bf, true);
+ list_add_tail(&bf->list, &bf_q);
+ ath_set_rates(tid->an->vif, tid->an->sta, bf);
+- if (bf_isampdu(bf)) {
+- ath_tx_addto_baw(sc, tid, bf);
++ if (bf_isampdu(bf))
+ bf->bf_state.bf_type &= ~BUF_AGGR;
+- }
+ if (bf_tail)
+ bf_tail->bf_next = bf;
+
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Wed, 22 Mar 2017 20:37:04 +0100
+Subject: [PATCH] ath9k_hw: fix channel maximum power level test
+
+The tx power applied by set_txpower is limited by the CTL (conformance
+test limit) entries in the EEPROM. These can change based on the user
+configured regulatory domain.
+Depending on the EEPROM data this can cause the tx power to become too
+limited, if the original regdomain CTLs impose lowr limits than the CTLs
+of the user configured regdomain.
+
+To fix this issue, set the initial channel limits without any CTL
+restrictions and only apply the CTL at run time when setting the channel
+and the real tx power.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2937,10 +2937,14 @@ void ath9k_hw_apply_txpower(struct ath_h
+ struct ieee80211_channel *channel;
+ int chan_pwr, new_pwr, max_gain;
+ int ant_gain, ant_reduction = 0;
++ u16 ctl = NO_CTL;
+
+ if (!chan)
+ return;
+
++ if (!test)
++ ctl = ath9k_regd_get_ctl(reg, chan);
++
+ channel = chan->chan;
+ chan_pwr = min_t(int, channel->max_power * 2, MAX_RATE_POWER);
+ new_pwr = min_t(int, chan_pwr, reg->power_limit);
+@@ -2950,9 +2954,7 @@ void ath9k_hw_apply_txpower(struct ath_h
+ if (ant_gain > max_gain)
+ ant_reduction = ant_gain - max_gain;
+
+- ah->eep_ops->set_txpower(ah, chan,
+- ath9k_regd_get_ctl(reg, chan),
+- ant_reduction, new_pwr, test);
++ ah->eep_ops->set_txpower(ah, chan, ctl, ant_reduction, new_pwr, test);
+ }
+
+ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Wed, 19 Jul 2017 08:49:31 +0200
+Subject: [PATCH] ath9k: adjust tx power reduction for US regulatory
+ domain
+
+FCC regulatory rules allow for up to 3 dBi antenna gain. Account for
+this in the EEPROM based tx power reduction code.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -2954,6 +2954,10 @@ void ath9k_hw_apply_txpower(struct ath_h
+ if (ant_gain > max_gain)
+ ant_reduction = ant_gain - max_gain;
+
++ /* FCC allows maximum antenna gain of 3 dBi */
++ if (reg->region == NL80211_DFS_FCC)
++ ant_reduction = max_t(int, ant_reduction - 6, 0);
++
+ ah->eep_ops->set_txpower(ah, chan, ctl, ant_reduction, new_pwr, test);
+ }
+
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sun, 23 Jul 2017 14:58:22 +0200
+Subject: [PATCH] ath9k: fix more-data flag for buffered multicast
+ packets
+
+The flag needs to be cleared for the last packet in the list, not the
+first one. Fixes some issues with multicast packet loss for powersave
+clients connected to an ath9k AP.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -2436,7 +2436,6 @@ void ath_tx_cabq(struct ieee80211_hw *hw
+ .txq = sc->beacon.cabq
+ };
+ struct ath_tx_info info = {};
+- struct ieee80211_hdr *hdr;
+ struct ath_buf *bf_tail = NULL;
+ struct ath_buf *bf;
+ LIST_HEAD(bf_q);
+@@ -2480,15 +2479,10 @@ void ath_tx_cabq(struct ieee80211_hw *hw
+ if (list_empty(&bf_q))
+ return;
+
+- bf = list_first_entry(&bf_q, struct ath_buf, list);
+- hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
+-
+- if (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) {
+- hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+- dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
+- sizeof(*hdr), DMA_TO_DEVICE);
+- }
++ bf = list_last_entry(&bf_q, struct ath_buf, list);
++ ath9k_set_moredata(sc, bf, false);
+
++ bf = list_first_entry(&bf_q, struct ath_buf, list);
+ ath_txq_lock(sc, txctl.txq);
+ ath_tx_fill_desc(sc, bf, txctl.txq, 0);
+ ath_tx_txqaddbuf(sc, txctl.txq, &bf_q, false);
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Mon, 20 Aug 2018 11:35:05 +0200
+Subject: [PATCH] ath9k: fix tx99 with monitor mode interface
+
+Tx99 is typically configured via a monitor mode interface, which does
+not get added to the driver as a vif. Since the code currently expects
+a configured virtual interface for tx99, enabling tx99 via debugfs fails.
+Since the vif is not needed anyway, remove all checks for it.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -1074,7 +1074,6 @@ struct ath_softc {
+
+ struct ath_spec_scan_priv spec_priv;
+
+- struct ieee80211_vif *tx99_vif;
+ struct sk_buff *tx99_skb;
+ bool tx99_state;
+ s16 tx99_power;
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -1251,15 +1251,10 @@ static int ath9k_add_interface(struct ie
+ struct ath_vif *avp = (void *)vif->drv_priv;
+ struct ath_node *an = &avp->mcast_node;
+
+- mutex_lock(&sc->mutex);
++ if (IS_ENABLED(CPTCFG_ATH9K_TX99))
++ return -EOPNOTSUPP;
+
+- if (IS_ENABLED(CPTCFG_ATH9K_TX99)) {
+- if (sc->cur_chan->nvifs >= 1) {
+- mutex_unlock(&sc->mutex);
+- return -EOPNOTSUPP;
+- }
+- sc->tx99_vif = vif;
+- }
++ mutex_lock(&sc->mutex);
+
+ ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
+ sc->cur_chan->nvifs++;
+@@ -1342,7 +1337,6 @@ static void ath9k_remove_interface(struc
+ ath9k_p2p_remove_vif(sc, vif);
+
+ sc->cur_chan->nvifs--;
+- sc->tx99_vif = NULL;
+ if (!ath9k_is_chanctx_enabled())
+ list_del(&avp->list);
+
+--- a/drivers/net/wireless/ath/ath9k/tx99.c
++++ b/drivers/net/wireless/ath/ath9k/tx99.c
+@@ -54,12 +54,6 @@ static struct sk_buff *ath9k_build_tx99_
+ struct ieee80211_hdr *hdr;
+ struct ieee80211_tx_info *tx_info;
+ struct sk_buff *skb;
+- struct ath_vif *avp;
+-
+- if (!sc->tx99_vif)
+- return NULL;
+-
+- avp = (struct ath_vif *)sc->tx99_vif->drv_priv;
+
+ skb = alloc_skb(len, GFP_KERNEL);
+ if (!skb)
+@@ -77,14 +71,11 @@ static struct sk_buff *ath9k_build_tx99_
+ memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
+ memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
+
+- hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
+-
+ tx_info = IEEE80211_SKB_CB(skb);
+ memset(tx_info, 0, sizeof(*tx_info));
+ rate = &tx_info->control.rates[0];
+ tx_info->band = sc->cur_chan->chandef.chan->band;
+ tx_info->flags = IEEE80211_TX_CTL_NO_ACK;
+- tx_info->control.vif = sc->tx99_vif;
+ rate->count = 1;
+ if (ah->curchan && IS_CHAN_HT(ah->curchan)) {
+ rate->flags |= IEEE80211_TX_RC_MCS;
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -2973,7 +2973,7 @@ int ath9k_tx99_send(struct ath_softc *sc
+ return -EINVAL;
+ }
+
+- ath_set_rates(sc->tx99_vif, NULL, bf);
++ ath_set_rates(NULL, NULL, bf);
+
+ 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);
--- /dev/null
+--- a/drivers/net/wireless/ath/Makefile
++++ b/drivers/net/wireless/ath/Makefile
+@@ -13,10 +13,10 @@ ath-objs := main.o \
+ regd.o \
+ hw.o \
+ key.o \
++ debug.o \
+ dfs_pattern_detector.o \
+ dfs_pri_detector.o
+
+-ath-$(CPTCFG_ATH_DEBUG) += debug.o
+ ath-$(CPTCFG_ATH_TRACEPOINTS) += trace.o
+
+ CFLAGS_trace.o := -I$(src)
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -318,14 +318,7 @@ void _ath_dbg(struct ath_common *common,
+ #endif /* CPTCFG_ATH_DEBUG */
+
+ /** Returns string describing opmode, or NULL if unknown mode. */
+-#ifdef CPTCFG_ATH_DEBUG
+ const char *ath_opmode_to_string(enum nl80211_iftype opmode);
+-#else
+-static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode)
+-{
+- return "UNKNOWN";
+-}
+-#endif
+
+ extern const char *ath_bus_type_strings[];
+ static inline const char *ath_bus_type_to_string(enum ath_bus_type bustype)
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -47,7 +47,7 @@ int ath9k_modparam_nohwcrypt;
+ module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444);
+ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
+
+-int ath9k_led_blink;
++int ath9k_led_blink = 1;
+ module_param_named(blink, ath9k_led_blink, int, 0444);
+ MODULE_PARM_DESC(blink, "Enable LED blink on activity");
+
--- /dev/null
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -24,6 +24,7 @@
+ #include "regd_common.h"
+
+ static int __ath_regd_init(struct ath_regulatory *reg);
++static struct reg_dmn_pair_mapping *ath_get_regpair(int regdmn);
+
+ /*
+ * This is a set of common rules used by our world regulatory domains.
+@@ -116,6 +117,9 @@ static const struct ieee80211_regdomain
+
+ static bool dynamic_country_user_possible(struct ath_regulatory *reg)
+ {
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return true;
++
+ if (IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
+ return true;
+
+@@ -188,6 +192,8 @@ static bool dynamic_country_user_possibl
+
+ static bool ath_reg_dyn_country_user_allow(struct ath_regulatory *reg)
+ {
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return true;
+ if (!IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_REG_HINTS))
+ return false;
+ if (!dynamic_country_user_possible(reg))
+@@ -345,6 +351,9 @@ ath_reg_apply_beaconing_flags(struct wip
+ struct ieee80211_channel *ch;
+ unsigned int i;
+
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return;
++
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
+ if (!wiphy->bands[band])
+ continue;
+@@ -378,6 +387,9 @@ ath_reg_apply_ir_flags(struct wiphy *wip
+ {
+ struct ieee80211_supported_band *sband;
+
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return;
++
+ sband = wiphy->bands[NL80211_BAND_2GHZ];
+ if (!sband)
+ return;
+@@ -407,6 +419,9 @@ static void ath_reg_apply_radar_flags(st
+ struct ieee80211_channel *ch;
+ unsigned int i;
+
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return;
++
+ if (!wiphy->bands[NL80211_BAND_5GHZ])
+ return;
+
+@@ -639,6 +654,10 @@ ath_regd_init_wiphy(struct ath_regulator
+ const struct ieee80211_regdomain *regd;
+
+ wiphy->reg_notifier = reg_notifier;
++
++ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
++ return 0;
++
+ wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
+ REGULATORY_CUSTOM_REG;
+
+--- a/drivers/net/wireless/ath/Kconfig
++++ b/drivers/net/wireless/ath/Kconfig
+@@ -23,6 +23,9 @@ config WLAN_VENDOR_ATH
+
+ if WLAN_VENDOR_ATH
+
++config ATH_USER_REGD
++ bool "Do not enforce EEPROM regulatory restrictions"
++
+ config ATH_DEBUG
+ bool "Atheros wireless debugging"
+ ---help---
+--- a/local-symbols
++++ b/local-symbols
+@@ -87,6 +87,7 @@ ADM8211=
+ ATH_COMMON=
+ WLAN_VENDOR_ATH=
+ ATH_DEBUG=
++ATH_USER_REGD=
+ ATH_TRACEPOINTS=
+ ATH_REG_DYNAMIC_USER_REG_HINTS=
+ ATH_REG_DYNAMIC_USER_CERT_TESTING=
--- /dev/null
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -44,7 +44,8 @@ static struct reg_dmn_pair_mapping *ath_
+ NL80211_RRF_NO_OFDM)
+
+ /* We allow IBSS on these on a case by case basis by regulatory domain */
+-#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 80, 0, 30,\
++#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5240+10, 80, 0, 30, 0),\
++ REG_RULE(5260-10, 5350+10, 80, 0, 30,\
+ NL80211_RRF_NO_IR)
+ #define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 80, 0, 30,\
+ NL80211_RRF_NO_IR)
+@@ -62,57 +63,56 @@ static struct reg_dmn_pair_mapping *ath_
+ #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \
+ ATH9K_5GHZ_5725_5850
+
++#define REGD_RULES(...) \
++ .reg_rules = { __VA_ARGS__ }, \
++ .n_reg_rules = ARRAY_SIZE(((struct ieee80211_reg_rule[]) { __VA_ARGS__ }))
++
+ /* Can be used for:
+ * 0x60, 0x61, 0x62 */
+ static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
+- .n_reg_rules = 5,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_ALL,
+ ATH9K_5GHZ_ALL,
+- }
++ )
+ };
+
+ /* Can be used by 0x63 and 0x65 */
+ static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
+- .n_reg_rules = 4,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_2GHZ_CH12_13,
+ ATH9K_5GHZ_NO_MIDBAND,
+- }
++ )
+ };
+
+ /* Can be used by 0x64 only */
+ static const struct ieee80211_regdomain ath_world_regdom_64 = {
+- .n_reg_rules = 3,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_5GHZ_NO_MIDBAND,
+- }
++ )
+ };
+
+ /* Can be used by 0x66 and 0x69 */
+ static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
+- .n_reg_rules = 3,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_5GHZ_ALL,
+- }
++ )
+ };
+
+ /* Can be used by 0x67, 0x68, 0x6A and 0x6C */
+ static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
+- .n_reg_rules = 4,
+ .alpha2 = "99",
+- .reg_rules = {
++ REGD_RULES(
+ ATH9K_2GHZ_CH01_11,
+ ATH9K_2GHZ_CH12_13,
+ ATH9K_5GHZ_ALL,
+- }
++ )
+ };
+
+ static bool dynamic_country_user_possible(struct ath_regulatory *reg)
--- /dev/null
+--- a/net/wireless/reg.c
++++ b/net/wireless/reg.c
+@@ -2860,6 +2860,8 @@ void regulatory_hint_country_ie(struct w
+ enum environment_cap env = ENVIRON_ANY;
+ struct regulatory_request *request = NULL, *lr;
+
++ return;
++
+ /* IE len must be evenly divisible by 2 */
+ if (country_ie_len & 0x01)
+ return;
+@@ -3066,6 +3068,7 @@ static void restore_regulatory_settings(
+
+ void regulatory_hint_disconnect(void)
+ {
++ return;
+ pr_debug("All devices are disconnected, going to restore regulatory settings\n");
+ restore_regulatory_settings(false);
+ }
--- /dev/null
+--- a/drivers/net/wireless/ath/regd_common.h
++++ b/drivers/net/wireless/ath/regd_common.h
+@@ -32,6 +32,7 @@ enum EnumRd {
+ FCC2_WORLD = 0x21,
+ FCC2_ETSIC = 0x22,
+ FCC6_WORLD = 0x23,
++ FCC3_FCCA_2 = 0x2A,
+ FRANCE_RES = 0x31,
+ FCC3_FCCA = 0x3A,
+ FCC3_WORLD = 0x3B,
+@@ -167,6 +168,7 @@ static struct reg_dmn_pair_mapping regDo
+ {FCC2_WORLD, CTL_FCC, CTL_ETSI},
+ {FCC2_ETSIC, CTL_FCC, CTL_ETSI},
+ {FCC3_FCCA, CTL_FCC, CTL_FCC},
++ {FCC3_FCCA_2, CTL_FCC, CTL_FCC},
+ {FCC3_WORLD, CTL_FCC, CTL_ETSI},
+ {FCC4_FCCA, CTL_FCC, CTL_FCC},
+ {FCC5_FCCA, CTL_FCC, CTL_FCC},
+@@ -463,6 +465,7 @@ static struct country_code_to_enum_rd al
+ {CTRY_UAE, NULL1_WORLD, "AE"},
+ {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"},
+ {CTRY_UNITED_STATES, FCC3_FCCA, "US"},
++ {CTRY_UNITED_STATES, FCC3_FCCA_2, "US"},
+ /* This "PS" is for US public safety actually... to support this we
+ * would need to assign new special alpha2 to CRDA db as with the world
+ * regdomain and use another alpha2 */
--- /dev/null
+--- a/drivers/net/wireless/ath/regd.c
++++ b/drivers/net/wireless/ath/regd.c
+@@ -115,6 +115,16 @@ static const struct ieee80211_regdomain
+ )
+ };
+
++static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
++{
++ return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
++}
++
++static bool is_default_regd(struct ath_regulatory *reg)
++{
++ return ath_regd_get_eepromRD(reg) == CTRY_DEFAULT;
++}
++
+ static bool dynamic_country_user_possible(struct ath_regulatory *reg)
+ {
+ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
+@@ -123,6 +133,9 @@ static bool dynamic_country_user_possibl
+ if (IS_ENABLED(CPTCFG_ATH_REG_DYNAMIC_USER_CERT_TESTING))
+ return true;
+
++ if (is_default_regd(reg))
++ return true;
++
+ switch (reg->country_code) {
+ case CTRY_UNITED_STATES:
+ case CTRY_JAPAN1:
+@@ -208,11 +221,6 @@ static inline bool is_wwr_sku(u16 regd)
+ (regd == WORLD));
+ }
+
+-static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
+-{
+- return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
+-}
+-
+ bool ath_is_world_regd(struct ath_regulatory *reg)
+ {
+ return is_wwr_sku(ath_regd_get_eepromRD(reg));
+@@ -658,6 +666,9 @@ ath_regd_init_wiphy(struct ath_regulator
+ if (IS_ENABLED(CPTCFG_ATH_USER_REGD))
+ return 0;
+
++ if (is_default_regd(reg))
++ return 0;
++
+ wiphy->regulatory_flags |= REGULATORY_STRICT_REG |
+ REGULATORY_CUSTOM_REG;
+
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -777,6 +777,7 @@ static const struct ieee80211_iface_limi
+ BIT(NL80211_IFTYPE_AP) },
+ { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO) },
++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
+ };
+
+ #ifdef CPTCFG_WIRELESS_WDS
--- /dev/null
+--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
++++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+@@ -86,13 +86,8 @@ ath5k_add_interface(struct ieee80211_hw
+ goto end;
+ }
+
+- /* Don't allow other interfaces if one ad-hoc is configured.
+- * TODO: Fix the problems with ad-hoc and multiple other interfaces.
+- * We would need to operate the HW in ad-hoc mode to allow TSF updates
+- * for the IBSS, but this breaks with additional AP or STA interfaces
+- * at the moment. */
+- if (ah->num_adhoc_vifs ||
+- (ah->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
++ /* Don't allow more than one ad-hoc interface */
++ if (ah->num_adhoc_vifs && vif->type == NL80211_IFTYPE_ADHOC) {
+ ATH5K_ERR(ah, "Only one single ad-hoc interface is allowed.\n");
+ ret = -ELNRNG;
+ goto end;
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -1965,7 +1965,7 @@ ath5k_beacon_send(struct ath5k_hw *ah)
+ }
+
+ if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
+- ah->num_mesh_vifs > 1) ||
++ ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) ||
+ ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+ u32 tsftu = TSF_TO_TU(tsf);
+@@ -2051,7 +2051,7 @@ ath5k_beacon_update_timers(struct ath5k_
+
+ intval = ah->bintval & AR5K_BEACON_PERIOD;
+ if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
+- + ah->num_mesh_vifs > 1) {
++ + ah->num_adhoc_vifs + ah->num_mesh_vifs > 1) {
+ intval /= ATH_BCBUF; /* staggered multi-bss beacons */
+ if (intval < 15)
+ ATH5K_WARN(ah, "intval %u is too low, min 15\n",
+@@ -2518,6 +2518,7 @@ static const struct ieee80211_iface_limi
+ BIT(NL80211_IFTYPE_MESH_POINT) |
+ #endif
+ BIT(NL80211_IFTYPE_AP) },
++ { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
+ };
+
+ static const struct ieee80211_iface_combination if_comb = {
--- /dev/null
+--- a/drivers/net/wireless/ath/ath5k/reset.c
++++ b/drivers/net/wireless/ath/ath5k/reset.c
+@@ -1154,6 +1154,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
+ tsf_lo = 0;
+ mode = 0;
+
++#if 0
+ /*
+ * Sanity check for fast flag
+ * Fast channel change only available
+@@ -1161,6 +1162,7 @@ ath5k_hw_reset(struct ath5k_hw *ah, enum
+ */
+ if (fast && (ah->ah_radio != AR5K_RF2413) &&
+ (ah->ah_radio != AR5K_RF5413))
++#endif
+ fast = false;
+
+ /* Disable sleep clock operation
--- /dev/null
+--- /dev/null
++++ b/include/linux/ath5k_platform.h
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (c) 2008 Atheros Communications Inc.
++ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
++ * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
++ * Copyright (c) 2010 Daniel Golle <daniel.golle@gmail.com>
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#ifndef _LINUX_ATH5K_PLATFORM_H
++#define _LINUX_ATH5K_PLATFORM_H
++
++#define ATH5K_PLAT_EEP_MAX_WORDS 2048
++
++struct ath5k_platform_data {
++ u16 *eeprom_data;
++ u8 *macaddr;
++};
++
++#endif /* _LINUX_ATH5K_PLATFORM_H */
--- /dev/null
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -21,6 +21,7 @@
+ #include <linux/pci-aspm.h>
+ #include <linux/etherdevice.h>
+ #include <linux/module.h>
++#include <linux/ath5k_platform.h>
+ #include "../ath.h"
+ #include "ath5k.h"
+ #include "debug.h"
+@@ -72,7 +73,7 @@ static void ath5k_pci_read_cachesize(str
+ }
+
+ /*
+- * Read from eeprom
++ * Read from eeprom or platform_data
+ */
+ static bool
+ ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
+@@ -80,6 +81,19 @@ ath5k_pci_eeprom_read(struct ath_common
+ struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
+ u32 status, timeout;
+
++ struct ath5k_platform_data *pdata = NULL;
++
++ if (ah->pdev)
++ pdata = ah->pdev->dev.platform_data;
++
++ if (pdata && pdata->eeprom_data && pdata->eeprom_data[61] == AR5K_EEPROM_MAGIC_VALUE) {
++ if (offset >= ATH5K_PLAT_EEP_MAX_WORDS)
++ return false;
++
++ *data = pdata->eeprom_data[offset];
++ return true;
++ }
++
+ /*
+ * Initialize EEPROM access
+ */
+@@ -123,6 +137,16 @@ static int ath5k_pci_eeprom_read_mac(str
+ u16 data;
+ int octet;
+
++ struct ath5k_platform_data *pdata = NULL;
++
++ if (ah->pdev)
++ pdata = ah->pdev->dev.platform_data;
++
++ if (pdata && pdata->macaddr) {
++ memcpy(mac, pdata->macaddr, ETH_ALEN);
++ return 0;
++ }
++
+ AR5K_EEPROM_READ(0x20, data);
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
--- /dev/null
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -48,6 +48,8 @@ static const struct pci_device_id ath5k_
+ { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
+ { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
+ { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
++ { PCI_VDEVICE(ATHEROS, 0xff16) }, /* 2413,2414 sx76x on lantiq_danube */
++ { PCI_VDEVICE(ATHEROS, 0xff1a) }, /* 2417 arv45xx on lantiq_danube */
+ { PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */
+ { 0 }
+ };
--- /dev/null
+This adds a bwmode debugfs file which can be used to set alternate
+channel operating bandwidths. Only tested with AR5413 and only at
+5 and 20 mhz channels.
+
+Signed-off-by: Pat Erley <pat-lkml at erley.org>
+---
+Other devices will need to be added to the switch in write_file_bwmode
+
+drivers/net/wireless/ath/ath5k/debug.c | 86 ++++++++++++++++++++++++++++++++
+ 1 files changed, 86 insertions(+), 0 deletions(-)
+
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath5k/debug.c
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath5k/debug.c
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath5k/debug.c
+@@ -822,6 +822,97 @@ static const struct file_operations fops
+ .llseek = default_llseek,
+ };
+
++/* debugfs: bwmode */
++
++static ssize_t read_file_bwmode(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath5k_hw *ah = file->private_data;
++ char buf[15];
++ unsigned int len = 0;
++
++ int cur_ah_bwmode = ah->ah_bwmode_debug;
++
++#define print_selected(MODE, LABEL) \
++ if (cur_ah_bwmode == MODE) \
++ len += snprintf(buf+len, sizeof(buf)-len, "[%s]", LABEL); \
++ else \
++ len += snprintf(buf+len, sizeof(buf)-len, "%s", LABEL); \
++ len += snprintf(buf+len, sizeof(buf)-len, " ");
++
++ print_selected(AR5K_BWMODE_5MHZ, "5");
++ print_selected(AR5K_BWMODE_10MHZ, "10");
++ print_selected(AR5K_BWMODE_DEFAULT, "20");
++ print_selected(AR5K_BWMODE_40MHZ, "40");
++#undef print_selected
++
++ len += snprintf(buf+len, sizeof(buf)-len, "\n");
++
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_bwmode(struct file *file,
++ const char __user *userbuf,
++ size_t count, loff_t *ppos)
++{
++ struct ath5k_hw *ah = file->private_data;
++ char buf[3];
++ int bw = 20;
++ int tobwmode = AR5K_BWMODE_DEFAULT;
++
++ if (copy_from_user(buf, userbuf, min(count, sizeof(buf))))
++ return -EFAULT;
++
++ /* TODO: Add check for active interface */
++
++ if(strncmp(buf, "5", 1) == 0 ) {
++ tobwmode = AR5K_BWMODE_5MHZ;
++ bw = 5;
++ } else if ( strncmp(buf, "10", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_10MHZ;
++ bw = 10;
++ } else if ( strncmp(buf, "20", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_DEFAULT;
++ bw = 20;
++ } else if ( strncmp(buf, "40", 2) == 0 ) {
++ tobwmode = AR5K_BWMODE_40MHZ;
++ bw = 40;
++ } else
++ return -EINVAL;
++
++ ATH5K_INFO(ah, "Changing to %imhz channel width[%i]\n",
++ bw, tobwmode);
++
++ switch (ah->ah_radio) {
++ /* TODO: only define radios that actually support 5/10mhz channels */
++ case AR5K_RF5413:
++ case AR5K_RF5110:
++ case AR5K_RF5111:
++ case AR5K_RF5112:
++ case AR5K_RF2413:
++ case AR5K_RF2316:
++ case AR5K_RF2317:
++ case AR5K_RF2425:
++ if(ah->ah_bwmode_debug != tobwmode) {
++ mutex_lock(&ah->lock);
++ ah->ah_bwmode = tobwmode;
++ ah->ah_bwmode_debug = tobwmode;
++ mutex_unlock(&ah->lock);
++ }
++ break;
++ default:
++ return -EOPNOTSUPP;
++ }
++ return count;
++}
++
++static const struct file_operations fops_bwmode = {
++ .read = read_file_bwmode,
++ .write = write_file_bwmode,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
+
+ /* debugfs: queues etc */
+
+@@ -1016,6 +1107,8 @@ ath5k_debug_init_device(struct ath5k_hw
+ debugfs_create_file("queue", 0600, phydir, ah, &fops_queue);
+ debugfs_create_bool("32khz_clock", 0600, phydir,
+ &ah->ah_use_32khz_clock);
++ debugfs_create_file("bwmode", S_IWUSR | S_IRUSR, phydir, ah,
++ &fops_bwmode);
+ }
+
+ /* functions used in other places */
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath5k/ath5k.h
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath5k/ath5k.h
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath5k/ath5k.h
+@@ -1372,6 +1372,7 @@ struct ath5k_hw {
+ u8 ah_coverage_class;
+ bool ah_ack_bitrate_high;
+ u8 ah_bwmode;
++ u8 ah_bwmode_debug;
+ bool ah_short_slot;
+
+ /* Antenna Control */
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath5k/base.c
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath5k/base.c
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath5k/base.c
+@@ -466,6 +466,9 @@ ath5k_chan_set(struct ath5k_hw *ah, stru
+ return -EINVAL;
+ }
+
++ if (ah->ah_bwmode_debug != AR5K_BWMODE_DEFAULT)
++ ah->ah_bwmode = ah->ah_bwmode_debug;
++
+ /*
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1374,6 +1374,53 @@ void ath9k_deinit_debug(struct ath_softc
+ ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
+ }
+
++static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ struct ath_common *common = ath9k_hw_common(ah);
++ int bytes = 0;
++ int pos = *ppos;
++ int size = 4096;
++ u16 val;
++ int i;
++
++ if (AR_SREV_9300_20_OR_LATER(ah))
++ size = 16384;
++
++ if (*ppos < 0)
++ return -EINVAL;
++
++ if (count > size - *ppos)
++ count = size - *ppos;
++
++ for (i = *ppos / 2; count > 0; count -= bytes, *ppos += bytes, i++) {
++ void *from = &val;
++
++ if (!common->bus_ops->eeprom_read(common, i, &val))
++ val = 0xffff;
++
++ if (*ppos % 2) {
++ from++;
++ bytes = 1;
++ } else if (count == 1) {
++ bytes = 1;
++ } else {
++ bytes = 2;
++ }
++ copy_to_user(user_buf, from, bytes);
++ user_buf += bytes;
++ }
++ return *ppos - pos;
++}
++
++static const struct file_operations fops_eeprom = {
++ .read = read_file_eeprom,
++ .open = simple_open,
++ .owner = THIS_MODULE
++};
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1393,6 +1440,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);
+
++ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
++ &fops_eeprom);
+ debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
+ read_file_dma);
+ debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
--- /dev/null
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath9k/init.c
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath9k/init.c
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath9k/init.c
+@@ -1144,25 +1144,25 @@ static int __init ath9k_init(void)
+ {
+ int error;
+
+- error = ath_pci_init();
++ error = ath_ahb_init();
+ if (error < 0) {
+- pr_err("No PCI devices found, driver not installed\n");
+ error = -ENODEV;
+ goto err_out;
+ }
+
+- error = ath_ahb_init();
++ error = ath_pci_init();
+ if (error < 0) {
++ pr_err("No PCI devices found, driver not installed\n");
+ error = -ENODEV;
+- goto err_pci_exit;
++ goto err_ahb_exit;
+ }
+
+ dmi_check_system(ath9k_quirks);
+
+ return 0;
+
+- err_pci_exit:
+- ath_pci_exit();
++ err_ahb_exit:
++ ath_ahb_exit();
+ err_out:
+ return error;
+ }
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -390,13 +390,8 @@ static void ath9k_hw_init_config(struct
+
+ ah->config.rx_intr_mitigation = true;
+
+- if (AR_SREV_9300_20_OR_LATER(ah)) {
+- ah->config.rimt_last = 500;
+- ah->config.rimt_first = 2000;
+- } else {
+- ah->config.rimt_last = 250;
+- ah->config.rimt_first = 700;
+- }
++ ah->config.rimt_last = 250;
++ ah->config.rimt_first = 500;
+
+ if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+ ah->config.pll_pwrsave = 7;
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -88,7 +88,7 @@ int ath_descdma_setup(struct ath_softc *
+ (_l) &= ((_sz) - 1); \
+ } while (0)
+
+-#define ATH_RXBUF 512
++#define ATH_RXBUF 256
+ #define ATH_TXBUF 512
+ #define ATH_TXBUF_RESERVE 5
+ #define ATH_TXMAXTRY 13
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1421,6 +1421,52 @@ static const struct file_operations fops
+ .owner = THIS_MODULE
+ };
+
++
++static ssize_t read_file_chan_bw(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ char buf[32];
++ unsigned int len;
++
++ len = sprintf(buf, "0x%08x\n", common->chan_bw);
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_chan_bw(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
++ unsigned long chan_bw;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (kstrtoul(buf, 0, &chan_bw))
++ return -EINVAL;
++
++ common->chan_bw = chan_bw;
++ if (!test_bit(ATH_OP_INVALID, &common->op_flags))
++ ath9k_ops.config(sc->hw, IEEE80211_CONF_CHANGE_CHANNEL);
++
++ return count;
++}
++
++static const struct file_operations fops_chanbw = {
++ .read = read_file_chan_bw,
++ .write = write_file_chan_bw,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1442,6 +1488,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+
+ debugfs_create_file("eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
+ &fops_eeprom);
++ debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++ sc, &fops_chanbw);
+ debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
+ read_file_dma);
+ debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
+--- a/drivers/net/wireless/ath/ath.h
++++ b/drivers/net/wireless/ath/ath.h
+@@ -151,6 +151,7 @@ struct ath_common {
+ int debug_mask;
+ enum ath_device_state state;
+ unsigned long op_flags;
++ u32 chan_bw;
+
+ struct ath_ani ani;
+
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -297,11 +297,13 @@ EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_ke
+ /*
+ * Update internal channel flags.
+ */
+-static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
++static void ath9k_cmn_update_ichannel(struct ath_common *common,
++ struct ath9k_channel *ichan,
+ struct cfg80211_chan_def *chandef)
+ {
+ struct ieee80211_channel *chan = chandef->chan;
+ u16 flags = 0;
++ int width;
+
+ ichan->channel = chan->center_freq;
+ ichan->chan = chan;
+@@ -309,7 +311,19 @@ static void ath9k_cmn_update_ichannel(st
+ if (chan->band == NL80211_BAND_5GHZ)
+ flags |= CHANNEL_5GHZ;
+
+- switch (chandef->width) {
++ switch (common->chan_bw) {
++ case 5:
++ width = NL80211_CHAN_WIDTH_5;
++ break;
++ case 10:
++ width = NL80211_CHAN_WIDTH_10;
++ break;
++ default:
++ width = chandef->width;
++ break;
++ }
++
++ switch (width) {
+ case NL80211_CHAN_WIDTH_5:
+ flags |= CHANNEL_QUARTER;
+ break;
+@@ -342,10 +356,11 @@ struct ath9k_channel *ath9k_cmn_get_chan
+ struct cfg80211_chan_def *chandef)
+ {
+ struct ieee80211_channel *curchan = chandef->chan;
++ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_channel *channel;
+
+ channel = &ah->channels[curchan->hw_value];
+- ath9k_cmn_update_ichannel(channel, chandef);
++ ath9k_cmn_update_ichannel(common, channel, chandef);
+
+ return channel;
+ }
--- /dev/null
+--- 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)
+
+ /* These are all the AR5008/AR9001/AR9002/AR9003 hardware family of chipsets */
+ switch (ah->hw_version.devid) {
++ case AR9300_DEVID_INVALID:
+ case AR5416_DEVID_PCI:
+ case AR5416_DEVID_PCIE:
+ case AR5416_AR9100_DEVID:
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -36,6 +36,7 @@
+
+ #define ATHEROS_VENDOR_ID 0x168c
+
++#define AR9300_DEVID_INVALID 0xabcd
+ #define AR5416_DEVID_PCI 0x0023
+ #define AR5416_DEVID_PCIE 0x0024
+ #define AR9160_DEVID_PCI 0x0027
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -773,6 +773,7 @@ static const struct pci_device_id ath_pc
+ .driver_data = ATH9K_PCI_BT_ANT_DIV },
+ #endif
+
++ { PCI_VDEVICE(ATHEROS, 0xabcd) }, /* PCI-E internal chip default ID */
+ { 0 }
+ };
+
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -850,6 +850,9 @@ static inline int ath9k_dump_btcoex(stru
+ #ifdef CPTCFG_MAC80211_LEDS
+ void ath_init_leds(struct ath_softc *sc);
+ void ath_deinit_leds(struct ath_softc *sc);
++int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name,
++ const char *trigger, bool active_low);
++
+ #else
+ static inline void ath_init_leds(struct ath_softc *sc)
+ {
+@@ -991,6 +994,13 @@ void ath_ant_comb_scan(struct ath_softc
+ #define AIRTIME_USE_NEW_QUEUES BIT(2)
+ #define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX)))
+
++struct ath_led {
++ struct list_head list;
++ struct ath_softc *sc;
++ const struct gpio_led *gpio;
++ struct led_classdev cdev;
++};
++
+ struct ath_softc {
+ struct ieee80211_hw *hw;
+ struct device *dev;
+@@ -1046,9 +1056,8 @@ struct ath_softc {
+ spinlock_t chan_lock;
+
+ #ifdef CPTCFG_MAC80211_LEDS
+- bool led_registered;
+- char led_name[32];
+- struct led_classdev led_cdev;
++ const char *led_default_trigger;
++ struct list_head leds;
+ #endif
+
+ #ifdef CPTCFG_ATH9K_DEBUGFS
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -39,61 +39,111 @@ static void ath_fill_led_pin(struct ath_
+ else
+ ah->led_pin = ATH_LED_PIN_DEF;
+ }
++}
++
++static void ath_led_brightness(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
++{
++ struct ath_led *led = container_of(led_cdev, struct ath_led, cdev);
++ struct ath_softc *sc = led->sc;
++
++ ath9k_ps_wakeup(sc);
++ ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio,
++ (brightness != LED_OFF) ^ led->gpio->active_low);
++ ath9k_ps_restore(sc);
++}
++
++static int ath_add_led(struct ath_softc *sc, struct ath_led *led)
++{
++ const struct gpio_led *gpio = led->gpio;
++ int ret;
++
++ led->cdev.name = gpio->name;
++ led->cdev.default_trigger = gpio->default_trigger;
++ led->cdev.brightness_set = ath_led_brightness;
++
++ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev);
++ if (ret < 0)
++ return ret;
++
++ led->sc = sc;
++ list_add(&led->list, &sc->leds);
+
+ /* Configure gpio for output */
+- ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led",
++ ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+
+- /* LED off, active low */
+- ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1);
++ /* LED off */
++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
++
++ return 0;
+ }
+
+-static void ath_led_brightness(struct led_classdev *led_cdev,
+- enum led_brightness brightness)
++int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name,
++ const char *trigger, bool active_low)
+ {
+- struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
+- u32 val = (brightness == LED_OFF);
++ struct ath_led *led;
++ struct gpio_led *gpio;
++ char *_name;
++ int ret;
+
+- if (sc->sc_ah->config.led_active_high)
+- val = !val;
++ led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1,
++ GFP_KERNEL);
++ if (!led)
++ return -ENOMEM;
++
++ led->gpio = gpio = (struct gpio_led *) (led + 1);
++ _name = (char *) (led->gpio + 1);
++
++ strcpy(_name, name);
++ gpio->name = _name;
++ gpio->gpio = gpio_num;
++ gpio->active_low = active_low;
++ gpio->default_trigger = trigger;
++
++ ret = ath_add_led(sc, led);
++ if (unlikely(ret < 0))
++ kfree(led);
+
+- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
++ return ret;
+ }
+
+ void ath_deinit_leds(struct ath_softc *sc)
+ {
+- if (!sc->led_registered)
+- return;
++ struct ath_led *led;
+
+- ath_led_brightness(&sc->led_cdev, LED_OFF);
+- led_classdev_unregister(&sc->led_cdev);
+-
+- ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin);
++ while (!list_empty(&sc->leds)) {
++ led = list_first_entry(&sc->leds, struct ath_led, list);
++ list_del(&led->list);
++ ath_led_brightness(&led->cdev, LED_OFF);
++ led_classdev_unregister(&led->cdev);
++ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
++ kfree(led);
++ }
+ }
+
+ void ath_init_leds(struct ath_softc *sc)
+ {
+- int ret;
++ char led_name[32];
++ const char *trigger;
++
++ INIT_LIST_HEAD(&sc->leds);
+
+ if (AR_SREV_9100(sc->sc_ah))
+ return;
+
+ ath_fill_led_pin(sc);
+
+- if (!ath9k_led_blink)
+- sc->led_cdev.default_trigger =
+- ieee80211_get_radio_led_name(sc->hw);
+-
+- snprintf(sc->led_name, sizeof(sc->led_name),
+- "ath9k-%s", wiphy_name(sc->hw->wiphy));
+- sc->led_cdev.name = sc->led_name;
+- sc->led_cdev.brightness_set = ath_led_brightness;
++ snprintf(led_name, sizeof(led_name), "ath9k-%s",
++ wiphy_name(sc->hw->wiphy));
+
+- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
+- if (ret < 0)
+- return;
++ if (ath9k_led_blink)
++ trigger = sc->led_default_trigger;
++ else
++ trigger = ieee80211_get_radio_led_name(sc->hw);
+
+- sc->led_registered = true;
++ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
++ !sc->sc_ah->config.led_active_high);
+ }
+ #endif
+
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -1000,7 +1000,7 @@ int ath9k_init_device(u16 devid, struct
+
+ #ifdef CPTCFG_MAC80211_LEDS
+ /* must be initialized before ieee80211_register_hw */
+- sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
++ sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
+ ARRAY_SIZE(ath9k_tpt_blink));
+ #endif
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1466,6 +1466,61 @@ static const struct file_operations fops
+ .llseek = default_llseek,
+ };
+
++#ifdef CONFIG_MAC80211_LEDS
++
++static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ char buf[32], *str, *name, *c;
++ ssize_t len;
++ unsigned int gpio;
++ bool active_low = false;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, ubuf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ name = strchr(buf, ',');
++ if (!name)
++ return -EINVAL;
++
++ *(name++) = 0;
++ if (!*name)
++ return -EINVAL;
++
++ c = strchr(name, '\n');
++ if (c)
++ *c = 0;
++
++ str = buf;
++ if (*str == '!') {
++ str++;
++ active_low = true;
++ }
++
++ if (kstrtouint(str, 0, &gpio) < 0)
++ return -EINVAL;
++
++ if (gpio >= sc->sc_ah->caps.num_gpio_pins)
++ return -EINVAL;
++
++ if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0)
++ return -EINVAL;
++
++ return count;
++}
++
++static const struct file_operations fops_gpio_led = {
++ .write = write_file_gpio_led,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++#endif
++
+
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+@@ -1490,6 +1545,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);
++#ifdef CONFIG_MAC80211_LEDS
++ debugfs_create_file("gpio_led", S_IWUSR,
++ sc->debug.debugfs_phy, sc, &fops_gpio_led);
++#endif
+ debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
+ read_file_dma);
+ debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
--- /dev/null
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -46,6 +46,9 @@ struct ath9k_platform_data {
+ int (*external_reset)(void);
+
+ bool use_eeprom;
++
++ int num_leds;
++ const struct gpio_led *leds;
+ };
+
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -15,6 +15,7 @@
+ */
+
+ #include "ath9k.h"
++#include <linux/ath9k_platform.h>
+
+ /********************************/
+ /* LED functions */
+@@ -108,6 +109,24 @@ int ath_create_gpio_led(struct ath_softc
+ return ret;
+ }
+
++static int ath_create_platform_led(struct ath_softc *sc,
++ const struct gpio_led *gpio)
++{
++ struct ath_led *led;
++ int ret;
++
++ led = kzalloc(sizeof(*led), GFP_KERNEL);
++ if (!led)
++ return -ENOMEM;
++
++ led->gpio = gpio;
++ ret = ath_add_led(sc, led);
++ if (ret < 0)
++ kfree(led);
++
++ return ret;
++}
++
+ void ath_deinit_leds(struct ath_softc *sc)
+ {
+ struct ath_led *led;
+@@ -124,8 +143,10 @@ void ath_deinit_leds(struct ath_softc *s
+
+ void ath_init_leds(struct ath_softc *sc)
+ {
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
+ char led_name[32];
+ const char *trigger;
++ int i;
+
+ INIT_LIST_HEAD(&sc->leds);
+
+@@ -134,6 +155,17 @@ void ath_init_leds(struct ath_softc *sc)
+
+ ath_fill_led_pin(sc);
+
++ if (pdata && pdata->leds && pdata->num_leds)
++ for (i = 0; i < pdata->num_leds; i++) {
++ if (pdata->leds[i].gpio == sc->sc_ah->led_pin)
++ sc->sc_ah->led_pin = -1;
++
++ ath_create_platform_led(sc, &pdata->leds[i]);
++ }
++
++ if (sc->sc_ah->led_pin < 0)
++ return;
++
+ snprintf(led_name, sizeof(led_name), "ath9k-%s",
+ wiphy_name(sc->hw->wiphy));
+
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ani.h
++++ b/drivers/net/wireless/ath/ath9k/ani.h
+@@ -42,7 +42,7 @@
+ #define ATH9K_ANI_PERIOD 300
+
+ /* in ms */
+-#define ATH9K_ANI_POLLINTERVAL 1000
++#define ATH9K_ANI_POLLINTERVAL 300
+
+ #define ATH9K_SIG_FIRSTEP_SETTING_MIN 0
+ #define ATH9K_SIG_FIRSTEP_SETTING_MAX 20
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/debug.c
++++ b/drivers/net/wireless/ath/ath9k/debug.c
+@@ -1522,6 +1522,50 @@ static const struct file_operations fops
+ #endif
+
+
++static ssize_t read_file_diag(struct file *file, char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ char buf[32];
++ unsigned int len;
++
++ len = sprintf(buf, "0x%08lx\n", ah->diag);
++ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
++}
++
++static ssize_t write_file_diag(struct file *file, const char __user *user_buf,
++ size_t count, loff_t *ppos)
++{
++ struct ath_softc *sc = file->private_data;
++ struct ath_hw *ah = sc->sc_ah;
++ unsigned long diag;
++ char buf[32];
++ ssize_t len;
++
++ len = min(count, sizeof(buf) - 1);
++ if (copy_from_user(buf, user_buf, len))
++ return -EFAULT;
++
++ buf[len] = '\0';
++ if (kstrtoul(buf, 0, &diag))
++ return -EINVAL;
++
++ ah->diag = diag;
++ ath9k_hw_update_diag(ah);
++
++ return count;
++}
++
++static const struct file_operations fops_diag = {
++ .read = read_file_diag,
++ .write = write_file_diag,
++ .open = simple_open,
++ .owner = THIS_MODULE,
++ .llseek = default_llseek,
++};
++
++
+ int ath9k_init_debug(struct ath_hw *ah)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+@@ -1549,6 +1593,8 @@ int ath9k_init_debug(struct ath_hw *ah)
+ debugfs_create_file("gpio_led", S_IWUSR,
+ sc->debug.debugfs_phy, sc, &fops_gpio_led);
+ #endif
++ debugfs_create_file("diag", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
++ sc, &fops_diag);
+ debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
+ read_file_dma);
+ 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
+@@ -520,6 +520,12 @@ enum {
+ ATH9K_RESET_COLD,
+ };
+
++enum {
++ ATH_DIAG_DISABLE_RX,
++ ATH_DIAG_DISABLE_TX,
++ ATH_DIAG_TRIGGER_ERROR,
++};
++
+ struct ath9k_hw_version {
+ u32 magic;
+ u16 devid;
+@@ -806,6 +812,8 @@ struct ath_hw {
+ u32 ah_flags;
+ s16 nf_override;
+
++ unsigned long diag;
++
+ bool reset_power_on;
+ bool htc_reset_init;
+
+@@ -1068,6 +1076,7 @@ void ath9k_hw_check_nav(struct ath_hw *a
+ bool ath9k_hw_check_alive(struct ath_hw *ah);
+
+ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
++void ath9k_hw_update_diag(struct ath_hw *ah);
+
+ /* Generic hw timer primitives */
+ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -1842,6 +1842,20 @@ u32 ath9k_hw_get_tsf_offset(struct times
+ }
+ EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
+
++void ath9k_hw_update_diag(struct ath_hw *ah)
++{
++ if (test_bit(ATH_DIAG_DISABLE_RX, &ah->diag))
++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++ else
++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
++
++ if (test_bit(ATH_DIAG_DISABLE_TX, &ah->diag))
++ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++ else
++ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_LOOP_BACK);
++}
++EXPORT_SYMBOL(ath9k_hw_update_diag);
++
+ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
+ struct ath9k_hw_cal_data *caldata, bool fastcc)
+ {
+@@ -2050,6 +2064,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ ar9003_hw_disable_phy_restart(ah);
+
+ ath9k_hw_apply_gpio_override(ah);
++ ath9k_hw_update_diag(ah);
+
+ if (AR_SREV_9565(ah) && common->bt_ant_diversity)
+ REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -528,6 +528,11 @@ irqreturn_t ath_isr(int irq, void *dev)
+ if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
+ return IRQ_HANDLED;
+
++ if (test_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag)) {
++ status |= ATH9K_INT_FATAL;
++ clear_bit(ATH_DIAG_TRIGGER_ERROR, &ah->diag);
++ }
++
+ /*
+ * If there are no status bits set, then this interrupt was not
+ * for me (should have been caught above).
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/hw.h
++++ b/drivers/net/wireless/ath/ath9k/hw.h
+@@ -721,6 +721,7 @@ struct ath_spec_scan {
+ * @config_pci_powersave:
+ * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
+ *
++ * @get_adc_entropy: get entropy from the raw ADC I/Q output
+ * @spectral_scan_config: set parameters for spectral scan and enable/disable it
+ * @spectral_scan_trigger: trigger a spectral scan run
+ * @spectral_scan_wait: wait for a spectral scan run to finish
+@@ -743,6 +744,7 @@ struct ath_hw_ops {
+ struct ath_hw_antcomb_conf *antconf);
+ void (*antdiv_comb_conf_set)(struct ath_hw *ah,
+ struct ath_hw_antcomb_conf *antconf);
++ void (*get_adc_entropy)(struct ath_hw *ah, u8 *buf, size_t len);
+ void (*spectral_scan_config)(struct ath_hw *ah,
+ struct ath_spec_scan *param);
+ void (*spectral_scan_trigger)(struct ath_hw *ah);
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -1945,6 +1945,26 @@ void ar9003_hw_init_rate_txpower(struct
+ }
+ }
+
++static void ar9003_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
++{
++ int i, j;
++
++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
++ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0);
++
++ memset(buf, 0, len);
++ for (i = 0; i < len; i++) {
++ for (j = 0; j < 4; j++) {
++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
++
++ buf[i] <<= 2;
++ buf[i] |= (regval & 1) | ((regval & BIT(10)) >> 9);
++ udelay(1);
++ }
++ }
++}
++
+ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
+ {
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+@@ -1981,6 +2001,7 @@ void ar9003_hw_attach_phy_ops(struct ath
+ priv_ops->set_radar_params = ar9003_hw_set_radar_params;
+ priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;
+
++ ops->get_adc_entropy = ar9003_hw_get_adc_entropy;
+ ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
+ ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
+ ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -765,7 +765,8 @@ static void ath9k_init_txpower_limits(st
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+ ath9k_init_band_txpower(sc, NL80211_BAND_5GHZ);
+
+- ah->curchan = curchan;
++ if (curchan)
++ ah->curchan = curchan;
+ }
+
+ static const struct ieee80211_iface_limit if_limits[] = {
+@@ -960,6 +961,18 @@ static void ath9k_set_hw_capab(struct at
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+ }
+
++static void ath_get_initial_entropy(struct ath_softc *sc)
++{
++ struct ath_hw *ah = sc->sc_ah;
++ char buf[256];
++
++ /* reuse last channel initialized by the tx power test */
++ ath9k_hw_reset(ah, ah->curchan, NULL, false);
++
++ ath9k_hw_get_adc_entropy(ah, buf, sizeof(buf));
++ add_device_randomness(buf, sizeof(buf));
++}
++
+ int ath9k_init_device(u16 devid, struct ath_softc *sc,
+ const struct ath_bus_ops *bus_ops)
+ {
+@@ -1005,6 +1018,8 @@ int ath9k_init_device(u16 devid, struct
+ ARRAY_SIZE(ath9k_tpt_blink));
+ #endif
+
++ ath_get_initial_entropy(sc);
++
+ /* Register with mac80211 */
+ error = ieee80211_register_hw(hw);
+ if (error)
+--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
++++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
+@@ -100,6 +100,12 @@ static inline void ath9k_hw_tx99_set_txp
+ ath9k_hw_ops(ah)->tx99_set_txpower(ah, power);
+ }
+
++static inline void ath9k_hw_get_adc_entropy(struct ath_hw *ah,
++ u8 *buf, size_t len)
++{
++ ath9k_hw_ops(ah)->get_adc_entropy(ah, buf, len);
++}
++
+ #ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
+
+ static inline void ath9k_hw_set_bt_ant_diversity(struct ath_hw *ah, bool enable)
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -1322,9 +1322,30 @@ void ar5008_hw_init_rate_txpower(struct
+ }
+ }
+
++static void ar5008_hw_get_adc_entropy(struct ath_hw *ah, u8 *buf, size_t len)
++{
++ int i, j;
++
++ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
++ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
++ REG_RMW_FIELD(ah, AR_PHY_TEST2, AR_PHY_TEST2_RX_OBS_SEL, 0);
++
++ memset(buf, 0, len);
++ for (i = 0; i < len; i++) {
++ for (j = 0; j < 4; j++) {
++ u32 regval = REG_READ(ah, AR_PHY_TST_ADC);
++
++ buf[i] <<= 2;
++ buf[i] |= (regval & 1) | ((regval & BIT(9)) >> 8);
++ udelay(1);
++ }
++ }
++}
++
+ int ar5008_hw_attach_phy_ops(struct ath_hw *ah)
+ {
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
++ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+ static const u32 ar5416_cca_regs[6] = {
+ AR_PHY_CCA,
+ AR_PHY_CH1_CCA,
+@@ -1339,6 +1360,8 @@ int ar5008_hw_attach_phy_ops(struct ath_
+ if (ret)
+ return ret;
+
++ ops->get_adc_entropy = ar5008_hw_get_adc_entropy;
++
+ priv_ops->rf_set_freq = ar5008_hw_set_channel;
+ priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
+
+--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h
++++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h
+@@ -20,6 +20,12 @@
+ #define PHY_AGC_CLR 0x10000000
+ #define RFSILENT_BB 0x00002000
+
++#define AR_PHY_TEST_BBB_OBS_SEL 0x780000
++#define AR_PHY_TEST_BBB_OBS_SEL_S 19
++
++#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23
++#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S)
++
+ #define AR_PHY_TURBO 0x9804
+ #define AR_PHY_FC_TURBO_MODE 0x00000001
+ #define AR_PHY_FC_TURBO_SHORT 0x00000002
+@@ -36,6 +42,9 @@
+
+ #define AR_PHY_TEST2 0x9808
+
++#define AR_PHY_TEST2_RX_OBS_SEL 0x3C00
++#define AR_PHY_TEST2_RX_OBS_SEL_S 10
++
+ #define AR_PHY_TIMING2 0x9810
+ #define AR_PHY_TIMING3 0x9814
+ #define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
+@@ -393,6 +402,8 @@
+ #define AR_PHY_RFBUS_GRANT 0x9C20
+ #define AR_PHY_RFBUS_GRANT_EN 0x00000001
+
++#define AR_PHY_TST_ADC 0x9C24
++
+ #define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
+ #define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
+
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/hw.c
++++ b/drivers/net/wireless/ath/ath9k/hw.c
+@@ -246,6 +246,19 @@ void ath9k_hw_get_channel_centers(struct
+ centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT);
+ }
+
++static inline void ath9k_hw_disable_pll_lock_detect(struct ath_hw *ah)
++{
++ /* On AR9330 and AR9340 devices, some PHY registers must be
++ * tuned to gain better stability/performance. These registers
++ * might be changed while doing wlan reset so the registers must
++ * be reprogrammed after each reset.
++ */
++ REG_CLR_BIT(ah, AR_PHY_USB_CTRL1, BIT(20));
++ REG_RMW(ah, AR_PHY_USB_CTRL2,
++ (1 << 21) | (0xf << 22),
++ (1 << 21) | (0x3 << 22));
++}
++
+ /******************/
+ /* Chip Revisions */
+ /******************/
+@@ -1414,6 +1427,9 @@ static bool ath9k_hw_set_reset(struct at
+ udelay(50);
+ }
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return true;
+ }
+
+@@ -1513,6 +1529,9 @@ static bool ath9k_hw_chip_reset(struct a
+ ar9003_hw_internal_regulator_apply(ah);
+ ath9k_hw_init_pll(ah, chan);
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return true;
+ }
+
+@@ -1820,8 +1839,14 @@ static int ath9k_hw_do_fastcc(struct ath
+ if (AR_SREV_9271(ah))
+ ar9002_hw_load_ani_reg(ah, chan);
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return 0;
+ fail:
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return -EINVAL;
+ }
+
+@@ -2075,6 +2100,9 @@ int ath9k_hw_reset(struct ath_hw *ah, st
+ ath9k_hw_set_radar_params(ah);
+ }
+
++ if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
++ ath9k_hw_disable_pll_lock_detect(ah);
++
+ return 0;
+ }
+ EXPORT_SYMBOL(ath9k_hw_reset);
+--- a/drivers/net/wireless/ath/ath9k/phy.h
++++ b/drivers/net/wireless/ath/ath9k/phy.h
+@@ -48,6 +48,9 @@
+ #define AR_PHY_PLL_CONTROL 0x16180
+ #define AR_PHY_PLL_MODE 0x16184
+
++#define AR_PHY_USB_CTRL1 0x16c84
++#define AR_PHY_USB_CTRL2 0x16c88
++
+ enum ath9k_ant_div_comb_lna_conf {
+ ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2,
+ ATH_ANT_DIV_COMB_LNA2,
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+@@ -951,55 +951,6 @@ static bool ar5008_hw_ani_control_new(st
+ * on == 0 means more noise imm
+ */
+ u32 on = param ? 1 : 0;
+- /*
+- * make register setting for default
+- * (weak sig detect ON) come from INI file
+- */
+- int m1ThreshLow = on ?
+- aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+- int m2ThreshLow = on ?
+- aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+- int m1Thresh = on ?
+- aniState->iniDef.m1Thresh : m1Thresh_off;
+- int m2Thresh = on ?
+- aniState->iniDef.m2Thresh : m2Thresh_off;
+- int m2CountThr = on ?
+- aniState->iniDef.m2CountThr : m2CountThr_off;
+- int m2CountThrLow = on ?
+- aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+- int m1ThreshLowExt = on ?
+- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+- int m2ThreshLowExt = on ?
+- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+- int m1ThreshExt = on ?
+- aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+- int m2ThreshExt = on ?
+- aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+-
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+- m1ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+- m2ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M1_THRESH, m1Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2_THRESH, m2Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2COUNT_THR, m2CountThr);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+- m2CountThrLow);
+-
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt);
+
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+@@ -42,20 +42,6 @@ static const int cycpwrThr1_table[] =
+ /* level: 0 1 2 3 4 5 6 7 8 */
+ { -6, -4, -2, 0, 2, 4, 6, 8 }; /* lvl 0-7, default 3 */
+
+-/*
+- * register values to turn OFDM weak signal detection OFF
+- */
+-static const int m1ThreshLow_off = 127;
+-static const int m2ThreshLow_off = 127;
+-static const int m1Thresh_off = 127;
+-static const int m2Thresh_off = 127;
+-static const int m2CountThr_off = 31;
+-static const int m2CountThrLow_off = 63;
+-static const int m1ThreshLowExt_off = 127;
+-static const int m2ThreshLowExt_off = 127;
+-static const int m1ThreshExt_off = 127;
+-static const int m2ThreshExt_off = 127;
+-
+ static const u8 ofdm2pwr[] = {
+ ALL_TARGET_LEGACY_6_24,
+ ALL_TARGET_LEGACY_6_24,
+@@ -1095,11 +1081,6 @@ static bool ar9003_hw_ani_control(struct
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_channel *chan = ah->curchan;
+ struct ar5416AniState *aniState = &ah->ani;
+- int m1ThreshLow, m2ThreshLow;
+- int m1Thresh, m2Thresh;
+- int m2CountThr, m2CountThrLow;
+- int m1ThreshLowExt, m2ThreshLowExt;
+- int m1ThreshExt, m2ThreshExt;
+ s32 value, value2;
+
+ switch (cmd & ah->ani_function) {
+@@ -1113,61 +1094,6 @@ static bool ar9003_hw_ani_control(struct
+ */
+ u32 on = param ? 1 : 0;
+
+- if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+- goto skip_ws_det;
+-
+- m1ThreshLow = on ?
+- aniState->iniDef.m1ThreshLow : m1ThreshLow_off;
+- m2ThreshLow = on ?
+- aniState->iniDef.m2ThreshLow : m2ThreshLow_off;
+- m1Thresh = on ?
+- aniState->iniDef.m1Thresh : m1Thresh_off;
+- m2Thresh = on ?
+- aniState->iniDef.m2Thresh : m2Thresh_off;
+- m2CountThr = on ?
+- aniState->iniDef.m2CountThr : m2CountThr_off;
+- m2CountThrLow = on ?
+- aniState->iniDef.m2CountThrLow : m2CountThrLow_off;
+- m1ThreshLowExt = on ?
+- aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off;
+- m2ThreshLowExt = on ?
+- aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off;
+- m1ThreshExt = on ?
+- aniState->iniDef.m1ThreshExt : m1ThreshExt_off;
+- m2ThreshExt = on ?
+- aniState->iniDef.m2ThreshExt : m2ThreshExt_off;
+-
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+- m1ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+- m2ThreshLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M1_THRESH,
+- m1Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2_THRESH,
+- m2Thresh);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+- AR_PHY_SFCORR_M2COUNT_THR,
+- m2CountThr);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+- m2CountThrLow);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+- m1ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+- m2ThreshLowExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M1_THRESH,
+- m1ThreshExt);
+- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+- AR_PHY_SFCORR_EXT_M2_THRESH,
+- m2ThreshExt);
+-skip_ws_det:
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
--- /dev/null
+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
+Date: Sun, 31 Jan 2016 20:48:49 +0100
+Subject: [PATCH v4 2/8] mac80211: ath9k: set default state for platform LEDs
+
+Support default state for platform LEDs connected to ath9k device.
+Now LEDs are correctly set on or off at ath9k module initialization.
+Very useful if power LED is connected to wireless chip.
+
+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
+---
+ gpio.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -74,8 +74,11 @@ static int ath_add_led(struct ath_softc
+ ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name,
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+
+- /* LED off */
+- ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
++ /* Set default LED state */
++ if (gpio->default_state == LEDS_GPIO_DEFSTATE_ON)
++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, !gpio->active_low);
++ else
++ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
+
+ return 0;
+ }
--- /dev/null
+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
+Date: Sun, 31 Jan 2016 21:01:31 +0100
+Subject: [PATCH v4 4/8] mac80211: ath9k: enable access to GPIO
+
+Enable access to GPIO chip and its pins for Atheros AR92xx
+wireless devices. For now AR9285 and AR9287 are supported.
+
+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -24,6 +24,7 @@
+ #include <linux/completion.h>
+ #include <linux/time.h>
+ #include <linux/hw_random.h>
++#include <linux/gpio/driver.h>
+
+ #include "common.h"
+ #include "debug.h"
+@@ -1001,6 +1002,14 @@ struct ath_led {
+ struct led_classdev cdev;
+ };
+
++#ifdef CONFIG_GPIOLIB
++struct ath9k_gpio_chip {
++ struct ath_softc *sc;
++ char label[32];
++ struct gpio_chip gchip;
++};
++#endif
++
+ struct ath_softc {
+ struct ieee80211_hw *hw;
+ struct device *dev;
+@@ -1058,6 +1067,9 @@ struct ath_softc {
+ #ifdef CPTCFG_MAC80211_LEDS
+ const char *led_default_trigger;
+ struct list_head leds;
++#ifdef CONFIG_GPIOLIB
++ struct ath9k_gpio_chip *gpiochip;
++#endif
+ #endif
+
+ #ifdef CPTCFG_ATH9K_DEBUGFS
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -16,13 +16,130 @@
+
+ #include "ath9k.h"
+ #include <linux/ath9k_platform.h>
++#include <linux/gpio.h>
++
++#ifdef CPTCFG_MAC80211_LEDS
++
++#ifdef CONFIG_GPIOLIB
++
++/***************/
++/* GPIO Chip */
++/***************/
++
++/* gpio_chip handler : set GPIO to input */
++static int ath9k_gpio_pin_cfg_input(struct gpio_chip *chip, unsigned offset)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++
++ ath9k_hw_gpio_request_in(gc->sc->sc_ah, offset, "ath9k-gpio");
++
++ return 0;
++}
++
++/* gpio_chip handler : set GPIO to output */
++static int ath9k_gpio_pin_cfg_output(struct gpio_chip *chip, unsigned offset,
++ int value)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++
++ ath9k_hw_gpio_request_out(gc->sc->sc_ah, offset, "ath9k-gpio",
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
++
++ return 0;
++}
++
++/* gpio_chip handler : query GPIO direction (0=out, 1=in) */
++static int ath9k_gpio_pin_get_dir(struct gpio_chip *chip, unsigned offset)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++ struct ath_hw *ah = gc->sc->sc_ah;
++
++ return !((REG_READ(ah, AR_GPIO_OE_OUT) >> (offset * 2)) & 3);
++}
++
++/* gpio_chip handler : get GPIO pin value */
++static int ath9k_gpio_pin_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++
++ return ath9k_hw_gpio_get(gc->sc->sc_ah, offset);
++}
++
++/* gpio_chip handler : set GPIO pin to value */
++static void ath9k_gpio_pin_set(struct gpio_chip *chip, unsigned offset,
++ int value)
++{
++ struct ath9k_gpio_chip *gc = container_of(chip, struct ath9k_gpio_chip,
++ gchip);
++
++ ath9k_hw_set_gpio(gc->sc->sc_ah, offset, value);
++}
++
++/* register GPIO chip */
++static void ath9k_register_gpio_chip(struct ath_softc *sc)
++{
++ struct ath9k_gpio_chip *gc;
++ struct ath_hw *ah = sc->sc_ah;
++
++ gc = kzalloc(sizeof(struct ath9k_gpio_chip), GFP_KERNEL);
++ if (!gc)
++ return;
++
++ gc->sc = sc;
++ snprintf(gc->label, sizeof(gc->label), "ath9k-%s",
++ wiphy_name(sc->hw->wiphy));
++
++ gc->gchip.label = gc->label;
++ gc->gchip.base = -1; /* determine base automatically */
++ gc->gchip.ngpio = ah->caps.num_gpio_pins;
++ gc->gchip.direction_input = ath9k_gpio_pin_cfg_input;
++ gc->gchip.direction_output = ath9k_gpio_pin_cfg_output;
++ gc->gchip.get_direction = ath9k_gpio_pin_get_dir;
++ gc->gchip.get = ath9k_gpio_pin_get;
++ gc->gchip.set = ath9k_gpio_pin_set;
++
++ if (gpiochip_add(&gc->gchip)) {
++ kfree(gc);
++ return;
++ }
++
++ sc->gpiochip = gc;
++}
++
++/* remove GPIO chip */
++static void ath9k_unregister_gpio_chip(struct ath_softc *sc)
++{
++ struct ath9k_gpio_chip *gc = sc->gpiochip;
++
++ if (!gc)
++ return;
++
++ gpiochip_remove(&gc->gchip);
++ kfree(gc);
++ sc->gpiochip = NULL;
++}
++
++#else /* CONFIG_GPIOLIB */
++
++static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
++{
++}
++
++static inline void ath9k_unregister_gpio_chip(struct ath_softc *sc)
++{
++}
++
++#endif /* CONFIG_GPIOLIB */
+
+ /********************************/
+ /* LED functions */
+ /********************************/
+
+-#ifdef CPTCFG_MAC80211_LEDS
+-
+ static void ath_fill_led_pin(struct ath_softc *sc)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+@@ -80,6 +197,12 @@ static int ath_add_led(struct ath_softc
+ else
+ ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low);
+
++#ifdef CONFIG_GPIOLIB
++ /* If there is GPIO chip configured, reserve LED pin */
++ if (sc->gpiochip)
++ gpio_request(sc->gpiochip->gchip.base + gpio->gpio, gpio->name);
++#endif
++
+ return 0;
+ }
+
+@@ -136,17 +259,24 @@ void ath_deinit_leds(struct ath_softc *s
+
+ while (!list_empty(&sc->leds)) {
+ led = list_first_entry(&sc->leds, struct ath_led, list);
++#ifdef CONFIG_GPIOLIB
++ /* If there is GPIO chip configured, free LED pin */
++ if (sc->gpiochip)
++ gpio_free(sc->gpiochip->gchip.base + led->gpio->gpio);
++#endif
+ list_del(&led->list);
+ ath_led_brightness(&led->cdev, LED_OFF);
+ led_classdev_unregister(&led->cdev);
+ ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio);
+ kfree(led);
+ }
++ ath9k_unregister_gpio_chip(sc);
+ }
+
+ void ath_init_leds(struct ath_softc *sc)
+ {
+ struct ath9k_platform_data *pdata = sc->dev->platform_data;
++ struct device_node *np = sc->dev->of_node;
+ char led_name[32];
+ const char *trigger;
+ int i;
+@@ -156,6 +286,15 @@ void ath_init_leds(struct ath_softc *sc)
+ if (AR_SREV_9100(sc->sc_ah))
+ return;
+
++ if (!np)
++ ath9k_register_gpio_chip(sc);
++
++ /* setup gpio controller only if requested and skip the led_pin setup */
++ if (of_property_read_bool(np, "gpio-controller")) {
++ ath9k_register_gpio_chip(sc);
++ return;
++ }
++
+ ath_fill_led_pin(sc);
+
+ if (pdata && pdata->leds && pdata->num_leds)
+@@ -180,6 +319,7 @@ void ath_init_leds(struct ath_softc *sc)
+ ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger,
+ !sc->sc_ah->config.led_active_high);
+ }
++
+ #endif
+
+ /*******************/
--- /dev/null
+From: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
+Subject: [PATCH v5 5/8] mac80211: ath9k: enable GPIO buttons
+
+Enable platform-defined GPIO button support for ath9k device.
+Key poller is activated for attached platform buttons.
+Requires ath9k GPIO chip access.
+
+Signed-off-by: Michal Cieslakiewicz <michal.cieslakiewicz@wp.pl>
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -1069,6 +1069,7 @@ struct ath_softc {
+ struct list_head leds;
+ #ifdef CONFIG_GPIOLIB
+ struct ath9k_gpio_chip *gpiochip;
++ struct platform_device *btnpdev; /* gpio-keys-polled */
+ #endif
+ #endif
+
+--- a/drivers/net/wireless/ath/ath9k/gpio.c
++++ b/drivers/net/wireless/ath/ath9k/gpio.c
+@@ -17,6 +17,8 @@
+ #include "ath9k.h"
+ #include <linux/ath9k_platform.h>
+ #include <linux/gpio.h>
++#include <linux/platform_device.h>
++#include <linux/gpio_keys.h>
+
+ #ifdef CPTCFG_MAC80211_LEDS
+
+@@ -124,6 +126,67 @@ static void ath9k_unregister_gpio_chip(s
+ sc->gpiochip = NULL;
+ }
+
++/******************/
++/* GPIO Buttons */
++/******************/
++
++/* add GPIO buttons */
++static void ath9k_init_buttons(struct ath_softc *sc)
++{
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
++ struct platform_device *pdev;
++ struct gpio_keys_platform_data gkpdata;
++ struct gpio_keys_button *bt;
++ int i;
++
++ if (!sc->gpiochip)
++ return;
++
++ if (!pdata || !pdata->btns || !pdata->num_btns)
++ return;
++
++ bt = devm_kmemdup(sc->dev, pdata->btns,
++ pdata->num_btns * sizeof(struct gpio_keys_button),
++ GFP_KERNEL);
++ if (!bt)
++ return;
++
++ for (i = 0; i < pdata->num_btns; i++) {
++ if (pdata->btns[i].gpio == sc->sc_ah->led_pin)
++ sc->sc_ah->led_pin = -1;
++
++ ath9k_hw_gpio_request_in(sc->sc_ah, pdata->btns[i].gpio,
++ "ath9k-gpio");
++ bt[i].gpio = sc->gpiochip->gchip.base + pdata->btns[i].gpio;
++ }
++
++ memset(&gkpdata, 0, sizeof(struct gpio_keys_platform_data));
++ gkpdata.buttons = bt;
++ gkpdata.nbuttons = pdata->num_btns;
++ gkpdata.poll_interval = pdata->btn_poll_interval;
++
++ pdev = platform_device_register_data(sc->dev, "gpio-keys-polled",
++ PLATFORM_DEVID_AUTO, &gkpdata,
++ sizeof(gkpdata));
++ if (!IS_ERR_OR_NULL(pdev))
++ sc->btnpdev = pdev;
++ else {
++ sc->btnpdev = NULL;
++ devm_kfree(sc->dev, bt);
++ }
++}
++
++/* remove GPIO buttons */
++static void ath9k_deinit_buttons(struct ath_softc *sc)
++{
++ if (!sc->gpiochip || !sc->btnpdev)
++ return;
++
++ platform_device_unregister(sc->btnpdev);
++
++ sc->btnpdev = NULL;
++}
++
+ #else /* CONFIG_GPIOLIB */
+
+ static inline void ath9k_register_gpio_chip(struct ath_softc *sc)
+@@ -134,6 +197,14 @@ static inline void ath9k_unregister_gpio
+ {
+ }
+
++static inline void ath9k_init_buttons(struct ath_softc *sc)
++{
++}
++
++static inline void ath9k_deinit_buttons(struct ath_softc *sc)
++{
++}
++
+ #endif /* CONFIG_GPIOLIB */
+
+ /********************************/
+@@ -257,6 +328,7 @@ void ath_deinit_leds(struct ath_softc *s
+ {
+ struct ath_led *led;
+
++ ath9k_deinit_buttons(sc);
+ while (!list_empty(&sc->leds)) {
+ led = list_first_entry(&sc->leds, struct ath_led, list);
+ #ifdef CONFIG_GPIOLIB
+@@ -296,6 +368,7 @@ void ath_init_leds(struct ath_softc *sc)
+ }
+
+ ath_fill_led_pin(sc);
++ ath9k_init_buttons(sc);
+
+ if (pdata && pdata->leds && pdata->num_leds)
+ for (i = 0; i < pdata->num_leds; i++) {
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -49,6 +49,10 @@ struct ath9k_platform_data {
+
+ int num_leds;
+ const struct gpio_led *leds;
++
++ unsigned num_btns;
++ const struct gpio_keys_button *btns;
++ unsigned btn_poll_interval;
+ };
+
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/init.c
++++ b/drivers/net/wireless/ath/ath9k/init.c
+@@ -571,6 +571,12 @@ static int ath9k_of_init(struct ath_soft
+
+ ath_dbg(common, CONFIG, "parsing configuration from OF node\n");
+
++ if (of_property_read_bool(np, "qca,disable-2ghz"))
++ ah->disable_2ghz = true;
++
++ if (of_property_read_bool(np, "qca,disable-5ghz"))
++ ah->disable_5ghz = true;
++
+ if (of_property_read_bool(np, "qca,no-eeprom")) {
+ /* ath9k-eeprom-<bus>-<id>.bin */
+ scnprintf(eeprom_name, sizeof(eeprom_name),
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/channel.c
++++ b/drivers/net/wireless/ath/ath9k/channel.c
+@@ -15,6 +15,8 @@
+ */
+
+ #include "ath9k.h"
++#include <linux/ath9k_platform.h>
++#include "hsr.h"
+
+ /* Set/change channels. If the channel is really being changed, it's done
+ * by reseting the chip. To accomplish this we must first cleanup any pending
+@@ -22,6 +24,7 @@
+ */
+ static int ath_set_channel(struct ath_softc *sc)
+ {
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_hw *hw = sc->hw;
+@@ -42,6 +45,11 @@ static int ath_set_channel(struct ath_so
+ ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
+ chan->center_freq, chandef->width);
+
++ if (pdata && pdata->ubnt_hsr) {
++ ath9k_hsr_enable(ah, chandef->width, chan->center_freq);
++ ath9k_hsr_status(ah);
++ }
++
+ /* update survey stats for the old channel before switching */
+ spin_lock_irqsave(&common->cc_lock, flags);
+ ath_update_survey_stats(sc);
+--- /dev/null
++++ b/drivers/net/wireless/ath/ath9k/hsr.c
+@@ -0,0 +1,247 @@
++/*
++ *
++ * The MIT License (MIT)
++ *
++ * Copyright (c) 2015 Kirill Berezin
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to deal
++ * in the Software without restriction, including without limitation the rights
++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ * copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
++
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/time.h>
++#include <linux/bitops.h>
++#include <linux/etherdevice.h>
++#include <linux/rtnetlink.h>
++#include <asm/unaligned.h>
++
++#include "hw.h"
++#include "ath9k.h"
++
++#define HSR_GPIO_CSN 8
++#define HSR_GPIO_CLK 6
++#define HSR_GPIO_DOUT 7
++#define HSR_GPIO_DIN 5
++
++/* delays are in useconds */
++#define HSR_DELAY_HALF_TICK 100
++#define HSR_DELAY_PRE_WRITE 75
++#define HSR_DELAY_FINAL 20000
++#define HSR_DELAY_TRAILING 200
++
++void ath9k_hsr_init(struct ath_hw *ah)
++{
++ ath9k_hw_gpio_request_in(ah, HSR_GPIO_DIN, NULL);
++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CSN, NULL,
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_CLK, NULL,
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++ ath9k_hw_gpio_request_out(ah, HSR_GPIO_DOUT, NULL,
++ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0);
++
++ udelay(HSR_DELAY_TRAILING);
++}
++
++static u32 ath9k_hsr_write_byte(struct ath_hw *ah, int delay, u32 value)
++{
++ struct ath_common *common = ath9k_hw_common(ah);
++ int i;
++ u32 rval = 0;
++
++ udelay(delay);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ for (i = 0; i < 8; ++i) {
++ rval = rval << 1;
++
++ /* pattern is left to right, that is 7-th bit runs first */
++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN);
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0);
++ udelay(HSR_DELAY_HALF_TICK);
++ }
++
++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1);
++ udelay(HSR_DELAY_HALF_TICK);
++
++ ath_dbg(common, CONFIG, "ath9k_hsr_write_byte: write byte %d return value is %d %c\n",
++ value, rval, rval > 32 ? rval : '-');
++
++ return rval & 0xff;
++}
++
++static int ath9k_hsr_write_a_chain(struct ath_hw *ah, char *chain, int items)
++{
++ int status = 0;
++ int i = 0;
++ int err;
++
++ /* a preamble */
++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++
++ /* clear HSR's reply buffer */
++ if (status) {
++ int loop = 0;
++
++ for (loop = 0; (loop < 42) && status; ++loop)
++ status = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE,
++ 0);
++
++ if (loop >= 42) {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_write_a_chain: can't clear an output buffer after a 42 cycles.\n");
++ return -1;
++ }
++ }
++
++ for (i = 0; (i < items) && (chain[i] != 0); ++i)
++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]);
++
++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++ mdelay(HSR_DELAY_FINAL / 1000);
++
++ /* reply */
++ memset(chain, 0, items);
++
++ ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++ udelay(HSR_DELAY_TRAILING);
++
++ for (i = 0; i < (items - 1); ++i) {
++ u32 ret;
++
++ ret = ath9k_hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0);
++ if (ret != 0)
++ chain[i] = (char)ret;
++ else
++ break;
++
++ udelay(HSR_DELAY_TRAILING);
++ }
++
++ if (i <= 1)
++ return 0;
++
++ err = kstrtoint(chain + 1, 10, &i);
++ if (err)
++ return err;
++
++ return i;
++}
++
++int ath9k_hsr_disable(struct ath_hw *ah)
++{
++ char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0};
++ int ret;
++
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if ((ret > 0) && (*cmd == 'B'))
++ return 0;
++
++ return -1;
++}
++
++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq)
++{
++ char cmd[10];
++ int ret;
++
++ /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn
++ * 20MHz on invalid values
++ */
++ if ((bw != 5) && (bw != 10) && (bw != 20) && (bw != 40))
++ bw = 20;
++
++ memset(cmd, 0, sizeof(cmd));
++ *cmd = 'b';
++ snprintf(cmd + 1, 3, "%02d", bw);
++
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if ((*cmd != 'B') || (ret != bw)) {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d)\n",
++ 'b', bw, *cmd, ret);
++ return -1;
++ }
++
++ memset(cmd, 0, sizeof(cmd));
++ *cmd = 'x';
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if (*cmd != 'X') {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_enable: failed 'x' command -> reply (%d, %d)\n",
++ *cmd, ret);
++ return -1;
++ }
++
++ memset(cmd, 0, sizeof(cmd));
++ *cmd = 'm';
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if (*cmd != 'M') {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_enable: failed 'm' command -> reply (%d, %d)\n",
++ *cmd, ret);
++ return -1;
++ }
++
++ memset(cmd, 0, sizeof(cmd));
++ *cmd = 'f';
++ snprintf(cmd + 1, 6, "%05d", fq);
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if ((*cmd != 'F') && (ret != fq)) {
++ ATH_DBG_WARN(1,
++ "ath9k_hsr_enable: failed set frequency -> reply (%d, %d)\n",
++ *cmd, ret);
++ return -1;
++ }
++
++ return 0;
++}
++
++int ath9k_hsr_status(struct ath_hw *ah)
++{
++ char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0};
++ int ret;
++
++ ret = ath9k_hsr_write_a_chain(ah, cmd, sizeof(cmd));
++ if (*cmd != 'S') {
++ ATH_DBG_WARN(1, "ath9k_hsr_status: returned %d,%d\n", *cmd,
++ ret);
++ return -1;
++ }
++
++ return 0;
++}
+--- /dev/null
++++ b/drivers/net/wireless/ath/ath9k/hsr.h
+@@ -0,0 +1,48 @@
++/*
++ * The MIT License (MIT)
++ *
++ * Copyright (c) 2015 Kirill Berezin
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a copy
++ * of this software and associated documentation files (the "Software"), to deal
++ * in the Software without restriction, including without limitation the rights
++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++ * copies of the Software, and to permit persons to whom the Software is
++ * furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef HSR_H
++#define HSR_H
++
++#ifdef CPTCFG_ATH9K_UBNTHSR
++
++void ath9k_hsr_init(struct ath_hw *ah);
++int ath9k_hsr_disable(struct ath_hw *ah);
++int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq);
++int ath9k_hsr_status(struct ath_hw *ah);
++
++#else
++static inline void ath9k_hsr_init(struct ath_hw *ah) {}
++
++static inline int ath9k_hsr_enable(struct ath_hw *ah, int bw, int fq)
++{
++ return 0;
++}
++
++static inline int ath9k_hsr_disable(struct ath_hw *ah) { return 0; }
++static inline int ath9k_hsr_status(struct ath_hw *ah) { return 0; }
++
++#endif
++
++#endif /* HSR_H */
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -16,8 +16,10 @@
+
+ #include <linux/nl80211.h>
+ #include <linux/delay.h>
++#include <linux/ath9k_platform.h>
+ #include "ath9k.h"
+ #include "btcoex.h"
++#include "hsr.h"
+
+ u8 ath9k_parse_mpdudensity(u8 mpdudensity)
+ {
+@@ -649,6 +651,7 @@ void ath_reset_work(struct work_struct *
+ static int ath9k_start(struct ieee80211_hw *hw)
+ {
+ struct ath_softc *sc = hw->priv;
++ struct ath9k_platform_data *pdata = sc->dev->platform_data;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan;
+@@ -727,6 +730,11 @@ static int ath9k_start(struct ieee80211_
+ AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+ }
+
++ if (pdata && pdata->ubnt_hsr) {
++ ath9k_hsr_init(ah);
++ ath9k_hsr_disable(ah);
++ }
++
+ /*
+ * Reset key cache to sane defaults (all entries cleared) instead of
+ * semi-random values after suspend/resume.
+--- a/drivers/net/wireless/ath/ath9k/Makefile
++++ b/drivers/net/wireless/ath/ath9k/Makefile
+@@ -16,6 +16,7 @@ ath9k-$(CPTCFG_ATH9K_DFS_CERTIFIED) += d
+ ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o
+ ath9k-$(CPTCFG_ATH9K_WOW) += wow.o
+ ath9k-$(CPTCFG_ATH9K_HWRNG) += rng.o
++ath9k-$(CPTCFG_ATH9K_UBNTHSR) += hsr.o
+
+ ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o
+
+--- a/include/linux/ath9k_platform.h
++++ b/include/linux/ath9k_platform.h
+@@ -53,6 +53,8 @@ struct ath9k_platform_data {
+ unsigned num_btns;
+ const struct gpio_keys_button *btns;
+ unsigned btn_poll_interval;
++
++ bool ubnt_hsr;
+ };
+
+ #endif /* _LINUX_ATH9K_PLATFORM_H */
+--- a/local-symbols
++++ b/local-symbols
+@@ -114,6 +114,7 @@ ATH9K_WOW=
+ ATH9K_RFKILL=
+ ATH9K_CHANNEL_CONTEXT=
+ ATH9K_PCOEM=
++ATH9K_UBNTHSR=
+ ATH9K_HTC=
+ ATH9K_HTC_DEBUGFS=
+ ATH9K_HWRNG=
+--- a/drivers/net/wireless/ath/ath9k/Kconfig
++++ b/drivers/net/wireless/ath/ath9k/Kconfig
+@@ -59,6 +59,19 @@ config ATH9K_AHB
+ Say Y, if you have a SoC with a compatible built-in
+ wireless MAC. Say N if unsure.
+
++config ATH9K_UBNTHSR
++ bool "Ubiquiti UniFi Outdoor Plus HSR support"
++ depends on ATH9K
++ ---help---
++ This options enables code to control the HSR RF
++ filter in the receive path of the Ubiquiti UniFi
++ Outdoor Plus access point.
++
++ Say Y if you want to use the access point. The
++ code will only be used if the device is detected,
++ so it does not harm other setup other than occupying
++ a bit of memory.
++
+ config ATH9K_DEBUGFS
+ bool "Atheros ath9k debugging"
+ depends on ATH9K && DEBUG_FS
--- /dev/null
+--- a/drivers/net/wireless/ath/ath9k/ahb.c
++++ b/drivers/net/wireless/ath/ath9k/ahb.c
+@@ -19,7 +19,15 @@
+ #include <linux/nl80211.h>
+ #include <linux/platform_device.h>
+ #include <linux/module.h>
++#include <linux/of_device.h>
+ #include "ath9k.h"
++#include <linux/ath9k_platform.h>
++
++#ifdef CONFIG_OF
++#include <asm/mach-ath79/ath79.h>
++#include <asm/mach-ath79/ar71xx_regs.h>
++#include <linux/mtd/mtd.h>
++#endif
+
+ static const struct platform_device_id ath9k_platform_id_table[] = {
+ {
+@@ -68,6 +76,235 @@ static const struct ath_bus_ops ath_ahb_
+ .eeprom_read = ath_ahb_eeprom_read,
+ };
+
++#ifdef CONFIG_OF
++
++#define QCA955X_DDR_CTL_CONFIG 0x108
++#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23)
++
++static int of_get_wifi_cal(struct device_node *np, struct ath9k_platform_data *pdata)
++{
++#ifdef CONFIG_MTD
++ struct device_node *mtd_np = NULL;
++ size_t retlen;
++ int size, ret;
++ struct mtd_info *mtd;
++ const char *part;
++ const __be32 *list;
++ phandle phandle;
++
++ list = of_get_property(np, "mtd-cal-data", &size);
++ if (!list)
++ return 0;
++
++ if (size != (2 * sizeof(*list)))
++ return 1;
++
++ phandle = be32_to_cpup(list++);
++ if (phandle)
++ mtd_np = of_find_node_by_phandle(phandle);
++
++ if (!mtd_np)
++ return 1;
++
++ part = of_get_property(mtd_np, "label", NULL);
++ if (!part)
++ part = mtd_np->name;
++
++ mtd = get_mtd_device_nm(part);
++ if (IS_ERR(mtd))
++ return 1;
++
++ ret = mtd_read(mtd, be32_to_cpup(list), sizeof(pdata->eeprom_data),
++ &retlen, (u8*)pdata->eeprom_data);
++ put_mtd_device(mtd);
++
++#endif
++ return 0;
++}
++
++static int ar913x_wmac_reset(void)
++{
++ ath79_device_reset_set(AR913X_RESET_AMBA2WMAC);
++ mdelay(10);
++
++ ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC);
++ mdelay(10);
++
++ return 0;
++}
++
++static int ar933x_wmac_reset(void)
++{
++ int retries = 20;
++
++ ath79_device_reset_set(AR933X_RESET_WMAC);
++ ath79_device_reset_clear(AR933X_RESET_WMAC);
++
++ while (1) {
++ u32 bootstrap;
++
++ bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
++ if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0)
++ return 0;
++
++ if (retries-- == 0)
++ break;
++
++ udelay(10000);
++ }
++
++ pr_err("ar933x: WMAC reset timed out");
++ return -ETIMEDOUT;
++}
++
++static int qca955x_wmac_reset(void)
++{
++ int i;
++
++ /* Try to wait for WMAC DDR activity to stop */
++ for (i = 0; i < 10; i++) {
++ if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) &
++ QCA955X_DDR_CTL_CONFIG_ACT_WMAC))
++ break;
++
++ udelay(10);
++ }
++
++ ath79_device_reset_set(QCA955X_RESET_RTC);
++ udelay(10);
++ ath79_device_reset_clear(QCA955X_RESET_RTC);
++ udelay(10);
++
++ return 0;
++}
++
++enum {
++ AR913X_WMAC = 0,
++ AR933X_WMAC,
++ AR934X_WMAC,
++ QCA953X_WMAC,
++ QCA955X_WMAC,
++ QCA956X_WMAC,
++};
++
++static int ar9330_get_soc_revision(void)
++{
++ if (ath79_soc_rev == 1)
++ return ath79_soc_rev;
++
++ return 0;
++}
++
++static int ath79_get_soc_revision(void)
++{
++ return ath79_soc_rev;
++}
++
++static const struct of_ath_ahb_data {
++ u16 dev_id;
++ u32 bootstrap_reg;
++ u32 bootstrap_ref;
++
++ int (*soc_revision)(void);
++ int (*wmac_reset)(void);
++} of_ath_ahb_data[] = {
++ [AR913X_WMAC] = {
++ .dev_id = AR5416_AR9100_DEVID,
++ .wmac_reset = ar913x_wmac_reset,
++
++ },
++ [AR933X_WMAC] = {
++ .dev_id = AR9300_DEVID_AR9330,
++ .bootstrap_reg = AR933X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = AR933X_BOOTSTRAP_REF_CLK_40,
++ .soc_revision = ar9330_get_soc_revision,
++ .wmac_reset = ar933x_wmac_reset,
++ },
++ [AR934X_WMAC] = {
++ .dev_id = AR9300_DEVID_AR9340,
++ .bootstrap_reg = AR934X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = AR934X_BOOTSTRAP_REF_CLK_40,
++ .soc_revision = ath79_get_soc_revision,
++ },
++ [QCA953X_WMAC] = {
++ .dev_id = AR9300_DEVID_AR953X,
++ .bootstrap_reg = QCA953X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = QCA953X_BOOTSTRAP_REF_CLK_40,
++ .soc_revision = ath79_get_soc_revision,
++ },
++ [QCA955X_WMAC] = {
++ .dev_id = AR9300_DEVID_QCA955X,
++ .bootstrap_reg = QCA955X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = QCA955X_BOOTSTRAP_REF_CLK_40,
++ .wmac_reset = qca955x_wmac_reset,
++ },
++ [QCA956X_WMAC] = {
++ .dev_id = AR9300_DEVID_QCA956X,
++ .bootstrap_reg = QCA956X_RESET_REG_BOOTSTRAP,
++ .bootstrap_ref = QCA956X_BOOTSTRAP_REF_CLK_40,
++ .soc_revision = ath79_get_soc_revision,
++ },
++};
++
++const struct of_device_id of_ath_ahb_match[] = {
++ { .compatible = "qca,ar9130-wmac", .data = &of_ath_ahb_data[AR913X_WMAC] },
++ { .compatible = "qca,ar9330-wmac", .data = &of_ath_ahb_data[AR933X_WMAC] },
++ { .compatible = "qca,ar9340-wmac", .data = &of_ath_ahb_data[AR934X_WMAC] },
++ { .compatible = "qca,qca9530-wmac", .data = &of_ath_ahb_data[QCA953X_WMAC] },
++ { .compatible = "qca,qca9550-wmac", .data = &of_ath_ahb_data[QCA955X_WMAC] },
++ { .compatible = "qca,qca9560-wmac", .data = &of_ath_ahb_data[QCA956X_WMAC] },
++ {},
++};
++MODULE_DEVICE_TABLE(of, of_ath_ahb_match);
++
++static int of_ath_ahb_probe(struct platform_device *pdev)
++{
++ struct ath9k_platform_data *pdata;
++ const struct of_device_id *match;
++ const struct of_ath_ahb_data *data;
++ u8 led_pin;
++
++ match = of_match_device(of_ath_ahb_match, &pdev->dev);
++ data = (const struct of_ath_ahb_data *)match->data;
++
++ pdata = dev_get_platdata(&pdev->dev);
++
++ if (!of_property_read_u8(pdev->dev.of_node, "qca,led-pin", &led_pin))
++ pdata->led_pin = led_pin;
++ else
++ pdata->led_pin = -1;
++
++ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-2ghz"))
++ pdata->disable_2ghz = true;
++
++ if (of_property_read_bool(pdev->dev.of_node, "qca,disable-5ghz"))
++ pdata->disable_5ghz = true;
++
++ if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo"))
++ pdata->tx_gain_buffalo = true;
++
++ if (data->wmac_reset) {
++ data->wmac_reset();
++ pdata->external_reset = data->wmac_reset;
++ }
++
++ if (data->bootstrap_reg && data->bootstrap_ref) {
++ u32 t = ath79_reset_rr(data->bootstrap_reg);
++ if (t & data->bootstrap_ref)
++ pdata->is_clk_25mhz = false;
++ else
++ pdata->is_clk_25mhz = true;
++ }
++
++ pdata->get_mac_revision = data->soc_revision;
++
++ if (of_get_wifi_cal(pdev->dev.of_node, pdata))
++ dev_err(&pdev->dev, "failed to load calibration data from mtd device\n");
++
++ return data->dev_id;
++}
++#endif
++
+ static int ath_ahb_probe(struct platform_device *pdev)
+ {
+ void __iomem *mem;
+@@ -79,6 +316,17 @@ static int ath_ahb_probe(struct platform
+ int ret = 0;
+ struct ath_hw *ah;
+ char hw_name[64];
++ u16 dev_id;
++
++ if (id)
++ dev_id = id->driver_data;
++
++#ifdef CONFIG_OF
++ if (pdev->dev.of_node)
++ pdev->dev.platform_data = devm_kzalloc(&pdev->dev,
++ sizeof(struct ath9k_platform_data),
++ GFP_KERNEL);
++#endif
+
+ if (!dev_get_platdata(&pdev->dev)) {
+ dev_err(&pdev->dev, "no platform data specified\n");
+@@ -121,13 +369,16 @@ static int ath_ahb_probe(struct platform
+ sc->mem = mem;
+ sc->irq = irq;
+
++#ifdef CONFIG_OF
++ dev_id = of_ath_ahb_probe(pdev);
++#endif
+ ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq failed\n");
+ goto err_free_hw;
+ }
+
+- ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
++ ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize device\n");
+ goto err_irq;
+@@ -158,6 +409,9 @@ static int ath_ahb_remove(struct platfor
+ free_irq(sc->irq, sc);
+ ieee80211_free_hw(sc->hw);
+ }
++#ifdef CONFIG_OF
++ pdev->dev.platform_data = NULL;
++#endif
+
+ return 0;
+ }
+@@ -167,6 +421,9 @@ static struct platform_driver ath_ahb_dr
+ .remove = ath_ahb_remove,
+ .driver = {
+ .name = "ath9k",
++#ifdef CONFIG_OF
++ .of_match_table = of_ath_ahb_match,
++#endif
+ },
+ .id_table = ath9k_platform_id_table,
+ };
+--- a/drivers/net/wireless/ath/ath9k/ath9k.h
++++ b/drivers/net/wireless/ath/ath9k/ath9k.h
+@@ -25,6 +25,7 @@
+ #include <linux/time.h>
+ #include <linux/hw_random.h>
+ #include <linux/gpio/driver.h>
++#include <linux/reset.h>
+
+ #include "common.h"
+ #include "debug.h"
+@@ -1023,6 +1024,9 @@ struct ath_softc {
+ struct ath_hw *sc_ah;
+ void __iomem *mem;
+ int irq;
++#ifdef CONFIG_OF
++ struct reset_control *reset;
++#endif
+ spinlock_t sc_serial_rw;
+ spinlock_t sc_pm_lock;
+ spinlock_t sc_pcu_lock;
--- /dev/null
+From: Sven Eckelmann <sven@open-mesh.com>
+Date: Tue, 18 Nov 2014 12:29:28 +0100
+Subject: [PATCH] ath10k: Don't initialize devices asynchronously
+
+OpenWrt requires all PHYs to be initialized to create the configuration files
+during bootup. ath10k violates this because it delays the creation of the PHY
+to a not well defined point in the future.
+
+Forcing the work to be done immediately works around this problem but may also
+delay the boot when firmware images cannot be found.
+
+Signed-off-by: Sven Eckelmann <sven@open-mesh.com>
+---
+
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -2507,6 +2507,16 @@ int ath10k_core_register(struct ath10k *
+ ar->chip_id = chip_id;
+ queue_work(ar->workqueue, &ar->register_work);
+
++ /* OpenWrt requires all PHYs to be initialized to create the
++ * configuration files during bootup. ath10k violates this
++ * because it delays the creation of the PHY to a not well defined
++ * point in the future.
++ *
++ * Forcing the work to be done immediately works around this problem
++ * but may also delay the boot when firmware images cannot be found.
++ */
++ flush_workqueue(ar->workqueue);
++
+ return 0;
+ }
+ EXPORT_SYMBOL(ath10k_core_register);
--- /dev/null
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -8122,6 +8122,21 @@ static int ath10k_mac_init_rd(struct ath
+ return 0;
+ }
+
++#ifdef CPTCFG_MAC80211_LEDS
++static const struct ieee80211_tpt_blink ath10k_tpt_blink[] = {
++ { .throughput = 0 * 1024, .blink_time = 334 },
++ { .throughput = 1 * 1024, .blink_time = 260 },
++ { .throughput = 2 * 1024, .blink_time = 220 },
++ { .throughput = 5 * 1024, .blink_time = 190 },
++ { .throughput = 10 * 1024, .blink_time = 170 },
++ { .throughput = 25 * 1024, .blink_time = 150 },
++ { .throughput = 54 * 1024, .blink_time = 130 },
++ { .throughput = 120 * 1024, .blink_time = 110 },
++ { .throughput = 265 * 1024, .blink_time = 80 },
++ { .throughput = 586 * 1024, .blink_time = 50 },
++};
++#endif
++
+ int ath10k_mac_register(struct ath10k *ar)
+ {
+ static const u32 cipher_suites[] = {
+@@ -8397,6 +8412,12 @@ int ath10k_mac_register(struct ath10k *a
+
+ wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
++#ifdef CPTCFG_MAC80211_LEDS
++ ieee80211_create_tpt_led_trigger(ar->hw,
++ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink,
++ ARRAY_SIZE(ath10k_tpt_blink));
++#endif
++
+ ret = ieee80211_register_hw(ar->hw);
+ if (ret) {
+ ath10k_err(ar, "failed to register ieee80211: %d\n", ret);
--- /dev/null
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -783,7 +783,7 @@ static int ath10k_core_get_board_id_from
+ if (ret) {
+ ath10k_err(ar, "could not execute otp for board id check: %d\n",
+ ret);
+- return ret;
++ return -EOPNOTSUPP;
+ }
+
+ board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP);
--- /dev/null
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/htt.h
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/htt.h
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/htt.h
+@@ -238,7 +238,7 @@ enum htt_rx_ring_flags {
+ };
+
+ #define HTT_RX_RING_SIZE_MIN 128
+-#define HTT_RX_RING_SIZE_MAX 2048
++#define HTT_RX_RING_SIZE_MAX 512
+ #define HTT_RX_RING_SIZE HTT_RX_RING_SIZE_MAX
+ #define HTT_RX_RING_FILL_LEVEL (((HTT_RX_RING_SIZE) / 2) - 1)
+ #define HTT_RX_RING_FILL_LEVEL_DUAL_MAC (HTT_RX_RING_SIZE - 1)
--- /dev/null
+--- a/drivers/net/wireless/ath/ath10k/pci.c
++++ b/drivers/net/wireless/ath/ath10k/pci.c
+@@ -128,7 +128,7 @@ static struct ce_attr host_ce_config_wla
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+- .dest_nentries = 512,
++ .dest_nentries = 128,
+ .recv_cb = ath10k_pci_htt_htc_rx_cb,
+ },
+
+@@ -137,7 +137,7 @@ static struct ce_attr host_ce_config_wla
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+- .dest_nentries = 128,
++ .dest_nentries = 64,
+ .recv_cb = ath10k_pci_htc_rx_cb,
+ },
+
+@@ -164,7 +164,7 @@ static struct ce_attr host_ce_config_wla
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 512,
+- .dest_nentries = 512,
++ .dest_nentries = 128,
+ .recv_cb = ath10k_pci_htt_rx_cb,
+ },
+
+@@ -189,7 +189,7 @@ static struct ce_attr host_ce_config_wla
+ .flags = CE_ATTR_FLAGS,
+ .src_nentries = 0,
+ .src_sz_max = 2048,
+- .dest_nentries = 128,
++ .dest_nentries = 96,
+ .recv_cb = ath10k_pci_pktlog_rx_cb,
+ },
+
--- /dev/null
+From: Sebastian Gottschall <s.gottschall@dd-wrt.com>
+
+current handling of peer_bw_rxnss_override parameter is based on guessing the VHT160/8080 capability by rx rate. this is wrong and may lead
+to a non initialized peer_bw_rxnss_override parameter which is required since VHT160 operation mode only supports 2x2 chainmasks in addition the original code
+initialized the parameter with wrong masked values.
+This patch uses the peer phymode and peer nss information for correct initialisation of the peer_bw_rxnss_override parameter.
+if this peer information is not available, we initialize the parameter by minimum nss which is suggested by QCA as temporary workaround according
+to the QCA sourcecodes.
+
+Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
+
+v2: remove debug messages
+v3: apply some cosmetics, update documentation
+v4: fix compile warning and truncate nss to maximum of 2x2 since current chipsets only support 2x2 at vht160
+v5: handle maximum nss for chipsets supportig vht160 with 1x1 only
+v7: use more simple code variant and take care about hw/sw chainmask configuration
+v8: fix some code style issues
+v9: use SM/MS macros from code.h to simplify shift/mask handling
+---
+ drivers/net/wireless/ath/ath10k/mac.c | 54 +++++++++++++++++++--------
+ drivers/net/wireless/ath/ath10k/wmi.c | 7 +---
+ drivers/net/wireless/ath/ath10k/wmi.h | 14 ++++++-
+ 3 files changed, 52 insertions(+), 23 deletions(-)
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -2466,7 +2466,7 @@ static void ath10k_peer_assoc_h_vht(stru
+ const u16 *vht_mcs_mask;
+ u8 ampdu_factor;
+ u8 max_nss, vht_mcs;
+- int i;
++ int i, nss160;
+
+ if (WARN_ON(ath10k_mac_vif_chan(vif, &def)))
+ return;
+@@ -2526,23 +2526,45 @@ static void ath10k_peer_assoc_h_vht(stru
+ __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
+ arg->peer_vht_rates.tx_mcs_set = ath10k_peer_assoc_h_vht_limit(
+ __le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask);
++ arg->peer_bw_rxnss_override = 0;
++ nss160 = 1; /* 1x1 default config for VHT160 */
+
+- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
+- sta->addr, arg->peer_max_mpdu, arg->peer_flags);
++ /* only local 4x4 configuration do support 2x2 for VHT160,
++ * everything else must use 1x1
++ */
+
+- if (arg->peer_vht_rates.rx_max_rate &&
+- (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) {
+- switch (arg->peer_vht_rates.rx_max_rate) {
+- case 1560:
+- /* Must be 2x2 at 160Mhz is all it can do. */
+- arg->peer_bw_rxnss_override = 2;
+- break;
+- case 780:
+- /* Can only do 1x1 at 160Mhz (Long Guard Interval) */
+- arg->peer_bw_rxnss_override = 1;
+- break;
+- }
++ if (ar->cfg_rx_chainmask == 15)
++ nss160 = arg->peer_num_spatial_streams <= 2 ? 1 : 2;
++
++ /* if peer provides 1x1 nss160 information using max rate
++ * vht information, we reduce local nss160 to 1x1.
++ * consider that it has been observed that some client
++ * devices provide zero here, no matter which transmission
++ * rate is possible. in that case the local nss configuration
++ * will be used at maxmimum configuration possible. (see above)
++ */
++
++ if (arg->peer_vht_rates.rx_max_rate == 780)
++ nss160 = 1;
++
++ /* in case if peer is connected with vht160 or vht80+80,
++ * we need to properly adjust rxnss parameters otherwise
++ * firmware will raise a assert
++ */
++ switch (arg->peer_phymode) {
++ case MODE_11AC_VHT80_80:
++ arg->peer_bw_rxnss_override = BW_NSS_FWCONF_80_80(nss160);
++ /* fall through */
++ case MODE_11AC_VHT160:
++ arg->peer_bw_rxnss_override |= BW_NSS_FWCONF_160(nss160);
++ break;
++ default:
++ break;
+ }
++
++ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x peer_bw_rxnss_override 0x%x\n",
++ sta->addr, arg->peer_max_mpdu, arg->peer_flags,
++ arg->peer_bw_rxnss_override);
+ }
+
+ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
+@@ -2694,9 +2716,9 @@ static int ath10k_peer_assoc_prepare(str
+ ath10k_peer_assoc_h_crypto(ar, vif, sta, arg);
+ ath10k_peer_assoc_h_rates(ar, vif, sta, arg);
+ ath10k_peer_assoc_h_ht(ar, vif, sta, arg);
++ ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
+ ath10k_peer_assoc_h_vht(ar, vif, sta, arg);
+ ath10k_peer_assoc_h_qos(ar, vif, sta, arg);
+- ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
+
+ return 0;
+ }
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -7231,12 +7231,7 @@ ath10k_wmi_peer_assoc_fill_10_4(struct a
+ struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
+
+ ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
+- if (arg->peer_bw_rxnss_override)
+- cmd->peer_bw_rxnss_override =
+- __cpu_to_le32((arg->peer_bw_rxnss_override - 1) |
+- BIT(PEER_BW_RXNSS_OVERRIDE_OFFSET));
+- else
+- cmd->peer_bw_rxnss_override = 0;
++ cmd->peer_bw_rxnss_override = __cpu_to_le32(arg->peer_bw_rxnss_override);
+ }
+
+ static int
+--- a/drivers/net/wireless/ath/ath10k/wmi.h
++++ b/drivers/net/wireless/ath/ath10k/wmi.h
+@@ -6306,7 +6306,19 @@ struct wmi_10_2_peer_assoc_complete_cmd
+ __le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
+ } __packed;
+
+-#define PEER_BW_RXNSS_OVERRIDE_OFFSET 31
++#define BW_NSS_FWCONF_MAP_ENABLE BIT(31)
++#define BW_NSS_FWCONF_MAP_160MHZ_LSB (0)
++#define BW_NSS_FWCONF_MAP_160MHZ_MASK (0x00000007)
++#define BW_NSS_FWCONF_MAP_80_80MHZ_LSB (3)
++#define BW_NSS_FWCONF_MAP_80_80MHZ_MASK (0x00000038)
++#define BW_NSS_FWCONF_MAP_MASK (0x0000003F)
++
++#define GET_BW_NSS_FWCONF_160(x) (MS(x, BW_NSS_FWCONF_MAP_160MHZ) + 1)
++#define GET_BW_NSS_FWCONF_80_80(x) (MS(x, BW_NSS_FWCONF_MAP_80_80MHZ) + 1)
++
++/* Values defined to set 160 MHz Bandwidth NSS Mapping into FW*/
++#define BW_NSS_FWCONF_160(x) (BW_NSS_FWCONF_MAP_ENABLE | SM(x - 1, BW_NSS_FWCONF_MAP_160MHZ))
++#define BW_NSS_FWCONF_80_80(x) (BW_NSS_FWCONF_MAP_ENABLE | SM(x - 1, BW_NSS_FWCONF_MAP_80_80MHZ))
+
+ struct wmi_10_4_peer_assoc_complete_cmd {
+ struct wmi_10_2_peer_assoc_complete_cmd cmd;
--- /dev/null
+From: Sebastian Gottschall <s.gottschall@dd-wrt.com>
+
+starting with firmware 10.4.3.4.x series QCA changed the handling of the channel property band_center_freq1 and band_center_freq2 in vht160 operation mode
+likelly for backward compatiblity with vht80 only capable clients.
+this patch adjusts the handling to get vht160 to work again with official qca firmwares newer than 3.3
+consider that this patch will not work with older firmwares anymore. to avoid undefined behaviour this we disable vht160 capability for outdated firmwares
+Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
+
+v2: fix trailing whitespace issue and fix some typos within the commit note
+---
+ drivers/net/wireless/ath/ath10k/mac.c | 7 -------
+ drivers/net/wireless/ath/ath10k/wmi.c | 11 ++++++++---
+ 2 files changed, 8 insertions(+), 10 deletions(-)
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -4445,13 +4445,6 @@ static struct ieee80211_sta_vht_cap ath1
+ vht_cap.cap |= val;
+ }
+
+- /* Currently the firmware seems to be buggy, don't enable 80+80
+- * mode until that's resolved.
+- */
+- if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) &&
+- (ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == 0)
+- vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+-
+ mcs_map = 0;
+ for (i = 0; i < 8; i++) {
+ if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -1672,13 +1672,18 @@ void ath10k_wmi_put_wmi_channel(struct w
+ flags |= WMI_CHAN_FLAG_HT40_PLUS;
+ if (arg->chan_radar)
+ flags |= WMI_CHAN_FLAG_DFS;
+-
++ ch->band_center_freq2 = 0;
+ ch->mhz = __cpu_to_le32(arg->freq);
+ ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
+ if (arg->mode == MODE_11AC_VHT80_80)
+ ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq2);
+- else
+- ch->band_center_freq2 = 0;
++ if (arg->mode == MODE_11AC_VHT160) {
++ if (arg->freq < arg->band_center_freq1)
++ ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1 - 40);
++ else
++ ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1 + 40);
++ ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq1);
++ }
+ ch->min_power = arg->min_power;
+ ch->max_power = arg->max_power;
+ ch->reg_power = arg->max_reg_power;
--- /dev/null
+From: Sebastian Gottschall <s.gottschall@newmedia-net.de>
+
+Adds LED and GPIO Control support for 988x, 9887, 9888, 99x0, 9984 based
+chipsets with on chipset connected led's using WMI Firmware API. The LED
+device will get available named as "ath10k-phyX" at sysfs and can be controlled
+with various triggers. adds also debugfs interface for gpio control.
+
+This patch is specific for OpenWRt base, as is use old backported package
+with old wireless source. Support for QCA9984 is removed and a simbol
+is added to local-simbol file to export the actually compile the code
+with the ATH10K_LEDS simbol.
+
+
+Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
+Reviewed-by: Steve deRosier <derosier@cal-sierra.com>
+[kvalo: major reorg and cleanup]
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
+---
+
+v13:
+
+* only compile tested!
+
+* fix all checkpatch warnings
+
+* fix commit log
+
+* sizeof(struct ath10k_gpiocontrol) -> sizeof(*gpio)
+
+* unsigned -> unsigned int
+
+* remove GPIOLIB code, that should be added in a separate patch
+
+* rename gpio.c to leds.c
+
+* add leds.h
+
+* rename some functions:
+
+ ath10k_attach_led() -> ath10k_leds_register()
+ ath10k_unregister_led() -> ath10k_leds_unregister()
+ ath10k_reset_led_pin() -> ath10k_leds_start()
+
+* call ath10k_leds_unregister() before ath10k_thermal_unregister() to preserve ordering
+
+* call ath10k_leds_start() only from ath10k_core_start() and not from mac.c
+
+* rename struct ath10k_gpiocontrol as anonymous function under struct
+ ath10k::leds, no need for memory allocation
+
+* merge ath10k_add_led() to ath10k_attach_led(), which is it's only caller
+
+* remove #if IS_ENABLED() checks from most of places, memory savings from those were not worth it
+
+* Kconfig help text improvement and move it lower in the menu, also don't enable it by default
+
+* switch to set_brightness_blocking() so that the callback can sleep,
+ then no need to use ath10k_wmi_cmd_send_nowait() and can take mutex
+ to access ar->state
+
+* don't touch ath10k_wmi_pdev_get_temperature()
+
+* as QCA6174/QCA9377 are not (yet) supported don't add the command to WMI-TLV interface
+
+* remove debugfs interface, that should be added in another patch
+
+* cleanup includes
+
+
+ drivers/net/wireless/ath/ath10k/Kconfig | 10 +++
+ drivers/net/wireless/ath/ath10k/Makefile | 1 +
+ drivers/net/wireless/ath/ath10k/core.c | 22 +++++++
+ drivers/net/wireless/ath/ath10k/core.h | 9 ++-
+ drivers/net/wireless/ath/ath10k/hw.h | 1 +
+ drivers/net/wireless/ath/ath10k/leds.c | 103 ++++++++++++++++++++++++++++++
+ drivers/net/wireless/ath/ath10k/leds.h | 45 +++++++++++++
+ drivers/net/wireless/ath/ath10k/mac.c | 1 +
+ drivers/net/wireless/ath/ath10k/wmi-ops.h | 32 ++++++++++
+ drivers/net/wireless/ath/ath10k/wmi-tlv.c | 2 +
+ drivers/net/wireless/ath/ath10k/wmi.c | 54 ++++++++++++++++
+ drivers/net/wireless/ath/ath10k/wmi.h | 35 ++++++++++
+ 12 files changed, 314 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/net/wireless/ath/ath10k/leds.c
+ create mode 100644 drivers/net/wireless/ath/ath10k/leds.h
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/Kconfig
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/Kconfig
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/Kconfig
+@@ -69,6 +69,16 @@ config ATH10K_DEBUGFS
+
+ If unsure, say Y to make it easier to debug problems.
+
++config ATH10K_LEDS
++ bool "Atheros ath10k LED support"
++ depends on ATH10K
++ select MAC80211_LEDS
++ select LEDS_CLASS
++ select NEW_LEDS
++ default y
++ ---help---
++ This option is necessary, if you want LED support for chipset connected led pins. If unsure, say N.
++
+ config ATH10K_SPECTRAL
+ bool "Atheros ath10k spectral scan support"
+ depends on ATH10K_DEBUGFS
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/Makefile
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/Makefile
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/Makefile
+@@ -19,6 +19,7 @@ ath10k_core-$(CPTCFG_ATH10K_SPECTRAL) +=
+ ath10k_core-$(CPTCFG_NL80211_TESTMODE) += testmode.o
+ ath10k_core-$(CPTCFG_ATH10K_TRACING) += trace.o
+ ath10k_core-$(CPTCFG_ATH10K_THERMAL) += thermal.o
++ath10k_core-$(CPTCFG_ATH10K_LEDS) += leds.o
+ ath10k_core-$(CPTCFG_MAC80211_DEBUGFS) += debugfs_sta.o
+ ath10k_core-$(CONFIG_PM) += wow.o
+ ath10k_core-$(CONFIG_DEV_COREDUMP) += coredump.o
+Index: backports-v4.18-rc7/local-symbols
+===================================================================
+--- backports-v4.18-rc7.orig/local-symbols
++++ backports-v4.18-rc7/local-symbols
+@@ -147,6 +147,7 @@ ATH10K_DEBUG=
+ ATH10K_DEBUGFS=
+ ATH10K_SPECTRAL=
+ ATH10K_THERMAL=
++ATH10K_LEDS=
+ ATH10K_TRACING=
+ ATH10K_DFS_CERTIFIED=
+ WCN36XX=
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/core.c
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/core.c
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/core.c
+@@ -34,6 +34,7 @@
+ #include "testmode.h"
+ #include "wmi-ops.h"
+ #include "coredump.h"
++#include "leds.h"
+
+ unsigned int ath10k_debug_mask;
+ static unsigned int ath10k_cryptmode_param;
+@@ -66,6 +67,7 @@ static const struct ath10k_hw_params ath
+ .id = QCA988X_HW_2_0_VERSION,
+ .dev_id = QCA988X_2_0_DEVICE_ID,
+ .name = "qca988x hw2.0",
++ .led_pin = 1,
+ .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
+@@ -129,6 +131,7 @@ static const struct ath10k_hw_params ath
+ .id = QCA9887_HW_1_0_VERSION,
+ .dev_id = QCA9887_1_0_DEVICE_ID,
+ .name = "qca9887 hw1.0",
++ .led_pin = 1,
+ .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_ALL,
+@@ -288,6 +291,7 @@ static const struct ath10k_hw_params ath
+ .id = QCA99X0_HW_2_0_DEV_VERSION,
+ .dev_id = QCA99X0_2_0_DEVICE_ID,
+ .name = "qca99x0 hw2.0",
++ .led_pin = 17,
+ .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .otp_exe_param = 0x00000700,
+@@ -325,6 +329,7 @@ static const struct ath10k_hw_params ath
+ .id = QCA9984_HW_1_0_DEV_VERSION,
+ .dev_id = QCA9984_1_0_DEVICE_ID,
+ .name = "qca9984/qca9994 hw1.0",
++ .led_pin = 17,
+ .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
+@@ -367,6 +372,7 @@ static const struct ath10k_hw_params ath
+ .id = QCA9888_HW_2_0_DEV_VERSION,
+ .dev_id = QCA9888_2_0_DEVICE_ID,
+ .name = "qca9888 hw2.0",
++ .led_pin = 17,
+ .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR,
+ .uart_pin = 7,
+ .cc_wraparound_type = ATH10K_HW_CC_WRAP_SHIFTED_EACH,
+@@ -2428,6 +2434,10 @@ int ath10k_core_start(struct ath10k *ar,
+ if (status)
+ goto err_hif_stop;
+
++ status = ath10k_leds_start(ar);
++ if (status)
++ goto err_hif_stop;
++
+ return 0;
+
+ err_hif_stop:
+@@ -2682,9 +2692,18 @@ static void ath10k_core_register_work(st
+ goto err_spectral_destroy;
+ }
+
++ status = ath10k_leds_register(ar);
++ if (status) {
++ ath10k_err(ar, "could not register leds: %d\n",
++ status);
++ goto err_thermal_unregister;
++ }
++
+ set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
+ return;
+
++err_thermal_unregister:
++ ath10k_thermal_unregister(ar);
+ err_spectral_destroy:
+ ath10k_spectral_destroy(ar);
+ err_debug_destroy:
+@@ -2728,6 +2747,8 @@ void ath10k_core_unregister(struct ath10
+ if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
+ return;
+
++ ath10k_leds_unregister(ar);
++
+ ath10k_thermal_unregister(ar);
+ /* Stop spectral before unregistering from mac80211 to remove the
+ * relayfs debugfs file cleanly. Otherwise the parent debugfs tree
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/core.h
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/core.h
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/core.h
+@@ -25,6 +25,7 @@
+ #include <linux/pci.h>
+ #include <linux/uuid.h>
+ #include <linux/time.h>
++#include <linux/leds.h>
+
+ #include "htt.h"
+ #include "htc.h"
+@@ -902,7 +903,6 @@ struct ath10k {
+ u32 low_5ghz_chan;
+ u32 high_5ghz_chan;
+ bool ani_enabled;
+-
+ bool p2p;
+
+ struct {
+@@ -1093,6 +1093,13 @@ struct ath10k {
+ } testmode;
+
+ struct {
++ struct gpio_led wifi_led;
++ struct led_classdev cdev;
++ char label[48];
++ u32 gpio_state_pin;
++ } leds;
++
++ struct {
+ /* protected by data_lock */
+ u32 fw_crash_counter;
+ u32 fw_warm_reset_counter;
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/hw.h
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/hw.h
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/hw.h
+@@ -504,6 +504,7 @@ struct ath10k_hw_params {
+ const char *name;
+ u32 patch_load_addr;
+ int uart_pin;
++ int led_pin;
+ u32 otp_exe_param;
+
+ /* Type of hw cycle counter wraparound logic, for more info
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/leds.c
+===================================================================
+--- /dev/null
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/leds.c
+@@ -0,0 +1,103 @@
++/*
++ * Copyright (c) 2005-2011 Atheros Communications Inc.
++ * Copyright (c) 2011-2017 Qualcomm Atheros, Inc.
++ * Copyright (c) 2018 Sebastian Gottschall <s.gottschall@dd-wrt.com>
++ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++
++#include <linux/leds.h>
++
++#include "core.h"
++#include "wmi.h"
++#include "wmi-ops.h"
++
++#include "leds.h"
++
++static int ath10k_leds_set_brightness_blocking(struct led_classdev *led_cdev,
++ enum led_brightness brightness)
++{
++ struct ath10k *ar = container_of(led_cdev, struct ath10k,
++ leds.cdev);
++ struct gpio_led *led = &ar->leds.wifi_led;
++
++ mutex_lock(&ar->conf_mutex);
++
++ if (ar->state != ATH10K_STATE_ON)
++ goto out;
++
++ ar->leds.gpio_state_pin = (brightness != LED_OFF) ^ led->active_low;
++ ath10k_wmi_gpio_output(ar, led->gpio, ar->leds.gpio_state_pin);
++
++out:
++ mutex_unlock(&ar->conf_mutex);
++
++ return 0;
++}
++
++int ath10k_leds_start(struct ath10k *ar)
++{
++ if (ar->hw_params.led_pin == 0)
++ /* leds not supported */
++ return 0;
++
++ /* under some circumstances, the gpio pin gets reconfigured
++ * to default state by the firmware, so we need to
++ * reconfigure it this behaviour has only ben seen on
++ * QCA9984 and QCA99XX devices so far
++ */
++ ath10k_wmi_gpio_config(ar, ar->hw_params.led_pin, 0,
++ WMI_GPIO_PULL_NONE, WMI_GPIO_INTTYPE_DISABLE);
++ ath10k_wmi_gpio_output(ar, ar->hw_params.led_pin, 1);
++
++ return 0;
++}
++
++int ath10k_leds_register(struct ath10k *ar)
++{
++ int ret;
++
++ if (ar->hw_params.led_pin == 0)
++ /* leds not supported */
++ return 0;
++
++ snprintf(ar->leds.label, sizeof(ar->leds.label), "ath10k-%s",
++ wiphy_name(ar->hw->wiphy));
++ ar->leds.wifi_led.active_low = 1;
++ ar->leds.wifi_led.gpio = ar->hw_params.led_pin;
++ ar->leds.wifi_led.name = ar->leds.label;
++ ar->leds.wifi_led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
++
++ ar->leds.cdev.name = ar->leds.label;
++ ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking;
++
++ /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */
++ ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger;
++
++ ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++void ath10k_leds_unregister(struct ath10k *ar)
++{
++ if (ar->hw_params.led_pin == 0)
++ /* leds not supported */
++ return;
++
++ led_classdev_unregister(&ar->leds.cdev);
++}
++
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/leds.h
+===================================================================
+--- /dev/null
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/leds.h
+@@ -0,0 +1,41 @@
++/*
++ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
++ *
++ * Permission to use, copy, modify, and/or distribute this software for any
++ * purpose with or without fee is hereby granted, provided that the above
++ * copyright notice and this permission notice appear in all copies.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++ */
++#ifndef _LEDS_H_
++#define _LEDS_H_
++
++#include "core.h"
++
++#ifdef CPTCFG_ATH10K_LEDS
++void ath10k_leds_unregister(struct ath10k *ar);
++int ath10k_leds_start(struct ath10k *ar);
++int ath10k_leds_register(struct ath10k *ar);
++#else
++static inline void ath10k_leds_unregister(struct ath10k *ar)
++{
++}
++
++static inline int ath10k_leds_start(struct ath10k *ar)
++{
++ return 0;
++}
++
++static inline int ath10k_leds_register(struct ath10k *ar)
++{
++ return 0;
++}
++
++#endif
++#endif /* _LEDS_H_ */
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/mac.c
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/mac.c
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/mac.c
+@@ -33,6 +33,7 @@
+ #include "wmi-tlv.h"
+ #include "wmi-ops.h"
+ #include "wow.h"
++#include "leds.h"
+
+ /*********/
+ /* Rates */
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/wmi-ops.h
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/wmi-ops.h
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/wmi-ops.h
+@@ -214,7 +214,10 @@ struct wmi_ops {
+ struct sk_buff *(*gen_echo)(struct ath10k *ar, u32 value);
+ struct sk_buff *(*gen_pdev_get_tpc_table_cmdid)(struct ath10k *ar,
+ u32 param);
++ struct sk_buff *(*gen_gpio_config)(struct ath10k *ar, u32 gpio_num,
++ u32 input, u32 pull_type, u32 intr_mode);
+
++ struct sk_buff *(*gen_gpio_output)(struct ath10k *ar, u32 gpio_num, u32 set);
+ };
+
+ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
+@@ -1042,6 +1045,35 @@ ath10k_wmi_force_fw_hang(struct ath10k *
+ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid);
+ }
+
++static inline int ath10k_wmi_gpio_config(struct ath10k *ar, u32 gpio_num,
++ u32 input, u32 pull_type, u32 intr_mode)
++{
++ struct sk_buff *skb;
++
++ if (!ar->wmi.ops->gen_gpio_config)
++ return -EOPNOTSUPP;
++
++ skb = ar->wmi.ops->gen_gpio_config(ar, gpio_num, input, pull_type, intr_mode);
++ if (IS_ERR(skb))
++ return PTR_ERR(skb);
++
++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_config_cmdid);
++}
++
++static inline int ath10k_wmi_gpio_output(struct ath10k *ar, u32 gpio_num, u32 set)
++{
++ struct sk_buff *skb;
++
++ if (!ar->wmi.ops->gen_gpio_config)
++ return -EOPNOTSUPP;
++
++ skb = ar->wmi.ops->gen_gpio_output(ar, gpio_num, set);
++ if (IS_ERR(skb))
++ return PTR_ERR(skb);
++
++ return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->gpio_output_cmdid);
++}
++
+ static inline int
+ ath10k_wmi_dbglog_cfg(struct ath10k *ar, u64 module_enable, u32 log_level)
+ {
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/wmi-tlv.c
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+@@ -3909,6 +3909,8 @@ static const struct wmi_ops wmi_tlv_ops
+ .gen_echo = ath10k_wmi_tlv_op_gen_echo,
+ .gen_vdev_spectral_conf = ath10k_wmi_tlv_op_gen_vdev_spectral_conf,
+ .gen_vdev_spectral_enable = ath10k_wmi_tlv_op_gen_vdev_spectral_enable,
++ /* .gen_gpio_config not implemented */
++ /* .gen_gpio_output not implemented */
+ };
+
+ static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/wmi.c
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/wmi.c
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -7115,6 +7115,49 @@ ath10k_wmi_op_gen_peer_set_param(struct
+ return skb;
+ }
+
++static struct sk_buff *ath10k_wmi_op_gen_gpio_config(struct ath10k *ar,
++ u32 gpio_num, u32 input,
++ u32 pull_type, u32 intr_mode)
++{
++ struct wmi_gpio_config_cmd *cmd;
++ struct sk_buff *skb;
++
++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
++ if (!skb)
++ return ERR_PTR(-ENOMEM);
++
++ cmd = (struct wmi_gpio_config_cmd *)skb->data;
++ cmd->pull_type = __cpu_to_le32(pull_type);
++ cmd->gpio_num = __cpu_to_le32(gpio_num);
++ cmd->input = __cpu_to_le32(input);
++ cmd->intr_mode = __cpu_to_le32(intr_mode);
++
++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_config gpio_num 0x%08x input 0x%08x pull_type 0x%08x intr_mode 0x%08x\n",
++ gpio_num, input, pull_type, intr_mode);
++
++ return skb;
++}
++
++static struct sk_buff *ath10k_wmi_op_gen_gpio_output(struct ath10k *ar,
++ u32 gpio_num, u32 set)
++{
++ struct wmi_gpio_output_cmd *cmd;
++ struct sk_buff *skb;
++
++ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
++ if (!skb)
++ return ERR_PTR(-ENOMEM);
++
++ cmd = (struct wmi_gpio_output_cmd *)skb->data;
++ cmd->gpio_num = __cpu_to_le32(gpio_num);
++ cmd->set = __cpu_to_le32(set);
++
++ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi gpio_output gpio_num 0x%08x set 0x%08x\n",
++ gpio_num, set);
++
++ return skb;
++}
++
+ static struct sk_buff *
+ ath10k_wmi_op_gen_set_psmode(struct ath10k *ar, u32 vdev_id,
+ enum wmi_sta_ps_mode psmode)
+@@ -8726,6 +8769,9 @@ static const struct wmi_ops wmi_ops = {
+ .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
+ .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
+ .gen_echo = ath10k_wmi_op_gen_echo,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
++
+ /* .gen_bcn_tmpl not implemented */
+ /* .gen_prb_tmpl not implemented */
+ /* .gen_p2p_go_bcn_ie not implemented */
+@@ -8796,6 +8842,8 @@ static const struct wmi_ops wmi_10_1_ops
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
+ .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
+ .gen_echo = ath10k_wmi_op_gen_echo,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
+ /* .gen_bcn_tmpl not implemented */
+ /* .gen_prb_tmpl not implemented */
+ /* .gen_p2p_go_bcn_ie not implemented */
+@@ -8867,6 +8915,8 @@ static const struct wmi_ops wmi_10_2_ops
+ .gen_delba_send = ath10k_wmi_op_gen_delba_send,
+ .fw_stats_fill = ath10k_wmi_10x_op_fw_stats_fill,
+ .get_vdev_subtype = ath10k_wmi_op_get_vdev_subtype,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
+ /* .gen_pdev_enable_adaptive_cca not implemented */
+ };
+
+@@ -8937,6 +8987,8 @@ static const struct wmi_ops wmi_10_2_4_o
+ .gen_pdev_enable_adaptive_cca =
+ ath10k_wmi_op_gen_pdev_enable_adaptive_cca,
+ .get_vdev_subtype = ath10k_wmi_10_2_4_op_get_vdev_subtype,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
+ /* .gen_bcn_tmpl not implemented */
+ /* .gen_prb_tmpl not implemented */
+ /* .gen_p2p_go_bcn_ie not implemented */
+@@ -9016,6 +9068,8 @@ static const struct wmi_ops wmi_10_4_ops
+ .gen_pdev_bss_chan_info_req = ath10k_wmi_10_2_op_gen_pdev_bss_chan_info,
+ .gen_echo = ath10k_wmi_op_gen_echo,
+ .gen_pdev_get_tpc_config = ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config,
++ .gen_gpio_config = ath10k_wmi_op_gen_gpio_config,
++ .gen_gpio_output = ath10k_wmi_op_gen_gpio_output,
+ };
+
+ int ath10k_wmi_attach(struct ath10k *ar)
+Index: backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/wmi.h
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/ath/ath10k/wmi.h
++++ backports-v4.18-rc7/drivers/net/wireless/ath/ath10k/wmi.h
+@@ -2941,6 +2941,41 @@ enum wmi_10_4_feature_mask {
+
+ };
+
++/* WMI_GPIO_CONFIG_CMDID */
++enum {
++ WMI_GPIO_PULL_NONE,
++ WMI_GPIO_PULL_UP,
++ WMI_GPIO_PULL_DOWN,
++};
++
++enum {
++ WMI_GPIO_INTTYPE_DISABLE,
++ WMI_GPIO_INTTYPE_RISING_EDGE,
++ WMI_GPIO_INTTYPE_FALLING_EDGE,
++ WMI_GPIO_INTTYPE_BOTH_EDGE,
++ WMI_GPIO_INTTYPE_LEVEL_LOW,
++ WMI_GPIO_INTTYPE_LEVEL_HIGH
++};
++
++/* WMI_GPIO_CONFIG_CMDID */
++struct wmi_gpio_config_cmd {
++ __le32 gpio_num; /* GPIO number to be setup */
++ __le32 input; /* 0 - Output/ 1 - Input */
++ __le32 pull_type; /* Pull type defined above */
++ __le32 intr_mode; /* Interrupt mode defined above (Input) */
++} __packed;
++
++/* WMI_GPIO_OUTPUT_CMDID */
++struct wmi_gpio_output_cmd {
++ __le32 gpio_num; /* GPIO number to be setup */
++ __le32 set; /* Set the GPIO pin*/
++} __packed;
++
++/* WMI_GPIO_INPUT_EVENTID */
++struct wmi_gpio_input_event {
++ __le32 gpio_num; /* GPIO number which changed state */
++} __packed;
++
+ struct wmi_ext_resource_config_10_4_cmd {
+ /* contains enum wmi_host_platform_type */
+ __le32 host_platform_config;
--- /dev/null
+From 79c9d7aabae1d1da9eea97d83b61e1517a8a2221 Mon Sep 17 00:00:00 2001
+From: Mathias Kresin <dev@kresin.me>
+Date: Fri, 22 Jun 2018 18:59:44 +0200
+Subject: [PATCH] ath10k: use tpt LED trigger by default
+
+Use the tpt LED trigger for each created phy led. Ths way LEDs attached
+to the ath10k GPIO pins are indicating the phy status and blink on
+traffic.
+
+Signed-off-by: Mathias Kresin <dev@kresin.me>
+---
+ drivers/net/wireless/ath/ath10k/core.h | 4 ++++
+ drivers/net/wireless/ath/ath10k/leds.c | 4 +---
+ drivers/net/wireless/ath/ath10k/mac.c | 2 +-
+ 3 files changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath10k/core.h
++++ b/drivers/net/wireless/ath/ath10k/core.h
+@@ -1055,6 +1055,10 @@ struct ath10k {
+ struct ath10k_radar_found_info last_radar_info;
+ struct work_struct radar_confirmation_work;
+
++#ifdef CPTCFG_MAC80211_LEDS
++ const char *led_default_trigger;
++#endif
++
+ /* must be last */
+ u8 drv_priv[0] __aligned(sizeof(void *));
+ };
+--- a/drivers/net/wireless/ath/ath10k/leds.c
++++ b/drivers/net/wireless/ath/ath10k/leds.c
+@@ -81,9 +81,7 @@ int ath10k_leds_register(struct ath10k *
+
+ ar->leds.cdev.name = ar->leds.label;
+ ar->leds.cdev.brightness_set_blocking = ath10k_leds_set_brightness_blocking;
+-
+- /* FIXME: this assignment doesn't make sense as it's NULL, remove it? */
+- ar->leds.cdev.default_trigger = ar->leds.wifi_led.default_trigger;
++ ar->leds.cdev.default_trigger = ar->led_default_trigger;
+
+ ret = led_classdev_register(wiphy_dev(ar->hw->wiphy), &ar->leds.cdev);
+ if (ret)
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -8429,7 +8429,7 @@ int ath10k_mac_register(struct ath10k *a
+ wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
+ #ifdef CPTCFG_MAC80211_LEDS
+- ieee80211_create_tpt_led_trigger(ar->hw,
++ ar->led_default_trigger = ieee80211_create_tpt_led_trigger(ar->hw,
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath10k_tpt_blink,
+ ARRAY_SIZE(ath10k_tpt_blink));
+ #endif
--- /dev/null
+From bbf0a8af2261bc7ae39b227ff6a1e9f45a008c27 Mon Sep 17 00:00:00 2001
+From: Sven Eckelmann <sven.eckelmann@openmesh.com>
+Date: Mon, 30 Jul 2018 17:31:41 +0200
+Subject: [PATCH] ath10k: Limit available channels via DT ieee80211-freq-limit
+
+Tri-band devices (1x 2.4GHz + 2x 5GHz) often incorporate special filters in
+the RX and TX path. These filtered channel can in theory still be used by
+the hardware but the signal strength is reduced so much that it makes no
+sense.
+
+There is already a DT property to limit the available channels but ath10k
+has to manually call this functionality to limit the currrently set wiphy
+channels further.
+
+Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
+
+Forwarded: https://patchwork.kernel.org/patch/10549245/
+---
+ drivers/net/wireless/ath/ath10k/mac.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath10k/mac.c
++++ b/drivers/net/wireless/ath/ath10k/mac.c
+@@ -17,6 +17,7 @@
+
+ #include "mac.h"
+
++#include <net/cfg80211.h>
+ #include <net/mac80211.h>
+ #include <linux/etherdevice.h>
+ #include <linux/acpi.h>
+@@ -8230,6 +8231,7 @@ int ath10k_mac_register(struct ath10k *a
+ ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band;
+ }
+
++ wiphy_read_of_freq_limits(ar->hw->wiphy);
+ ath10k_mac_setup_ht_vht_cap(ar);
+
+ ar->hw->wiphy->interface_modes =
--- /dev/null
+--- a/drivers/net/wireless/broadcom/brcm80211/Kconfig
++++ b/drivers/net/wireless/broadcom/brcm80211/Kconfig
+@@ -1,5 +1,5 @@
+ config BRCMUTIL
+- tristate
++ tristate "Broadcom 802.11 driver utility functions"
+ depends on m
+
+ config BRCMSMAC
--- /dev/null
+--- a/drivers/net/wireless/broadcom/b43/b43.h
++++ b/drivers/net/wireless/broadcom/b43/b43.h
+@@ -839,6 +839,7 @@ struct b43_wldev {
+ bool qos_enabled; /* TRUE, if QoS is used. */
+ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
+ bool use_pio; /* TRUE if next init should use PIO */
++ int gpiomask; /* GPIO LED mask as a module parameter */
+
+ /* PHY/Radio device. */
+ struct b43_phy phy;
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -85,6 +85,11 @@ MODULE_FIRMWARE("b43/ucode40.fw");
+ MODULE_FIRMWARE("b43/ucode42.fw");
+ MODULE_FIRMWARE("b43/ucode9.fw");
+
++static int modparam_gpiomask = 0x000F;
++module_param_named(gpiomask, modparam_gpiomask, int, 0444);
++MODULE_PARM_DESC(gpiomask,
++ "GPIO mask for LED control (default 0x000F)");
++
+ static int modparam_bad_frames_preempt;
+ module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
+ MODULE_PARM_DESC(bad_frames_preempt,
+@@ -2892,10 +2897,10 @@ static int b43_gpio_init(struct b43_wlde
+ u32 mask, set;
+
+ b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
+- b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xF);
++ b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, modparam_gpiomask);
+
+ mask = 0x0000001F;
+- set = 0x0000000F;
++ set = modparam_gpiomask;
+ if (dev->dev->chip_id == 0x4301) {
+ mask |= 0x0060;
+ set |= 0x0060;
--- /dev/null
+--- a/drivers/net/wireless/broadcom/b43/Makefile
++++ b/drivers/net/wireless/broadcom/b43/Makefile
+@@ -17,7 +17,7 @@ b43-$(CPTCFG_B43_PHY_AC) += phy_ac.o
+ b43-y += sysfs.o
+ b43-y += xmit.o
+ b43-y += dma.o
+-b43-y += pio.o
++b43-$(CPTCFG_B43_PIO) += pio.o
+ b43-y += rfkill.o
+ b43-y += ppr.o
+ b43-$(CPTCFG_B43_LEDS) += leds.o
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -2018,10 +2018,12 @@ static void b43_do_interrupt_thread(stru
+ dma_reason[0], dma_reason[1],
+ dma_reason[2], dma_reason[3],
+ dma_reason[4], dma_reason[5]);
++#ifdef CPTCFG_B43_PIO
+ b43err(dev->wl, "This device does not support DMA "
+ "on your system. It will now be switched to PIO.\n");
+ /* Fall back to PIO transfers if we get fatal DMA errors! */
+ dev->use_pio = true;
++#endif
+ b43_controller_restart(dev, "DMA error");
+ return;
+ }
+--- a/drivers/net/wireless/broadcom/b43/pio.h
++++ b/drivers/net/wireless/broadcom/b43/pio.h
+@@ -150,7 +150,7 @@ static inline void b43_piorx_write32(str
+ b43_write32(q->dev, q->mmio_base + offset, value);
+ }
+
+-
++#ifdef CPTCFG_B43_PIO
+ int b43_pio_init(struct b43_wldev *dev);
+ void b43_pio_free(struct b43_wldev *dev);
+
+@@ -161,5 +161,37 @@ void b43_pio_rx(struct b43_pio_rxqueue *
+
+ void b43_pio_tx_suspend(struct b43_wldev *dev);
+ void b43_pio_tx_resume(struct b43_wldev *dev);
++#else
++static inline int b43_pio_init(struct b43_wldev *dev)
++{
++ return 0;
++}
++
++static inline void b43_pio_free(struct b43_wldev *dev)
++{
++}
++
++static inline int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
++{
++ return 0;
++}
++
++static inline void b43_pio_handle_txstatus(struct b43_wldev *dev,
++ const struct b43_txstatus *status)
++{
++}
++
++static inline void b43_pio_rx(struct b43_pio_rxqueue *q)
++{
++}
++
++static inline void b43_pio_tx_suspend(struct b43_wldev *dev)
++{
++}
++
++static inline void b43_pio_tx_resume(struct b43_wldev *dev)
++{
++}
++#endif /* CPTCFG_B43_PIO */
+
+ #endif /* B43_PIO_H_ */
+--- a/drivers/net/wireless/broadcom/b43/Kconfig
++++ b/drivers/net/wireless/broadcom/b43/Kconfig
+@@ -98,7 +98,7 @@ config B43_BCMA_PIO
+ default y
+
+ config B43_PIO
+- bool
++ bool "Broadcom 43xx PIO support"
+ depends on B43 && B43_SSB
+ select SSB_BLOCKIO
+ default y
--- /dev/null
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -1658,7 +1658,7 @@ static void b43_write_beacon_template(st
+ len, ram_offset, shm_size_offset, rate);
+
+ /* Write the PHY TX control parameters. */
+- antenna = B43_ANTENNA_DEFAULT;
++ antenna = dev->tx_antenna;
+ 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. */
+@@ -3307,8 +3307,8 @@ static int b43_chip_init(struct b43_wlde
+
+ /* Select the antennae */
+ if (phy->ops->set_rx_antenna)
+- phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT);
+- b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT);
++ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
++ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+
+ if (phy->type == B43_PHYTYPE_B) {
+ value16 = b43_read16(dev, 0x005E);
+@@ -4008,7 +4008,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;
+- int antenna;
+ int err = 0;
+
+ mutex_lock(&wl->mutex);
+@@ -4051,11 +4050,9 @@ static int b43_op_config(struct ieee8021
+ }
+
+ /* Antennas for RX and management frame TX. */
+- antenna = B43_ANTENNA_DEFAULT;
+- b43_mgmtframe_txantenna(dev, antenna);
+- antenna = B43_ANTENNA_DEFAULT;
++ b43_mgmtframe_txantenna(dev, dev->tx_antenna);
+ if (phy->ops->set_rx_antenna)
+- phy->ops->set_rx_antenna(dev, antenna);
++ phy->ops->set_rx_antenna(dev, dev->rx_antenna);
+
+ if (wl->radio_enabled != phy->radio_on) {
+ if (wl->radio_enabled) {
+@@ -5199,6 +5196,47 @@ static int b43_op_get_survey(struct ieee
+ return 0;
+ }
+
++static int b43_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
++{
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++ struct b43_wldev *dev = wl->current_dev;
++
++ if (tx_ant == 1 && rx_ant == 1) {
++ dev->tx_antenna = B43_ANTENNA0;
++ dev->rx_antenna = B43_ANTENNA0;
++ }
++ else if (tx_ant == 2 && rx_ant == 2) {
++ dev->tx_antenna = B43_ANTENNA1;
++ dev->rx_antenna = B43_ANTENNA1;
++ }
++ else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) {
++ dev->tx_antenna = B43_ANTENNA_DEFAULT;
++ dev->rx_antenna = B43_ANTENNA_DEFAULT;
++ }
++ else {
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++
++static int b43_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
++{
++ struct b43_wl *wl = hw_to_b43_wl(hw);
++ struct b43_wldev *dev = wl->current_dev;
++
++ switch (dev->tx_antenna) {
++ case B43_ANTENNA0:
++ *tx_ant = 1; *rx_ant = 1; break;
++ case B43_ANTENNA1:
++ *tx_ant = 2; *rx_ant = 2; break;
++ case B43_ANTENNA_DEFAULT:
++ *tx_ant = 3; *rx_ant = 3; break;
++ }
++ return 0;
++}
++
+ static const struct ieee80211_ops b43_hw_ops = {
+ .tx = b43_op_tx,
+ .conf_tx = b43_op_conf_tx,
+@@ -5220,6 +5258,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,
++ .set_antenna = b43_op_set_antenna,
++ .get_antenna = b43_op_get_antenna,
+ };
+
+ /* Hard-reset the chip. Do not call this directly.
+@@ -5523,6 +5563,8 @@ static int b43_one_core_attach(struct b4
+ if (!wldev)
+ goto out;
+
++ wldev->rx_antenna = B43_ANTENNA_DEFAULT;
++ wldev->tx_antenna = B43_ANTENNA_DEFAULT;
+ wldev->use_pio = b43_modparam_pio;
+ wldev->dev = dev;
+ wldev->wl = wl;
+@@ -5617,6 +5659,9 @@ static struct b43_wl *b43_wireless_init(
+
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
+
++ hw->wiphy->available_antennas_rx = 0x3;
++ hw->wiphy->available_antennas_tx = 0x3;
++
+ wl->hw_registred = false;
+ hw->max_rates = 2;
+ SET_IEEE80211_DEV(hw, dev->dev);
+--- a/drivers/net/wireless/broadcom/b43/b43.h
++++ b/drivers/net/wireless/broadcom/b43/b43.h
+@@ -840,6 +840,8 @@ struct b43_wldev {
+ bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */
+ bool use_pio; /* TRUE if next init should use PIO */
+ int gpiomask; /* GPIO LED mask as a module parameter */
++ int rx_antenna; /* Used RX antenna (B43_ANTENNAxxx) */
++ int tx_antenna; /* Used TX antenna (B43_ANTENNAxxx) */
+
+ /* PHY/Radio device. */
+ struct b43_phy phy;
--- /dev/null
+--- a/drivers/net/wireless/broadcom/b43/dma.h
++++ b/drivers/net/wireless/broadcom/b43/dma.h
+@@ -169,7 +169,7 @@ struct b43_dmadesc_generic {
+
+ /* DMA engine tuning knobs */
+ #define B43_TXRING_SLOTS 256
+-#define B43_RXRING_SLOTS 256
++#define B43_RXRING_SLOTS 32
+ #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
+ #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
+
--- /dev/null
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -2909,6 +2909,14 @@ static int b43_gpio_init(struct b43_wlde
+ } else if (dev->dev->chip_id == 0x5354) {
+ /* Don't allow overtaking buttons GPIOs */
+ set &= 0x2; /* 0x2 is LED GPIO on BCM5354 */
++ } else if (dev->dev->chip_id == BCMA_CHIP_ID_BCM4716 ||
++ dev->dev->chip_id == BCMA_CHIP_ID_BCM47162 ||
++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5356 ||
++ dev->dev->chip_id == BCMA_CHIP_ID_BCM5357 ||
++ dev->dev->chip_id == BCMA_CHIP_ID_BCM53572) {
++ /* just use gpio 0 and 1 for 2.4 GHz wifi led */
++ set &= 0x3;
++ mask &= 0x3;
+ }
+
+ if (0 /* FIXME: conditional unknown */ ) {
--- /dev/null
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -127,7 +127,7 @@ static int b43_modparam_pio = 0;
+ module_param_named(pio, b43_modparam_pio, int, 0644);
+ MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
+
+-static int modparam_allhwsupport = !IS_ENABLED(CPTCFG_BRCMSMAC);
++static int modparam_allhwsupport = 1;
+ module_param_named(allhwsupport, modparam_allhwsupport, int, 0444);
+ MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if overlaps with the brcmsmac driver)");
+
--- /dev/null
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
+@@ -58,19 +58,12 @@
+ (((c) < 149) ? 3 : 4))))
+
+ #define BRCM_2GHZ_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 19, 0)
+-#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, \
+- NL80211_RRF_NO_IR)
++#define BRCM_2GHZ_2467_2472 REG_RULE(2467-10, 2472+10, 20, 0, 19, 0)
+
+-#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, \
+- NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, \
+- NL80211_RRF_DFS | \
+- NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, \
+- NL80211_RRF_DFS | \
+- NL80211_RRF_NO_IR)
+-#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, \
+- NL80211_RRF_NO_IR)
++#define BRCM_5GHZ_5180_5240 REG_RULE(5180-10, 5240+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5260_5320 REG_RULE(5260-10, 5320+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5500_5700 REG_RULE(5500-10, 5700+10, 40, 0, 21, 0)
++#define BRCM_5GHZ_5745_5825 REG_RULE(5745-10, 5825+10, 40, 0, 21, 0)
+
+ static const struct ieee80211_regdomain brcms_regdom_x2 = {
+ .n_reg_rules = 6,
--- /dev/null
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Mon, 8 Jun 2015 16:11:40 +0200
+Subject: [PATCH] brcmfmac: register wiphy(s) during module_init
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is needed by OpenWrt which expects all PHYs to be created after
+module loads successfully.
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -1347,6 +1347,7 @@ int __init brcmf_core_init(void)
+ {
+ if (!schedule_work(&brcmf_driver_work))
+ return -EBUSY;
++ flush_work(&brcmf_driver_work);
+
+ return 0;
+ }
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+@@ -441,6 +441,7 @@ struct brcmf_fw {
+ struct brcmf_fw_request *req;
+ u32 curpos;
+ void (*done)(struct device *dev, int err, struct brcmf_fw_request *req);
++ struct completion *completion;
+ };
+
+ static void brcmf_fw_request_done(const struct firmware *fw, void *ctx);
+@@ -589,6 +590,8 @@ fail:
+ fwctx->req = NULL;
+ done:
+ fwctx->done(fwctx->dev, ret, fwctx->req);
++ if (fwctx->completion)
++ complete(fwctx->completion);
+ kfree(fwctx);
+ }
+
+@@ -612,6 +615,8 @@ int brcmf_fw_get_firmwares(struct device
+ struct brcmf_fw_request *req))
+ {
+ struct brcmf_fw *fwctx;
++ struct completion completion;
++ int err;
+
+ brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
+ if (!fw_cb)
+@@ -628,7 +633,14 @@ int brcmf_fw_get_firmwares(struct device
+ fwctx->req = req;
+ fwctx->done = fw_cb;
+
++ init_completion(&completion);
++ fwctx->completion = &completion;
++
+ brcmf_fw_request_next_item(fwctx, true);
++
++ wait_for_completion_timeout(fwctx->completion, msecs_to_jiffies(5000));
++ fwctx->completion = NULL;
++
+ return 0;
+ }
+
--- /dev/null
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
+Date: Thu, 9 Jul 2015 00:07:59 +0200
+Subject: [PATCH] brcmfmac: workaround bug with some inconsistent BSSes state
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -614,9 +614,37 @@ static struct wireless_dev *brcmf_cfg802
+ enum nl80211_iftype type,
+ struct vif_params *params)
+ {
++ struct net_device *dev;
+ struct wireless_dev *wdev;
+ int err;
+
++ /*
++ * There is a bug with in-firmware BSS management. When adding virtual
++ * interface brcmfmac first tells firmware to create new BSS and then
++ * it creates new struct net_device.
++ *
++ * If creating/registering netdev(ice) fails, BSS remains in some bugged
++ * state. It conflicts with existing BSSes by overtaking their auth
++ * requests.
++ *
++ * It results in one BSS (addresss X) sending beacons and another BSS
++ * (address Y) replying to authentication requests. This makes interface
++ * unusable as AP.
++ *
++ * To workaround this bug we may try to guess if register_netdev(ice)
++ * will fail. The most obvious case is using interface name that already
++ * exists. This is actually quite likely with brcmfmac & some user space
++ * scripts as brcmfmac doesn't allow deleting virtual interfaces.
++ * So this bug can be triggered even by something trivial like:
++ * iw dev wlan0 delete
++ * iw phy phy0 interface add wlan0 type __ap
++ */
++ dev = dev_get_by_name(&init_net, name);
++ if (dev) {
++ dev_put(dev);
++ return ERR_PTR(-ENFILE);
++ }
++
+ brcmf_dbg(TRACE, "enter: %s type %d\n", name, type);
+ err = brcmf_vif_add_validate(wiphy_to_cfg(wiphy), type);
+ if (err) {
--- /dev/null
+From 66ae1b1750720a33e29792a177b1e696f4f005fb Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Wed, 9 Mar 2016 17:25:59 +0000
+Subject: [PATCH] brcmfmac: Disable power management
+
+Disable wireless power saving in the brcmfmac WLAN driver. This is a
+temporary measure until the connectivity loss resulting from power
+saving is resolved.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -2725,6 +2725,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip
+ * preference in cfg struct to apply this to
+ * FW later while initializing the dongle
+ */
++#if defined(CONFIG_ARCH_BCM2835)
++ brcmf_dbg(INFO, "power management disabled\n");
++ enabled = false;
++#endif
+ cfg->pwr_save = enabled;
+ if (!check_vif_up(ifp->vif)) {
+
--- /dev/null
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Subject: [PATCH] brcmfmac: add in-driver tables with country codes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This adds early support for changing region. Ideally this data should
+be stored in DT as all these mappings are devices specific.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+---
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c
+@@ -23,6 +23,36 @@
+ #include "common.h"
+ #include "of.h"
+
++/* TODO: FIXME: Use DT */
++static void brcmf_of_probe_cc(struct device *dev,
++ struct brcmf_mp_device *settings)
++{
++ static struct brcmfmac_pd_cc_entry netgear_r8000_cc_ent[] = {
++ { "JP", "JP", 78 },
++ { "US", "Q2", 86 },
++ };
++ struct brcmfmac_pd_cc_entry *cc_ent = NULL;
++ int table_size = 0;
++
++ if (of_machine_is_compatible("netgear,r8000")) {
++ cc_ent = netgear_r8000_cc_ent;
++ table_size = ARRAY_SIZE(netgear_r8000_cc_ent);
++ }
++
++ if (cc_ent && table_size) {
++ struct brcmfmac_pd_cc *cc;
++ size_t memsize;
++
++ memsize = table_size * sizeof(struct brcmfmac_pd_cc_entry);
++ cc = devm_kzalloc(dev, sizeof(*cc) + memsize, GFP_KERNEL);
++ if (!cc)
++ return;
++ cc->table_size = table_size;
++ memcpy(cc->table, cc_ent, memsize);
++ settings->country_codes = cc;
++ }
++}
++
+ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
+ struct brcmf_mp_device *settings)
+ {
+@@ -32,6 +62,8 @@ void brcmf_of_probe(struct device *dev,
+ u32 irqf;
+ u32 val;
+
++ brcmf_of_probe_cc(dev, settings);
++
+ if (!np || bus_type != BRCMF_BUSTYPE_SDIO ||
+ !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
+ return;
--- /dev/null
+brcmfmac: do not use internal roaming engine by default
+
+Some evidence of curing disconnects with this disabled, so make it a default.
+Can be overridden with module parameter roamoff=0
+See: http://projectable.me/optimize-my-pi-wi-fi/
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+
+Index: backports-v4.18-rc7/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+===================================================================
+--- backports-v4.18-rc7.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
++++ backports-v4.18-rc7/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+@@ -70,7 +70,11 @@ static int brcmf_fcmode;
+ module_param_named(fcmode, brcmf_fcmode, int, 0);
+ MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control");
+
++#if defined(CONFIG_ARCH_BCM2835)
++static int brcmf_roamoff = 1;
++#else
+ static int brcmf_roamoff;
++#endif
+ module_param_named(roamoff, brcmf_roamoff, int, 0400);
+ MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
+
--- /dev/null
+--- a/kconf/Makefile
++++ b/kconf/Makefile
+@@ -1,9 +1,9 @@
+-CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer
++CFLAGS=-Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -DKBUILD_NO_NLS
+
+ LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o
+
+ conf: conf.o zconf.tab.o
+-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE
++mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags)
+ mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
+ mconf: CFLAGS += $(mconf_CFLAGS)
+
--- /dev/null
+--- a/Makefile
++++ b/Makefile
+@@ -5,7 +5,7 @@
+ ifeq ($(KERNELRELEASE),)
+
+ MAKEFLAGS += --no-print-directory
+-SHELL := /bin/bash
++SHELL := /usr/bin/env bash
+ BACKPORT_DIR := $(shell pwd)
+
+ KMODDIR ?= updates
+@@ -19,6 +19,7 @@ KLIB_BUILD ?= $(KLIB)/build/
+ KERNEL_CONFIG := $(KLIB_BUILD)/.config
+ KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile
+ CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//')
++STAMP_KERNEL_CONFIG := .kernel_config_md5_$(CONFIG_MD5)
+
+ export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG
+
+@@ -36,7 +37,8 @@ mrproper:
+ @rm -f .kernel_config_md5 Kconfig.versions Kconfig.kernel
+ @rm -f backport-include/backport/autoconf.h
+
+-.DEFAULT:
++.SILENT: $(STAMP_KERNEL_CONFIG)
++$(STAMP_KERNEL_CONFIG):
+ @set -e ; test -f local-symbols || ( \
+ echo "/--------------" ;\
+ echo "| You shouldn't run make in the backports tree, but only in" ;\
+@@ -60,57 +62,61 @@ mrproper:
+ echo "| (that isn't currently running.)" ;\
+ echo "\\--" ;\
+ false)
+- @set -e ; if [ "$$(cat .kernel_config_md5 2>/dev/null)" != "$(CONFIG_MD5)" ] ;\
+- then \
+- echo -n "Generating local configuration database from kernel ..." ;\
+- grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
+- while read l ; do \
+- if [ "$${l:0:7}" != "CONFIG_" ] ; then \
+- continue ;\
+- fi ;\
+- l=$${l:7} ;\
+- n=$${l%%=*} ;\
+- v=$${l#*=} ;\
+- if [ "$$v" = "m" ] ; then \
+- echo config $$n ;\
+- echo ' tristate' ;\
+- elif [ "$$v" = "y" ] ; then \
+- echo config $$n ;\
+- echo ' bool' ;\
+- else \
+- continue ;\
+- fi ;\
+- echo " default $$v" ;\
+- echo "" ;\
+- done \
+- ) > Kconfig.kernel ;\
+- kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
+- 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 19 | sed 's/^/3./')" ;\
+- kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
+- print=0 ;\
+- for v in $$kvers ; do \
+- if [ "$$print" = "1" ] ; then \
+- echo config KERNEL_$$(echo $$v | tr . _) ;\
+- echo " def_bool y" ;\
+- fi ;\
+- if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
+- done > Kconfig.versions ;\
+- # RHEL as well, sadly we need to grep for it ;\
+- RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
+- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
+- RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
+- sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
+- for v in $$(seq 0 $$RHEL_MINOR) ; do \
+- echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
+- echo " def_bool y" ;\
+- done >> Kconfig.versions ;\
+- echo " done." ;\
+- fi ;\
+- echo "$(CONFIG_MD5)" > .kernel_config_md5
++ @rm -f .kernel_config_md5_*
++ @touch $@
++
++Kconfig.kernel: $(STAMP_KERNEL_CONFIG) local-symbols
++ @printf "Generating local configuration database from kernel ..."
++ @grep -v -f local-symbols $(KERNEL_CONFIG) | grep = | ( \
++ while read l ; do \
++ if [ "$${l:0:7}" != "CONFIG_" ] ; then \
++ continue ;\
++ fi ;\
++ l=$${l:7} ;\
++ n=$${l%%=*} ;\
++ v=$${l#*=} ;\
++ if [ "$$v" = "m" ] ; then \
++ echo config $$n ;\
++ echo ' tristate' ;\
++ elif [ "$$v" = "y" ] ; then \
++ echo config $$n ;\
++ echo ' bool' ;\
++ else \
++ continue ;\
++ fi ;\
++ echo " default $$v" ;\
++ echo "" ;\
++ done \
++ ) > $@
++ @echo " done."
++
++Kconfig.versions: Kconfig.kernel
++ @kver=$$($(MAKE) --no-print-directory -C $(KLIB_BUILD) kernelversion | \
++ 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 19 | sed 's/^/3./')" ;\
++ kvers="$$kvers $$(seq 0 99 | sed 's/^/4./')" ;\
++ print=0 ;\
++ for v in $$kvers ; do \
++ if [ "$$print" = "1" ] ; then \
++ echo config KERNEL_$$(echo $$v | tr . _) ;\
++ echo " def_bool y" ;\
++ fi ;\
++ if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
++ done > $@
++ @RHEL_MAJOR=$$(grep '^RHEL_MAJOR' $(KERNEL_MAKEFILE) | \
++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
++ RHEL_MINOR=$$(grep '^RHEL_MINOR' $(KERNEL_MAKEFILE) | \
++ sed 's/.*=\s*\([0-9]*\)/\1/;t;d') ;\
++ for v in $$(seq 0 $$RHEL_MINOR) ; do \
++ echo config BACKPORT_RHEL_KERNEL_$${RHEL_MAJOR}_$$v ;\
++ echo " def_bool y" ;\
++ done >> $@
++
++.DEFAULT:
++ @$(MAKE) Kconfig.versions
+ @$(MAKE) -f Makefile.real "$@"
+
+ .PHONY: defconfig-help
+--- a/Makefile.real
++++ b/Makefile.real
+@@ -59,7 +59,7 @@ defconfig-%::
+
+ backport-include/backport/autoconf.h: .config Kconfig.versions Kconfig.kernel
+ @$(MAKE) oldconfig
+- @echo -n "Building backport-include/backport/autoconf.h ..."
++ @printf "Building backport-include/backport/autoconf.h ..."
+ @grep -f local-symbols .config | ( \
+ echo "#ifndef COMPAT_AUTOCONF_INCLUDED" ;\
+ echo "#define COMPAT_AUTOCONF_INCLUDED" ;\
+@@ -80,7 +80,12 @@ backport-include/backport/autoconf.h: .c
+ esac ;\
+ done ;\
+ echo "#endif /* COMPAT_AUTOCONF_INCLUDED */" ;\
+- ) > backport-include/backport/autoconf.h
++ ) > $@.new
++ @if cmp -s $@ $@.new; then \
++ rm -f $@.new; \
++ else \
++ mv $@.new $@; \
++ fi
+ @echo " done."
+
+ .PHONY: modules
--- /dev/null
+--- a/kconf/conf.c
++++ b/kconf/conf.c
+@@ -594,40 +594,12 @@ int main(int ac, char **av)
+ case oldconfig:
+ case listnewconfig:
+ case olddefconfig:
+- conf_read(NULL);
+- break;
+ case allnoconfig:
+ case allyesconfig:
+ case allmodconfig:
+ case alldefconfig:
+ case randconfig:
+- name = getenv("KCONFIG_ALLCONFIG");
+- if (!name)
+- break;
+- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
+- if (conf_read_simple(name, S_DEF_USER)) {
+- fprintf(stderr,
+- _("*** Can't read seed configuration \"%s\"!\n"),
+- name);
+- exit(1);
+- }
+- break;
+- }
+- switch (input_mode) {
+- case allnoconfig: name = "allno.config"; break;
+- case allyesconfig: name = "allyes.config"; break;
+- case allmodconfig: name = "allmod.config"; break;
+- case alldefconfig: name = "alldef.config"; break;
+- case randconfig: name = "allrandom.config"; break;
+- default: break;
+- }
+- if (conf_read_simple(name, S_DEF_USER) &&
+- conf_read_simple("all.config", S_DEF_USER)) {
+- fprintf(stderr,
+- _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
+- name);
+- exit(1);
+- }
++ conf_read(NULL);
+ break;
+ default:
+ break;
+--- a/kconf/confdata.c
++++ b/kconf/confdata.c
+@@ -1170,6 +1170,8 @@ bool conf_set_all_new_symbols(enum conf_
+ }
+ bool has_changed = false;
+
++ sym_clear_all_valid();
++
+ for_all_symbols(i, sym) {
+ if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
+ continue;
+@@ -1213,8 +1215,6 @@ bool conf_set_all_new_symbols(enum conf_
+
+ }
+
+- sym_clear_all_valid();
+-
+ /*
+ * We have different type of choice blocks.
+ * If curr.tri equals to mod then we can select several
--- /dev/null
+--- a/compat/main.c
++++ b/compat/main.c
+@@ -20,31 +20,6 @@ MODULE_LICENSE("GPL");
+ #error "You need a CPTCFG_VERSION"
+ #endif
+
+-static char *backported_kernel_name = CPTCFG_KERNEL_NAME;
+-
+-module_param(backported_kernel_name, charp, 0400);
+-MODULE_PARM_DESC(backported_kernel_name,
+- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")");
+-
+-#ifdef BACKPORTS_GIT_TRACKED
+-static char *backports_tracker_id = BACKPORTS_GIT_TRACKED;
+-module_param(backports_tracker_id, charp, 0400);
+-MODULE_PARM_DESC(backports_tracker_id,
+- "The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")");
+-#else
+-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION;
+-static char *backports_version = CPTCFG_VERSION;
+-
+-module_param(backported_kernel_version, charp, 0400);
+-MODULE_PARM_DESC(backported_kernel_version,
+- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")");
+-
+-module_param(backports_version, charp, 0400);
+-MODULE_PARM_DESC(backports_version,
+- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")");
+-
+-#endif
+-
+ void backport_dependency_symbol(void)
+ {
+ }
--- /dev/null
+--- a/backport-include/linux/kconfig.h
++++ b/backport-include/linux/kconfig.h
+@@ -5,6 +5,8 @@
+ #include_next <linux/kconfig.h>
+ #endif
+
++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)
++
+ #ifndef __ARG_PLACEHOLDER_1
+ #define __ARG_PLACEHOLDER_1 0,
+ #define config_enabled(cfg) _config_enabled(cfg)
+@@ -16,6 +18,7 @@
+ * 3.1 - 3.3 had a broken version of this, so undef
+ * (they didn't have __ARG_PLACEHOLDER_1)
+ */
++
+ #undef IS_ENABLED
+ #define IS_ENABLED(option) \
+ (config_enabled(option) || config_enabled(option##_MODULE))
+@@ -31,6 +34,8 @@
+ #undef IS_BUILTIN
+ #define IS_BUILTIN(option) config_enabled(option)
+
++#endif
++
+ #ifndef IS_REACHABLE
+ /*
+ * IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled
--- /dev/null
+Index: backports-v4.18-rc7/compat/Makefile
+===================================================================
+--- backports-v4.18-rc7.orig/compat/Makefile
++++ backports-v4.18-rc7/compat/Makefile
+@@ -70,8 +70,6 @@ quiet_cmd_build_OID_registry = GEN $
+ cmd_build_OID_registry = perl $(src)/build_OID_registry $< $@
+ compat-$(CPTCFG_BPAUTO_ASN1_DECODER) += lib-asn1_decoder.o
+ compat-$(CPTCFG_BPAUTO_BUILD_SYSTEM_DATA_VERIFICATION) += lib-oid_registry.o
+-skcipher-objs += crypto-skcipher.o
+-obj-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += skcipher.o
+ compat-$(CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP) += drivers-base-devcoredump.o
+ compat-$(CPTCFG_BPAUTO_RHASHTABLE) += lib-rhashtable.o
+ cordic-objs += lib-cordic.o
--- /dev/null
+--- a/compat/backport-4.12.c
++++ b/compat/backport-4.12.c
+@@ -225,6 +225,7 @@ int bp_extack_genl_register_family(struc
+
+ /* copy this since the family might access it directly */
+ family->attrbuf = copy->family.attrbuf;
++ family->mcgrp_offset = copy->family.mcgrp_offset;
+
+ mutex_lock(&copies_mutex);
+ list_add_tail(©->list, &copies_list);
--- /dev/null
+--- a/backport-include/linux/rfkill.h
++++ b/backport-include/linux/rfkill.h
+@@ -2,6 +2,12 @@
+ #define __COMPAT_RFKILL_H
+ #include <linux/version.h>
+
++#undef CONFIG_RFKILL
++#undef CONFIG_RFKILL_FULL
++#undef CONFIG_RFKILL_LEDS
++#undef CONFIG_RFKILL_MODULE
++#undef CONFIG_RFKILL_FULL_MODULE
++
+ #if LINUX_VERSION_IS_GEQ(3,10,0)
+ #include_next <linux/rfkill.h>
+ #else
--- /dev/null
+--- a/Makefile
++++ b/Makefile
+@@ -2,7 +2,7 @@
+ # Makefile for the output source package
+ #
+
+-ifeq ($(KERNELRELEASE),)
++ifeq ($(KERNELVERSION),)
+
+ MAKEFLAGS += --no-print-directory
+ SHELL := /usr/bin/env bash
--- /dev/null
+--- a/net/wireless/Kconfig
++++ b/net/wireless/Kconfig
+@@ -181,7 +181,7 @@ config CFG80211_WEXT_EXPORT
+ wext compatibility symbols to be exported.
+
+ config LIB80211
+- tristate
++ tristate "lib80211"
+ depends on m
+ default n
+ help
+@@ -191,15 +191,15 @@ config LIB80211
+ Drivers should select this themselves if needed.
+
+ config LIB80211_CRYPT_WEP
+- tristate
++ tristate "lib80211 WEP support"
+ depends on m
+
+ config LIB80211_CRYPT_CCMP
+- tristate
++ tristate "lib80211 CCMP support"
+ depends on m
+
+ config LIB80211_CRYPT_TKIP
+- tristate
++ tristate "lib80211 TKIP support"
+ depends on m
+
+ config LIB80211_DEBUG
--- /dev/null
+--- a/local-symbols
++++ b/local-symbols
+@@ -388,45 +388,6 @@ USB_IPHETH=
+ USB_SIERRA_NET=
+ USB_VL600=
+ USB_NET_CH9200=
+-SSB_POSSIBLE=
+-SSB=
+-SSB_SPROM=
+-SSB_BLOCKIO=
+-SSB_PCIHOST_POSSIBLE=
+-SSB_PCIHOST=
+-SSB_B43_PCI_BRIDGE=
+-SSB_PCMCIAHOST_POSSIBLE=
+-SSB_PCMCIAHOST=
+-SSB_SDIOHOST_POSSIBLE=
+-SSB_SDIOHOST=
+-SSB_HOST_SOC=
+-SSB_SILENT=
+-SSB_DEBUG=
+-SSB_SERIAL=
+-SSB_DRIVER_PCICORE_POSSIBLE=
+-SSB_DRIVER_PCICORE=
+-SSB_PCICORE_HOSTMODE=
+-SSB_DRIVER_MIPS=
+-SSB_SFLASH=
+-SSB_EMBEDDED=
+-SSB_DRIVER_EXTIF=
+-SSB_DRIVER_GIGE=
+-SSB_DRIVER_GPIO=
+-BCMA_POSSIBLE=
+-BCMA=
+-BCMA_BLOCKIO=
+-BCMA_HOST_PCI_POSSIBLE=
+-BCMA_HOST_PCI=
+-BCMA_HOST_SOC=
+-BCMA_DRIVER_PCI=
+-BCMA_DRIVER_PCI_HOSTMODE=
+-BCMA_DRIVER_MIPS=
+-BCMA_PFLASH=
+-BCMA_SFLASH=
+-BCMA_NFLASH=
+-BCMA_DRIVER_GMAC_CMN=
+-BCMA_DRIVER_GPIO=
+-BCMA_DEBUG=
+ NFC=
+ NFC_DIGITAL=
+ NFC_NCI=
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -2876,7 +2876,7 @@ static struct ssb_device *b43_ssb_gpio_d
+ {
+ struct ssb_bus *bus = dev->dev->sdev->bus;
+
+-#ifdef CPTCFG_SSB_DRIVER_PCICORE
++#ifdef CONFIG_SSB_DRIVER_PCICORE
+ return (bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev);
+ #else
+ return bus->chipco.dev;
+@@ -4893,7 +4893,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. */
+-#if defined(CPTCFG_B43_SSB) && defined(CPTCFG_SSB_DRIVER_PCICORE)
++#if defined(CPTCFG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
+ dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
+--- a/drivers/net/wireless/broadcom/b43legacy/main.c
++++ b/drivers/net/wireless/broadcom/b43legacy/main.c
+@@ -1937,7 +1937,7 @@ static int b43legacy_gpio_init(struct b4
+ if (dev->dev->id.revision >= 2)
+ mask |= 0x0010; /* FIXME: This is redundant. */
+
+-#ifdef CPTCFG_SSB_DRIVER_PCICORE
++#ifdef CONFIG_SSB_DRIVER_PCICORE
+ pcidev = bus->pcicore.dev;
+ #endif
+ gpiodev = bus->chipco.dev ? : pcidev;
+@@ -1956,7 +1956,7 @@ static void b43legacy_gpio_cleanup(struc
+ struct ssb_bus *bus = dev->dev->bus;
+ struct ssb_device *gpiodev, *pcidev = NULL;
+
+-#ifdef CPTCFG_SSB_DRIVER_PCICORE
++#ifdef CONFIG_SSB_DRIVER_PCICORE
+ pcidev = bus->pcicore.dev;
+ #endif
+ gpiodev = bus->chipco.dev ? : pcidev;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/Makefile
+@@ -42,6 +42,6 @@ brcmsmac-y := \
+ brcms_trace_events.o \
+ debug.o
+
+-brcmsmac-$(CPTCFG_BCMA_DRIVER_GPIO) += led.o
++brcmsmac-$(CONFIG_BCMA_DRIVER_GPIO) += led.o
+
+ obj-$(CPTCFG_BRCMSMAC) += brcmsmac.o
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.h
+@@ -22,7 +22,7 @@ struct brcms_led {
+ bool active_low;
+ };
+
+-#ifdef CPTCFG_BCMA_DRIVER_GPIO
++#ifdef CONFIG_BCMA_DRIVER_GPIO
+ void brcms_led_unregister(struct brcms_info *wl);
+ int brcms_led_register(struct brcms_info *wl);
+ #else
+--- 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/usb/Kconfig"
+
+-source "$BACKPORT_DIR/drivers/ssb/Kconfig"
+-source "$BACKPORT_DIR/drivers/bcma/Kconfig"
+-
+ source "$BACKPORT_DIR/net/nfc/Kconfig"
+
+ #source "$BACKPORT_DIR/drivers/media/Kconfig"
+--- a/Makefile.kernel
++++ b/Makefile.kernel
+@@ -42,8 +42,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/
--- /dev/null
+--- a/drivers/net/wireless/marvell/mwl8k.c
++++ b/drivers/net/wireless/marvell/mwl8k.c
+@@ -5681,6 +5681,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+ MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
+
+ static const struct pci_device_id mwl8k_pci_id_table[] = {
++ { PCI_VDEVICE(MARVELL, 0x2a02), .driver_data = MWL8363, },
+ { PCI_VDEVICE(MARVELL, 0x2a0a), .driver_data = MWL8363, },
+ { PCI_VDEVICE(MARVELL, 0x2a0c), .driver_data = MWL8363, },
+ { PCI_VDEVICE(MARVELL, 0x2a24), .driver_data = MWL8363, },
--- /dev/null
+--- a/drivers/net/wireless/marvell/libertas/cfg.c
++++ b/drivers/net/wireless/marvell/libertas/cfg.c
+@@ -2040,6 +2040,8 @@ struct wireless_dev *lbs_cfg_alloc(struc
+ goto err_wiphy_new;
+ }
+
++ set_wiphy_dev(wdev->wiphy, dev);
++
+ return wdev;
+
+ err_wiphy_new:
+--- a/drivers/net/wireless/marvell/libertas/main.c
++++ b/drivers/net/wireless/marvell/libertas/main.c
+@@ -930,6 +930,7 @@ struct lbs_private *lbs_add_card(void *c
+ goto err_adapter;
+ }
+
++ dev_net_set(dev, wiphy_net(wdev->wiphy));
+ dev->ieee80211_ptr = wdev;
+ dev->ml_priv = priv;
+ SET_NETDEV_DEV(dev, dmdev);
--- /dev/null
+--- a/drivers/net/wireless/marvell/libertas/cfg.c
++++ b/drivers/net/wireless/marvell/libertas/cfg.c
+@@ -2116,6 +2116,8 @@ int lbs_cfg_register(struct lbs_private
+ wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+ wdev->wiphy->reg_notifier = lbs_reg_notifier;
+
++ memcpy(wdev->wiphy->perm_addr, priv->current_addr, ETH_ALEN);
++
+ ret = wiphy_register(wdev->wiphy);
+ if (ret < 0)
+ pr_err("cannot register wiphy device\n");
--- /dev/null
+--- a/drivers/net/wireless/marvell/mwl8k.c
++++ b/drivers/net/wireless/marvell/mwl8k.c
+@@ -6266,6 +6266,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:
+@@ -6299,8 +6301,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;
--- /dev/null
+--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
+@@ -225,36 +225,37 @@ config RT2800SOC
+
+
+ config RT2800_LIB
+- tristate
++ tristate "RT2800 USB/PCI support"
+ depends on m
+
+ config RT2800_LIB_MMIO
+- tristate
++ tristate "RT2800 MMIO support"
+ depends on m
+ select RT2X00_LIB_MMIO
+ select RT2800_LIB
+
+ config RT2X00_LIB_MMIO
+- tristate
++ tristate "RT2x00 MMIO support"
+ depends on m
+
+ config RT2X00_LIB_PCI
+- tristate
++ tristate "RT2x00 PCI support"
+ depends on m
+ select RT2X00_LIB
+
+ config RT2X00_LIB_SOC
+- tristate
++ tristate "RT2x00 SoC support"
++ depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
+ depends on m
+ select RT2X00_LIB
+
+ config RT2X00_LIB_USB
+- tristate
++ tristate "RT2x00 USB support"
+ depends on m
+ select RT2X00_LIB
+
+ config RT2X00_LIB
+- tristate
++ tristate "RT2x00 support"
+ depends on m
+
+ config RT2X00_LIB_FIRMWARE
--- /dev/null
+From 91094ed065f7794886b4a5490fd6de942f036bb4 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: allow to build rt2800soc module for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
+@@ -210,7 +210,7 @@ endif
+ config RT2800SOC
+ tristate "Ralink WiSoC support"
+ depends on m
+- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
+ select RT2X00_LIB_SOC
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_CRYPTO
+@@ -245,7 +245,7 @@ config RT2X00_LIB_PCI
+
+ config RT2X00_LIB_SOC
+ tristate "RT2x00 SoC support"
+- depends on SOC_RT288X || SOC_RT305X || SOC_MT7620
++ depends on SOC_RT288X || SOC_RT305X || SOC_RT3883 || SOC_MT7620
+ depends on m
+ select RT2X00_LIB
+
--- /dev/null
+From 4f16582c93a71eba9d389e0f0a8aa9099a9587cd Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: rt2800lib: enable support for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -9403,6 +9403,7 @@ static int rt2800_probe_rt(struct rt2x00
+ case RT3390:
+ case RT3572:
+ case RT3593:
++ case RT3883:
+ case RT5350:
+ case RT5390:
+ case RT5392:
--- /dev/null
+From ecb394ccf248d8652c463133c4f404458a57a9c1 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add rf_vals for RF3853
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800.h | 4 +-
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 65 +++++++++++++++++++++++++++++++
+ 2 files changed, 68 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
+@@ -48,7 +48,8 @@
+ * RF2853 2.4G/5G 3T3R
+ * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390)
+ * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392)
+- * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
++ * RF3053 2.4G/5G 3T3R(RT3563/RT3573/RT3593)
++ * RF3853 2.4G/5G 3T3R(RT3883/RT3662)
+ * RF5592 2.4G/5G 2T2R
+ * RF3070 2.4G 1T1R
+ * RF5360 2.4G 1T1R
+@@ -72,6 +73,7 @@
+ #define RF5592 0x000f
+ #define RF3070 0x3070
+ #define RF3290 0x3290
++#define RF3853 0x3853
+ #define RF5350 0x5350
+ #define RF5360 0x5360
+ #define RF5362 0x5362
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -8981,6 +8981,66 @@ static const struct rf_channel rf_vals_3
+ {14, 0xF0, 2, 0x18},
+ };
+
++static const struct rf_channel rf_vals_3853[] = {
++ {1, 241, 6, 2},
++ {2, 241, 6, 7},
++ {3, 242, 6, 2},
++ {4, 242, 6, 7},
++ {5, 243, 6, 2},
++ {6, 243, 6, 7},
++ {7, 244, 6, 2},
++ {8, 244, 6, 7},
++ {9, 245, 6, 2},
++ {10, 245, 6, 7},
++ {11, 246, 6, 2},
++ {12, 246, 6, 7},
++ {13, 247, 6, 2},
++ {14, 248, 6, 4},
++
++ {36, 0x56, 8, 4},
++ {38, 0x56, 8, 6},
++ {40, 0x56, 8, 8},
++ {44, 0x57, 8, 0},
++ {46, 0x57, 8, 2},
++ {48, 0x57, 8, 4},
++ {52, 0x57, 8, 8},
++ {54, 0x57, 8, 10},
++ {56, 0x58, 8, 0},
++ {60, 0x58, 8, 4},
++ {62, 0x58, 8, 6},
++ {64, 0x58, 8, 8},
++
++ {100, 0x5b, 8, 8},
++ {102, 0x5b, 8, 10},
++ {104, 0x5c, 8, 0},
++ {108, 0x5c, 8, 4},
++ {110, 0x5c, 8, 6},
++ {112, 0x5c, 8, 8},
++ {114, 0x5c, 8, 10},
++ {116, 0x5d, 8, 0},
++ {118, 0x5d, 8, 2},
++ {120, 0x5d, 8, 4},
++ {124, 0x5d, 8, 8},
++ {126, 0x5d, 8, 10},
++ {128, 0x5e, 8, 0},
++ {132, 0x5e, 8, 4},
++ {134, 0x5e, 8, 6},
++ {136, 0x5e, 8, 8},
++ {140, 0x5f, 8, 0},
++
++ {149, 0x5f, 8, 9},
++ {151, 0x5f, 8, 11},
++ {153, 0x60, 8, 1},
++ {157, 0x60, 8, 5},
++ {159, 0x60, 8, 7},
++ {161, 0x60, 8, 9},
++ {165, 0x61, 8, 1},
++ {167, 0x61, 8, 3},
++ {169, 0x61, 8, 5},
++ {171, 0x61, 8, 7},
++ {173, 0x61, 8, 9},
++};
++
+ static const struct rf_channel rf_vals_5592_xtal20[] = {
+ /* Channel, N, K, mod, R */
+ {1, 482, 4, 10, 3},
+@@ -9244,6 +9304,11 @@ static int rt2800_probe_hw_mode(struct r
+ spec->channels = rf_vals_3x;
+ break;
+
++ case RF3853:
++ spec->num_channels = ARRAY_SIZE(rf_vals_3853);
++ spec->channels = rf_vals_3853;
++ break;
++
+ case RF5592:
+ reg = rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX);
+ if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) {
--- /dev/null
+From f8e3fcf18e1f2d7f9e6a9680c5452da090f33d88 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Thu, 1 Aug 2013 14:40:44 +0200
+Subject: [PATCH] rt2x00: rt2800lib: enable VCO calibration for RF3853
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -4881,6 +4881,7 @@ void rt2800_vco_calibration(struct rt2x0
+ case RF3053:
+ case RF3070:
+ case RF3290:
++ case RF3853:
+ case RF5350:
+ case RF5360:
+ case RF5362:
+@@ -9426,6 +9427,7 @@ static int rt2800_probe_hw_mode(struct r
+ case RF3053:
+ case RF3070:
+ case RF3290:
++ case RF3853:
+ case RF5350:
+ case RF5360:
+ case RF5362:
--- /dev/null
+From 6e3a17190815c6aa4dc53c2cfe9125fb1154f187 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:27 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add channel configuration function for
+ RF3853
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 208 +++++++++++++++++++++++++++++++
+ 1 file changed, 208 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -2713,6 +2713,211 @@ static void rt2800_config_channel_rf3053
+ }
+ }
+
++static void rt2800_config_channel_rf3853(struct rt2x00_dev *rt2x00dev,
++ struct ieee80211_conf *conf,
++ struct rf_channel *rf,
++ struct channel_info *info)
++{
++ u8 rfcsr;
++ u8 bbp;
++ u8 pwr1, pwr2, pwr3;
++
++ const bool txbf_enabled = false; /* TODO */
++
++ /* TODO: add band selection */
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
++ else if (rf->channel < 132)
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x80);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
++
++ rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
++ rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x46);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 12, 0x52);
++
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
++ rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
++
++ switch (rt2x00dev->default_ant.tx_chain_num) {
++ case 3:
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1);
++ /* fallthrough */
++ case 2:
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1);
++ /* fallthrough */
++ case 1:
++ rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
++ break;
++ }
++
++ switch (rt2x00dev->default_ant.rx_chain_num) {
++ case 3:
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1);
++ /* fallthrough */
++ case 2:
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1);
++ /* fallthrough */
++ case 1:
++ rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
++ break;
++ }
++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
++
++ rt2800_freq_cal_mode1(rt2x00dev);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 30);
++ if (!conf_is_ht40(conf))
++ rfcsr &= ~(0x06);
++ else
++ rfcsr |= 0x06;
++ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 31, 0xa0);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
++
++ if (conf_is_ht40(conf))
++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 34, 0x3c);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
++
++ /* loopback RF_BS */
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 36);
++ if (rf->channel <= 14)
++ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1);
++ else
++ rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0);
++ rt2800_rfcsr_write(rt2x00dev, 36, rfcsr);
++
++ if (rf->channel <= 14)
++ rfcsr = 0x23;
++ else if (rf->channel < 100)
++ rfcsr = 0x36;
++ else if (rf->channel < 132)
++ rfcsr = 0x32;
++ else
++ rfcsr = 0x30;
++
++ if (txbf_enabled)
++ rfcsr |= 0x40;
++
++ rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
++
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 44, 0x9b);
++
++ if (rf->channel <= 14)
++ rfcsr = 0xbb;
++ else if (rf->channel < 100)
++ rfcsr = 0xeb;
++ else if (rf->channel < 132)
++ rfcsr = 0xb3;
++ else
++ rfcsr = 0x9b;
++ rt2800_rfcsr_write(rt2x00dev, 45, rfcsr);
++
++ if (rf->channel <= 14)
++ rfcsr = 0x8e;
++ else
++ rfcsr = 0x8a;
++
++ if (txbf_enabled)
++ rfcsr |= 0x20;
++
++ rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
++
++ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 51);
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 51, 0x75);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 52);
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 52, 0x45);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
++
++ if (rf->channel <= 14) {
++ pwr1 = info->default_power1 & 0x1f;
++ pwr2 = info->default_power2 & 0x1f;
++ pwr3 = info->default_power3 & 0x1f;
++ } else {
++ pwr1 = 0x48 | ((info->default_power1 & 0x18) << 1) |
++ (info->default_power1 & 0x7);
++ pwr2 = 0x48 | ((info->default_power2 & 0x18) << 1) |
++ (info->default_power2 & 0x7);
++ pwr3 = 0x48 | ((info->default_power3 & 0x18) << 1) |
++ (info->default_power3 & 0x7);
++ }
++
++ rt2800_rfcsr_write(rt2x00dev, 53, pwr1);
++ rt2800_rfcsr_write(rt2x00dev, 54, pwr2);
++ rt2800_rfcsr_write(rt2x00dev, 55, pwr3);
++
++ rt2x00_dbg(rt2x00dev, "Channel:%d, pwr1:%02x, pwr2:%02x, pwr3:%02x\n",
++ rf->channel, pwr1, pwr2, pwr3);
++
++ bbp = (info->default_power1 >> 5) |
++ ((info->default_power2 & 0xe0) >> 1);
++ rt2800_bbp_write(rt2x00dev, 109, bbp);
++
++ bbp = rt2800_bbp_read(rt2x00dev, 110);
++ bbp &= 0x0f;
++ bbp |= (info->default_power3 & 0xe0) >> 1;
++ rt2800_bbp_write(rt2x00dev, 110, bbp);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 57);
++ if (rf->channel <= 14)
++ rt2800_rfcsr_write(rt2x00dev, 57, 0x6e);
++ else
++ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
++
++ /* Enable RF tuning */
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 3);
++ rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1);
++ rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
++
++ udelay(2000);
++
++ bbp = rt2800_bbp_read(rt2x00dev, 49);
++ /* clear update flag */
++ rt2800_bbp_write(rt2x00dev, 49, bbp & 0xfe);
++ rt2800_bbp_write(rt2x00dev, 49, bbp);
++
++ /* TODO: add calibration for TxBF */
++}
++
+ #define POWER_BOUND 0x27
+ #define POWER_BOUND_5G 0x2b
+
+@@ -3570,6 +3775,9 @@ static void rt2800_config_channel(struct
+ case RF3322:
+ rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info);
+ break;
++ case RF3853:
++ rt2800_config_channel_rf3853(rt2x00dev, conf, rf, info);
++ break;
+ case RF3070:
+ case RF5350:
+ case RF5360:
--- /dev/null
+From afd38ae82226551bf879b6c7c4b620c271fee9d2 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Thu, 1 Aug 2013 14:42:05 +0200
+Subject: [PATCH] rt2x00: rt2800lib: enable RF3853 support
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -8906,6 +8906,7 @@ static int rt2800_init_eeprom(struct rt2
+ case RF3290:
+ case RF3320:
+ case RF3322:
++ case RF3853:
+ case RF5350:
+ case RF5360:
+ case RF5362:
--- /dev/null
+From 0094872a5e8e4664c6ea1b2dfa487063d39ae363 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add MAC register initialization for
+ RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800.h | 14 ++++++++++++++
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 19 ++++++++++++++++---
+ 2 files changed, 30 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
+@@ -1727,6 +1727,20 @@
+ #define TX_PWR_CFG_9B_STBC_MCS7 FIELD32(0x000000ff)
+
+ /*
++ * TX_TXBF_CFG:
++ */
++#define TX_TXBF_CFG_0 0x138c
++#define TX_TXBF_CFG_1 0x13a4
++#define TX_TXBF_CFG_2 0x13a8
++#define TX_TXBF_CFG_3 0x13ac
++
++/*
++ * TX_FBK_CFG_3S:
++ */
++#define TX_FBK_CFG_3S_0 0x13c4
++#define TX_FBK_CFG_3S_1 0x13c8
++
++/*
+ * RX_FILTER_CFG: RX configuration register.
+ */
+ #define RX_FILTER_CFG 0x1400
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -5509,6 +5509,12 @@ static int rt2800_init_registers(struct
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2,
+ 0x00000000);
+ }
++ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
++ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
++ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00040000);
++ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
++ rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
+ } else if (rt2x00_rt(rt2x00dev, RT5390) ||
+ rt2x00_rt(rt2x00dev, RT5392) ||
+ rt2x00_rt(rt2x00dev, RT6352)) {
+@@ -5722,6 +5728,11 @@ static int rt2800_init_registers(struct
+ reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002;
+ rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);
+
++ if (rt2x00_rt(rt2x00dev, RT3883)) {
++ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_0, 0x12111008);
++ rt2800_register_write(rt2x00dev, TX_FBK_CFG_3S_1, 0x16151413);
++ }
++
+ reg = rt2800_register_read(rt2x00dev, TX_RTS_CFG);
+ rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 7);
+ rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES,
--- /dev/null
+From 6c2d32478159fffff0b85abb6817a21bb2338231 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:27 +0100
+Subject: [PATCH] rt2x00: rt2800soc: fix rt2800soc_disable_radio for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800soc.c | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+@@ -51,9 +51,16 @@ static bool rt2800soc_hwcrypt_disabled(s
+
+ static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev)
+ {
++ u32 reg;
++
+ rt2800_disable_radio(rt2x00dev);
+ rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+- rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0);
++
++ reg = 0;
++ if (rt2x00_rt(rt2x00dev, RT3883))
++ rt2x00_set_field32(®, TX_PIN_CFG_RFTR_EN, 1);
++
++ rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, reg);
+ }
+
+ static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev,
--- /dev/null
+From 84833056aa7dd25f5b097e31c78f2a0914c5160c Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:26 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add BBP register initialization for
+ RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 44 +++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -6349,6 +6349,47 @@ static void rt2800_init_bbp_3593(struct
+ rt2800_bbp_write(rt2x00dev, 103, 0xc0);
+ }
+
++static void rt2800_init_bbp_3883(struct rt2x00_dev *rt2x00dev)
++{
++ rt2800_init_bbp_early(rt2x00dev);
++
++ rt2800_bbp_write(rt2x00dev, 4, 0x50);
++ rt2800_bbp_write(rt2x00dev, 47, 0x48);
++
++ rt2800_bbp_write(rt2x00dev, 86, 0x46);
++ rt2800_bbp_write(rt2x00dev, 88, 0x90);
++
++ rt2800_bbp_write(rt2x00dev, 92, 0x02);
++
++ rt2800_bbp_write(rt2x00dev, 103, 0xc0);
++ rt2800_bbp_write(rt2x00dev, 104, 0x92);
++ rt2800_bbp_write(rt2x00dev, 105, 0x34);
++ rt2800_bbp_write(rt2x00dev, 106, 0x12);
++ rt2800_bbp_write(rt2x00dev, 120, 0x50);
++ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
++ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
++
++ /* Set ITxBF timeout to 0x9C40=1000msec */
++ rt2800_bbp_write(rt2x00dev, 179, 0x02);
++ rt2800_bbp_write(rt2x00dev, 180, 0x00);
++ rt2800_bbp_write(rt2x00dev, 182, 0x40);
++ rt2800_bbp_write(rt2x00dev, 180, 0x01);
++ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
++
++ rt2800_bbp_write(rt2x00dev, 179, 0x00);
++
++ /* Reprogram the inband interface to put right values in RXWI */
++ rt2800_bbp_write(rt2x00dev, 142, 0x04);
++ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
++ rt2800_bbp_write(rt2x00dev, 142, 0x06);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
++ rt2800_bbp_write(rt2x00dev, 142, 0x07);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
++ rt2800_bbp_write(rt2x00dev, 142, 0x08);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
++ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
++}
++
+ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev)
+ {
+ int ant, div_mode;
+@@ -6792,6 +6833,9 @@ static void rt2800_init_bbp(struct rt2x0
+ case RT3593:
+ rt2800_init_bbp_3593(rt2x00dev);
+ return;
++ case RT3883:
++ rt2800_init_bbp_3883(rt2x00dev);
++ return;
+ case RT5390:
+ case RT5392:
+ rt2800_init_bbp_53xx(rt2x00dev);
--- /dev/null
+From 99c659cf345640fd0f733cbcaf4583cc2c868ec0 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 29 Apr 2013 13:21:48 +0200
+Subject: [PATCH] rt2x00: rt2800lib: add RFCSR initialization for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800.h | 1 +
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 141 +++++++++++++++++++++++++++++++
+ 2 files changed, 142 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
+@@ -2311,6 +2311,7 @@ struct mac_iveiv_entry {
+ /*
+ * RFCSR 2:
+ */
++#define RFCSR2_RESCAL_BP FIELD8(0x40)
+ #define RFCSR2_RESCAL_EN FIELD8(0x80)
+ #define RFCSR2_RX2_EN_MT7620 FIELD8(0x02)
+ #define RFCSR2_TX2_EN_MT7620 FIELD8(0x20)
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -7707,6 +7707,144 @@ static void rt2800_init_rfcsr_5350(struc
+ rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
+ }
+
++static void rt2800_init_rfcsr_3883(struct rt2x00_dev *rt2x00dev)
++{
++ u8 rfcsr;
++
++ /* TODO: get the actual ECO value from the SoC */
++ const unsigned int eco = 5;
++
++ rt2800_rf_init_calibration(rt2x00dev, 2);
++
++ rt2800_rfcsr_write(rt2x00dev, 0, 0xe0);
++ rt2800_rfcsr_write(rt2x00dev, 1, 0x03);
++ rt2800_rfcsr_write(rt2x00dev, 2, 0x50);
++ rt2800_rfcsr_write(rt2x00dev, 3, 0x20);
++ rt2800_rfcsr_write(rt2x00dev, 4, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 5, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 6, 0x40);
++ rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 8, 0x5b);
++ rt2800_rfcsr_write(rt2x00dev, 9, 0x08);
++ rt2800_rfcsr_write(rt2x00dev, 10, 0xd3);
++ rt2800_rfcsr_write(rt2x00dev, 11, 0x48);
++ rt2800_rfcsr_write(rt2x00dev, 12, 0x1a);
++ rt2800_rfcsr_write(rt2x00dev, 13, 0x12);
++ rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
++
++ /* RFCSR 17 will be initialized later based on the
++ * frequency offset stored in the EEPROM
++ */
++
++ rt2800_rfcsr_write(rt2x00dev, 18, 0x40);
++ rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
++ rt2800_rfcsr_write(rt2x00dev, 23, 0xc0);
++ rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 25, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 27, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 29, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 30, 0x10);
++ rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
++ rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 34, 0x20);
++ rt2800_rfcsr_write(rt2x00dev, 35, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 37, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 38, 0x86);
++ rt2800_rfcsr_write(rt2x00dev, 39, 0x23);
++ rt2800_rfcsr_write(rt2x00dev, 40, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 41, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 42, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 43, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 44, 0x93);
++ rt2800_rfcsr_write(rt2x00dev, 45, 0xbb);
++ rt2800_rfcsr_write(rt2x00dev, 46, 0x60);
++ rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 48, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 49, 0x8e);
++ rt2800_rfcsr_write(rt2x00dev, 50, 0x86);
++ rt2800_rfcsr_write(rt2x00dev, 51, 0x51);
++ rt2800_rfcsr_write(rt2x00dev, 52, 0x05);
++ rt2800_rfcsr_write(rt2x00dev, 53, 0x76);
++ rt2800_rfcsr_write(rt2x00dev, 54, 0x76);
++ rt2800_rfcsr_write(rt2x00dev, 55, 0x76);
++ rt2800_rfcsr_write(rt2x00dev, 56, 0xdb);
++ rt2800_rfcsr_write(rt2x00dev, 57, 0x3e);
++ rt2800_rfcsr_write(rt2x00dev, 58, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 59, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 60, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 61, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
++ rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
++
++ /* TODO: rx filter calibration? */
++
++ rt2800_bbp_write(rt2x00dev, 137, 0x0f);
++
++ rt2800_bbp_write(rt2x00dev, 163, 0x9d);
++
++ rt2800_bbp_write(rt2x00dev, 105, 0x05);
++
++ rt2800_bbp_write(rt2x00dev, 179, 0x02);
++ rt2800_bbp_write(rt2x00dev, 180, 0x00);
++ rt2800_bbp_write(rt2x00dev, 182, 0x40);
++ rt2800_bbp_write(rt2x00dev, 180, 0x01);
++ rt2800_bbp_write(rt2x00dev, 182, 0x9c);
++
++ rt2800_bbp_write(rt2x00dev, 179, 0x00);
++
++ rt2800_bbp_write(rt2x00dev, 142, 0x04);
++ rt2800_bbp_write(rt2x00dev, 143, 0x3b);
++ rt2800_bbp_write(rt2x00dev, 142, 0x06);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa0);
++ rt2800_bbp_write(rt2x00dev, 142, 0x07);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa1);
++ rt2800_bbp_write(rt2x00dev, 142, 0x08);
++ rt2800_bbp_write(rt2x00dev, 143, 0xa2);
++ rt2800_bbp_write(rt2x00dev, 148, 0xc8);
++
++ if (eco == 5) {
++ rt2800_rfcsr_write(rt2x00dev, 32, 0xd8);
++ rt2800_rfcsr_write(rt2x00dev, 33, 0x32);
++ }
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 2);
++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_BP, 0);
++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
++ msleep(1);
++ rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0);
++ rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 1);
++ rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
++ rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 6);
++ rfcsr |= 0xc0;
++ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 22);
++ rfcsr |= 0x20;
++ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 46);
++ rfcsr |= 0x20;
++ rt2800_rfcsr_write(rt2x00dev, 46, rfcsr);
++
++ rfcsr = rt2800_rfcsr_read(rt2x00dev, 20);
++ rfcsr &= ~0xee;
++ rt2800_rfcsr_write(rt2x00dev, 20, rfcsr);
++}
++
+ static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev)
+ {
+ rt2800_rf_init_calibration(rt2x00dev, 2);
+@@ -8549,6 +8687,9 @@ static void rt2800_init_rfcsr(struct rt2
+ case RT3390:
+ rt2800_init_rfcsr_3390(rt2x00dev);
+ break;
++ case RT3883:
++ rt2800_init_rfcsr_3883(rt2x00dev);
++ break;
+ case RT3572:
+ rt2800_init_rfcsr_3572(rt2x00dev);
+ break;
--- /dev/null
+From 86022438ffeb1b87dfcd018bf477fdbb43076691 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Wed, 8 May 2013 19:35:33 +0200
+Subject: [PATCH] rt2x00: rt2800lib: use the extended EEPROM map for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -381,7 +381,8 @@ static unsigned int rt2800_eeprom_word_i
+ wiphy_name(rt2x00dev->hw->wiphy), word))
+ return 0;
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ map = rt2800_eeprom_map_ext;
+ else
+ map = rt2800_eeprom_map;
--- /dev/null
+From 4cf5403f02fa65dc2207f61d223cffa9ae50e907 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Thu, 1 Aug 2013 14:48:21 +0200
+Subject: [PATCH] rt2x00: rt2800lib: force rf type to RF3853 on RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -9083,6 +9083,8 @@ static int rt2800_init_eeprom(struct rt2
+ rf = rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID);
+ else if (rt2x00_rt(rt2x00dev, RT3352))
+ rf = RF3322;
++ else if (rt2x00_rt(rt2x00dev, RT3883))
++ rf = RF3853;
+ else if (rt2x00_rt(rt2x00dev, RT5350))
+ rf = RF5350;
+ else
--- /dev/null
+From 269f19c848a2380db03a3f207cafb88e28d71c53 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:28 +0100
+Subject: [PATCH] rt2x00: rt2800lib: add channel configuration code for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 72 +++++++++++++++++++++++++++++--
+ 1 file changed, 69 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -3738,6 +3738,36 @@ static char rt2800_txpower_to_dev(struct
+ return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER);
+ }
+
++static void rt3883_bbp_adjust(struct rt2x00_dev *rt2x00dev,
++ struct rf_channel *rf)
++{
++ u8 bbp;
++
++ bbp = (rf->channel > 14) ? 0x48 : 0x38;
++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, bbp);
++
++ rt2800_bbp_write(rt2x00dev, 69, 0x12);
++
++ if (rf->channel <= 14) {
++ rt2800_bbp_write(rt2x00dev, 70, 0x0a);
++ } else {
++ /* Disable CCK packet detection */
++ rt2800_bbp_write(rt2x00dev, 70, 0x00);
++ }
++
++ rt2800_bbp_write(rt2x00dev, 73, 0x10);
++
++ if (rf->channel > 14) {
++ rt2800_bbp_write(rt2x00dev, 62, 0x1d);
++ rt2800_bbp_write(rt2x00dev, 63, 0x1d);
++ rt2800_bbp_write(rt2x00dev, 64, 0x1d);
++ } else {
++ rt2800_bbp_write(rt2x00dev, 62, 0x2d);
++ rt2800_bbp_write(rt2x00dev, 63, 0x2d);
++ rt2800_bbp_write(rt2x00dev, 64, 0x2d);
++ }
++}
++
+ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+@@ -3756,6 +3786,12 @@ static void rt2800_config_channel(struct
+ rt2800_txpower_to_dev(rt2x00dev, rf->channel,
+ info->default_power3);
+
++ switch (rt2x00dev->chip.rt) {
++ case RT3883:
++ rt3883_bbp_adjust(rt2x00dev, rf);
++ break;
++ }
++
+ switch (rt2x00dev->chip.rf) {
+ case RF2020:
+ case RF3020:
+@@ -3860,6 +3896,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);
++ } else if (rt2x00_rt(rt2x00dev, RT3883)) {
++ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
++ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
++
++ if (rt2x00dev->default_ant.rx_chain_num > 1)
++ rt2800_bbp_write(rt2x00dev, 86, 0x46);
++ else
++ rt2800_bbp_write(rt2x00dev, 86, 0);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+@@ -3873,6 +3918,7 @@ static void rt2800_config_channel(struct
+ !rt2x00_rt(rt2x00dev, RT6352)) {
+ if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {
+ rt2800_bbp_write(rt2x00dev, 82, 0x62);
++ rt2800_bbp_write(rt2x00dev, 82, 0x62);
+ rt2800_bbp_write(rt2x00dev, 75, 0x46);
+ } else {
+ if (rt2x00_rt(rt2x00dev, RT3593))
+@@ -3881,19 +3927,22 @@ static void rt2800_config_channel(struct
+ rt2800_bbp_write(rt2x00dev, 82, 0x84);
+ rt2800_bbp_write(rt2x00dev, 75, 0x50);
+ }
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ rt2800_bbp_write(rt2x00dev, 83, 0x8a);
+ }
+
+ } else {
+ if (rt2x00_rt(rt2x00dev, RT3572))
+ rt2800_bbp_write(rt2x00dev, 82, 0x94);
+- else if (rt2x00_rt(rt2x00dev, RT3593))
++ else if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ rt2800_bbp_write(rt2x00dev, 82, 0x82);
+ else if (!rt2x00_rt(rt2x00dev, RT6352))
+ rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ rt2800_bbp_write(rt2x00dev, 83, 0x9a);
+
+ if (rt2x00_has_cap_external_lna_a(rt2x00dev))
+@@ -4019,6 +4068,23 @@ static void rt2800_config_channel(struct
+
+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
+
++ usleep_range(1000, 1500);
++ }
++
++ if (rt2x00_rt(rt2x00dev, RT3883)) {
++ if (!conf_is_ht40(conf))
++ rt2800_bbp_write(rt2x00dev, 105, 0x34);
++ else
++ rt2800_bbp_write(rt2x00dev, 105, 0x04);
++
++ /* AGC init */
++ if (rf->channel <= 14)
++ reg = 0x2e + rt2x00dev->lna_gain;
++ else
++ reg = 0x20 + ((rt2x00dev->lna_gain * 5) / 3);
++
++ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
++
+ usleep_range(1000, 1500);
+ }
+
--- /dev/null
+From e37d93abaabe3ab72b0332a18092acc162307274 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 30 Sep 2013 13:57:26 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix txpower_to_dev function for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -3725,13 +3725,15 @@ static char rt2800_txpower_to_dev(struct
+ unsigned int channel,
+ char txpower)
+ {
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC);
+
+ if (channel <= 14)
+ return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER);
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ return clamp_t(char, txpower, MIN_A_TXPOWER_3593,
+ MAX_A_TXPOWER_3593);
+ else
--- /dev/null
+From c4d79e344bd580d85821390d49f92dced7d8e125 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:29 +0100
+Subject: [PATCH] rt2x00: rt2800lib: use correct txpower calculation function
+ for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -5111,7 +5111,8 @@ static void rt2800_config_txpower(struct
+ struct ieee80211_channel *chan,
+ int power_level)
+ {
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level);
+ else if (rt2x00_rt(rt2x00dev, RT6352))
+ rt2800_config_txpower_rt6352(rt2x00dev, chan, power_level);
--- /dev/null
+From caea0671cd8fd9ade4f5969cbe0ee545e94ae105 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sat, 24 Aug 2013 11:49:55 +0200
+Subject: [PATCH] rt2x00: rt2800lib: hardcode txmixer gain values to zero for
+ RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -8965,7 +8965,8 @@ static u8 rt2800_get_txmixer_gain_24g(st
+ {
+ u16 word;
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ return 0;
+
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG);
+@@ -8979,7 +8980,8 @@ static u8 rt2800_get_txmixer_gain_5g(str
+ {
+ u16 word;
+
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ return 0;
+
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A);
--- /dev/null
+From 11c40fb47c4a4dd6ad060c2ae127ced89ffb9fe1 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Thu, 18 Apr 2013 14:33:33 +0200
+Subject: [PATCH] rt2x00: rt2800lib: use correct [RT]XWI size for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -591,6 +591,7 @@ void rt2800_get_txwi_rxwi_size(struct rt
+ {
+ switch (rt2x00dev->chip.rt) {
+ case RT3593:
++ case RT3883:
+ *txwi_size = TXWI_DESC_SIZE_4WORDS;
+ *rxwi_size = RXWI_DESC_SIZE_5WORDS;
+ break;
--- /dev/null
+From fa5ad9c025610c22048add2f0ad03f62b6ca1e74 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 30 Sep 2013 16:53:33 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix antenna configuration for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -2017,7 +2017,8 @@ void rt2800_config_ant(struct rt2x00_dev
+ rt2800_bbp_write(rt2x00dev, 3, r3);
+ rt2800_bbp_write(rt2x00dev, 1, r1);
+
+- if (rt2x00_rt(rt2x00dev, RT3593)) {
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ if (ant->rx_chain_num == 1)
+ rt2800_bbp_write(rt2x00dev, 86, 0x00);
+ else
--- /dev/null
+From 6d668fef3a1baa60bdd715ee062ddb6333d2647c Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Mon, 30 Sep 2013 16:58:23 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix LNA gain configuration for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -2040,7 +2040,8 @@ static void rt2800_config_lna_gain(struc
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_LNA);
+ lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
+ } else if (libconf->rf.channel <= 128) {
+- if (rt2x00_rt(rt2x00dev, RT3593)) {
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
+ lna_gain = rt2x00_get_field16(eeprom,
+ EEPROM_EXT_LNA2_A1);
+@@ -2050,7 +2051,8 @@ static void rt2800_config_lna_gain(struc
+ EEPROM_RSSI_BG2_LNA_A1);
+ }
+ } else {
+- if (rt2x00_rt(rt2x00dev, RT3593)) {
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
+ lna_gain = rt2x00_get_field16(eeprom,
+ EEPROM_EXT_LNA2_A2);
--- /dev/null
+From c49b2d829aa1c816a46a577cdec6d2ff14d9f06e Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Tue, 1 Oct 2013 15:40:08 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix VGC setup for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -5364,7 +5364,8 @@ static u8 rt2800_get_default_vgc(struct
+ else
+ vgc = 0x2e + rt2x00dev->lna_gain;
+ } else { /* 5GHZ band */
+- if (rt2x00_rt(rt2x00dev, RT3593))
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883))
+ vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3;
+ else if (rt2x00_rt(rt2x00dev, RT5592))
+ vgc = 0x24 + (2 * rt2x00dev->lna_gain);
+@@ -5384,7 +5385,8 @@ static inline void rt2800_set_vgc(struct
+ {
+ if (qual->vgc_level != vgc_level) {
+ if (rt2x00_rt(rt2x00dev, RT3572) ||
+- rt2x00_rt(rt2x00dev, RT3593)) {
++ rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
+ vgc_level);
+ } else if (rt2x00_rt(rt2x00dev, RT5592)) {
+@@ -5431,6 +5433,11 @@ void rt2800_link_tuner(struct rt2x00_dev
+ }
+ break;
+
++ case RT3883:
++ if (qual->rssi > -65)
++ vgc += 0x10;
++ break;
++
+ case RT5592:
+ if (qual->rssi > -65)
+ vgc += 0x20;
--- /dev/null
+From 1616650aea676541d4dc8adc6f4219856d193c8b Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Tue, 1 Oct 2013 17:27:57 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix EEPROM LNA validation for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -9098,7 +9098,8 @@ static int rt2800_validate_eeprom(struct
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2);
+ if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
+ rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
+- if (!rt2x00_rt(rt2x00dev, RT3593)) {
++ if (!rt2x00_rt(rt2x00dev, RT3593) &&
++ !rt2x00_rt(rt2x00dev, RT3883)) {
+ 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,
+@@ -9118,7 +9119,8 @@ static int rt2800_validate_eeprom(struct
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2);
+ if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
+ rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
+- if (!rt2x00_rt(rt2x00dev, RT3593)) {
++ if (!rt2x00_rt(rt2x00dev, RT3593) &&
++ !rt2x00_rt(rt2x00dev, RT3883)) {
+ 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,
+@@ -9126,7 +9128,8 @@ static int rt2800_validate_eeprom(struct
+ }
+ rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
+
+- if (rt2x00_rt(rt2x00dev, RT3593)) {
++ if (rt2x00_rt(rt2x00dev, RT3593) ||
++ rt2x00_rt(rt2x00dev, RT3883)) {
+ word = rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2);
+ if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 ||
+ rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff)
--- /dev/null
+From e3871034a0e7c8a95152dc3eafbcc4535398cbdc Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Wed, 2 Oct 2013 10:11:59 +0200
+Subject: [PATCH] rt2x00: rt2800lib: fix txpower compensation for RT3883
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -4354,6 +4354,9 @@ static u8 rt2800_compensate_txpower(stru
+ if (rt2x00_rt(rt2x00dev, RT3593))
+ return min_t(u8, txpower, 0xc);
+
++ if (rt2x00_rt(rt2x00dev, RT3883))
++ return min_t(u8, txpower, 0xf);
++
+ if (rt2x00_has_cap_power_limit(rt2x00dev)) {
+ /*
+ * Check if eirp txpower exceed txpower_limit.
--- /dev/null
+From 5e67d4f8a46d19748b501c2ef86de3f50d3cfd51 Mon Sep 17 00:00:00 2001
+From: Gabor Juhos <juhosg@openwrt.org>
+Date: Sun, 24 Mar 2013 19:26:27 +0100
+Subject: [PATCH] rt2x00: rt2800mmio: add a workaround for spurious
+ TX_FIFO_STATUS interrupts
+
+Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800mmio.c | 72 +++++++++++++++++++++++++-----
+ drivers/net/wireless/ralink/rt2x00/rt2x00.h | 5 +++
+ 2 files changed, 65 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800mmio.c
+@@ -424,9 +424,9 @@ void rt2800mmio_autowake_tasklet(unsigne
+ }
+ EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet);
+
+-static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
++static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev,
++ u32 status)
+ {
+- u32 status;
+ int i;
+
+ /*
+@@ -447,29 +447,77 @@ static void rt2800mmio_txstatus_interrup
+ * Since we have only one producer and one consumer we don't
+ * need to lock the kfifo.
+ */
+- for (i = 0; i < rt2x00dev->tx->limit; i++) {
+- status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
+-
+- if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
+- break;
+-
++ i = 0;
++ do {
+ if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) {
+- rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n");
++ rt2x00_warn(rt2x00dev,
++ "TX status FIFO overrun, drop TX status report\n");
+ break;
+ }
+- }
++
++ if (++i >= rt2x00dev->tx->limit)
++ break;
++
++ status = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
++ } while (rt2x00_get_field32(status, TX_STA_FIFO_VALID));
+
+ /* Schedule the tasklet for processing the tx status. */
+ tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+ }
+
++#define RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES 4
++
++static bool rt2800mmio_txstatus_is_spurious(struct rt2x00_dev *rt2x00dev,
++ u32 txstatus)
++{
++ if (likely(rt2x00_get_field32(txstatus, TX_STA_FIFO_VALID))) {
++ rt2x00dev->txstatus_irq_retries = 0;
++ return false;
++ }
++
++ rt2x00dev->txstatus_irq_retries++;
++
++ /* Ensure that we don't go into an infinite IRQ loop. */
++ if (rt2x00dev->txstatus_irq_retries >=
++ RT2800MMIO_TXSTATUS_IRQ_MAX_RETRIES) {
++ rt2x00_warn(rt2x00dev,
++ "%u spurious TX_FIFO_STATUS interrupt(s)\n",
++ rt2x00dev->txstatus_irq_retries);
++ rt2x00dev->txstatus_irq_retries = 0;
++ return false;
++ }
++
++ return true;
++}
++
+ irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance)
+ {
+ struct rt2x00_dev *rt2x00dev = dev_instance;
+ u32 reg, mask;
++ u32 txstatus = 0;
+
+- /* Read status and ACK all interrupts */
++ /* Read status */
+ reg = rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR);
++
++ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
++ /* Due to unknown reason the hardware generates a
++ * TX_FIFO_STATUS interrupt before the TX_STA_FIFO
++ * register contain valid data. Read the TX status
++ * here to see if we have to process the actual
++ * request.
++ */
++ txstatus = rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO);
++ if (rt2800mmio_txstatus_is_spurious(rt2x00dev, txstatus)) {
++ /* Remove the TX_FIFO_STATUS bit so it won't be
++ * processed in this turn. The hardware will
++ * generate another IRQ for us.
++ */
++ rt2x00_set_field32(®,
++ INT_SOURCE_CSR_TX_FIFO_STATUS, 0);
++ }
++ }
++
++ /* ACK interrupts */
+ rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+ if (!reg)
+@@ -486,7 +534,7 @@ irqreturn_t rt2800mmio_interrupt(int irq
+ mask = ~reg;
+
+ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
+- rt2800mmio_txstatus_interrupt(rt2x00dev);
++ rt2800mmio_txstatus_interrupt(rt2x00dev, txstatus);
+ /*
+ * Never disable the TX_FIFO_STATUS interrupt.
+ */
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -1000,6 +1000,11 @@ struct rt2x00_dev {
+ int rf_channel;
+
+ /*
++ * Counter for tx status irq retries (rt2800pci).
++ */
++ unsigned int txstatus_irq_retries;
++
++ /*
+ * Protect the interrupt mask register.
+ */
+ spinlock_t irqmask_lock;
--- /dev/null
+--- /dev/null
++++ b/include/linux/rt2x00_platform.h
+@@ -0,0 +1,19 @@
++/*
++ * Platform data definition for the rt2x00 driver
++ *
++ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published
++ * by the Free Software Foundation.
++ *
++ */
++
++#ifndef _RT2X00_PLATFORM_H
++#define _RT2X00_PLATFORM_H
++
++struct rt2x00_platform_data {
++ char *eeprom_file_name;
++};
++
++#endif /* _RT2X00_PLATFORM_H */
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -40,6 +40,7 @@
+ #include <linux/average.h>
+ #include <linux/usb.h>
+ #include <linux/clk.h>
++#include <linux/rt2x00_platform.h>
+
+ #include <net/mac80211.h>
+
--- /dev/null
+--- a/local-symbols
++++ b/local-symbols
+@@ -299,6 +299,7 @@ RT2X00_LIB_FIRMWARE=
+ RT2X00_LIB_CRYPTO=
+ RT2X00_LIB_LEDS=
+ RT2X00_LIB_DEBUGFS=
++RT2X00_LIB_EEPROM=
+ RT2X00_DEBUG=
+ WLAN_VENDOR_REALTEK=
+ RTL8180=
+--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
+@@ -69,6 +69,7 @@ config RT2800PCI
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_PCI
+ select RT2X00_LIB_FIRMWARE
++ select RT2X00_LIB_EEPROM
+ select RT2X00_LIB_CRYPTO
+ depends on CRC_CCITT
+ depends on EEPROM_93CX6
+@@ -215,6 +216,7 @@ config RT2800SOC
+ select RT2X00_LIB_MMIO
+ select RT2X00_LIB_CRYPTO
+ select RT2X00_LIB_FIRMWARE
++ select RT2X00_LIB_EEPROM
+ select RT2800_LIB
+ select RT2800_LIB_MMIO
+ ---help---
+@@ -265,6 +267,9 @@ config RT2X00_LIB_FIRMWARE
+ config RT2X00_LIB_CRYPTO
+ bool
+
++config RT2X00_LIB_EEPROM
++ boolean
++
+ config RT2X00_LIB_LEDS
+ bool
+ default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n)
+--- a/drivers/net/wireless/ralink/rt2x00/Makefile
++++ b/drivers/net/wireless/ralink/rt2x00/Makefile
+@@ -7,6 +7,7 @@ rt2x00lib-$(CPTCFG_RT2X00_LIB_DEBUGFS) +
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o
+ rt2x00lib-$(CPTCFG_RT2X00_LIB_LEDS) += rt2x00leds.o
++rt2x00lib-$(CPTCFG_RT2X00_LIB_EEPROM) += rt2x00eeprom.o
+
+ obj-$(CPTCFG_RT2X00_LIB) += rt2x00lib.o
+ obj-$(CPTCFG_RT2X00_LIB_MMIO) += rt2x00mmio.o
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h
+@@ -48,6 +48,8 @@ struct rt2800_drv_data {
+ struct ieee80211_sta *wcid_to_sta[STA_IDS_SIZE];
+ };
+
++#include "rt2800.h"
++
+ struct rt2800_ops {
+ u32 (*register_read)(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset);
+@@ -145,6 +147,15 @@ static inline int rt2800_read_eeprom(str
+ {
+ const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv;
+
++ if (rt2x00dev->eeprom_file) {
++ memcpy(rt2x00dev->eeprom, rt2x00dev->eeprom_file->data,
++ EEPROM_SIZE);
++ return 0;
++ }
++
++ if (!rt2800ops->read_eeprom)
++ return -EINVAL;
++
+ return rt2800ops->read_eeprom(rt2x00dev);
+ }
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+@@ -102,19 +102,6 @@ static int rt2800soc_set_device_state(st
+ return retval;
+ }
+
+-static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev)
+-{
+- void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
+-
+- if (!base_addr)
+- return -ENOMEM;
+-
+- memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE);
+-
+- iounmap(base_addr);
+- return 0;
+-}
+-
+ /* Firmware functions */
+ static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -178,7 +165,6 @@ static const struct rt2800_ops rt2800soc
+ .register_multiread = rt2x00mmio_register_multiread,
+ .register_multiwrite = rt2x00mmio_register_multiwrite,
+ .regbusy_read = rt2x00mmio_regbusy_read,
+- .read_eeprom = rt2800soc_read_eeprom,
+ .hwcrypt_disabled = rt2800soc_hwcrypt_disabled,
+ .drv_write_firmware = rt2800soc_write_firmware,
+ .drv_init_registers = rt2800mmio_init_registers,
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -702,6 +702,7 @@ enum rt2x00_capability_flags {
+ REQUIRE_HT_TX_DESC,
+ REQUIRE_PS_AUTOWAKE,
+ REQUIRE_DELAYED_RFKILL,
++ REQUIRE_EEPROM_FILE,
+
+ /*
+ * Capabilities
+@@ -977,6 +978,11 @@ struct rt2x00_dev {
+ const struct firmware *fw;
+
+ /*
++ * EEPROM image.
++ */
++ const struct firmware *eeprom_file;
++
++ /*
+ * FIFO for storing tx status reports between isr and tasklet.
+ */
+ DECLARE_KFIFO_PTR(txstatus_fifo, u32);
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+@@ -1421,6 +1421,10 @@ int rt2x00lib_probe_dev(struct rt2x00_de
+ INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
+ INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
+
++ retval = rt2x00lib_load_eeprom_file(rt2x00dev);
++ if (retval)
++ goto exit;
++
+ /*
+ * Let the driver probe the device to detect the capabilities.
+ */
+@@ -1562,6 +1566,11 @@ void rt2x00lib_remove_dev(struct rt2x00_
+ * Free the driver data.
+ */
+ kfree(rt2x00dev->drv_data);
++
++ /*
++ * Free EEPROM image.
++ */
++ rt2x00lib_free_eeprom_file(rt2x00dev);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);
+
+--- /dev/null
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+@@ -0,0 +1,105 @@
++/*
++ Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
++ Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
++ <http://rt2x00.serialmonkey.com>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the
++ Free Software Foundation, Inc.,
++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ */
++
++/*
++ Module: rt2x00lib
++ Abstract: rt2x00 eeprom file loading routines.
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#include "rt2x00.h"
++#include "rt2x00lib.h"
++
++static const char *
++rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
++{
++ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
++
++ if (pdata && pdata->eeprom_file_name)
++ return pdata->eeprom_file_name;
++
++ return NULL
++}
++
++static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ const struct firmware *ee;
++ const char *ee_name;
++ int retval;
++
++ ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
++ if (!ee_name && test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags)) {
++ rt2x00_err(rt2x00dev, "Required EEPROM name is missing.");
++ return -EINVAL;
++ }
++
++ if (!ee_name)
++ return 0;
++
++ rt2x00_info(rt2x00dev, "Loading EEPROM data from '%s'.\n", ee_name);
++
++ retval = request_firmware(&ee, ee_name, rt2x00dev->dev);
++ if (retval) {
++ rt2x00_err(rt2x00dev, "Failed to request EEPROM.\n");
++ return retval;
++ }
++
++ if (!ee || !ee->size || !ee->data) {
++ rt2x00_err(rt2x00dev, "Failed to read EEPROM file.\n");
++ retval = -ENOENT;
++ goto err_exit;
++ }
++
++ if (ee->size != rt2x00dev->ops->eeprom_size) {
++ rt2x00_err(rt2x00dev,
++ "EEPROM file size is invalid, it should be %d bytes\n",
++ rt2x00dev->ops->eeprom_size);
++ retval = -EINVAL;
++ goto err_release_ee;
++ }
++
++ rt2x00dev->eeprom_file = ee;
++ return 0;
++
++err_release_ee:
++ release_firmware(ee);
++err_exit:
++ return retval;
++}
++
++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ int retval;
++
++ retval = rt2x00lib_request_eeprom_file(rt2x00dev);
++ if (retval)
++ return retval;
++
++ return 0;
++}
++
++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ release_firmware(rt2x00dev->eeprom_file);
++ rt2x00dev->eeprom_file = NULL;
++}
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00lib.h
+@@ -297,6 +297,22 @@ static inline void rt2x00lib_free_firmwa
+ #endif /* CPTCFG_RT2X00_LIB_FIRMWARE */
+
+ /*
++ * EEPROM file handlers.
++ */
++#ifdef CPTCFG_RT2X00_LIB_EEPROM
++int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev);
++void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev);
++#else
++static inline int rt2x00lib_load_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++ return 0;
++}
++static inline void rt2x00lib_free_eeprom_file(struct rt2x00_dev *rt2x00dev)
++{
++}
++#endif /* CPTCFG_RT2X00_LIB_EEPROM */
++
++/*
+ * Debugfs handlers.
+ */
+ #ifdef CPTCFG_RT2X00_LIB_DEBUGFS
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00soc.c
+@@ -97,6 +97,7 @@ int rt2x00soc_probe(struct platform_devi
+ if (IS_ERR(rt2x00dev->clk))
+ rt2x00dev->clk = NULL;
+
++ set_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags);
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
+
+ retval = rt2x00soc_alloc_reg(rt2x00dev);
--- /dev/null
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+@@ -26,6 +26,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/of.h>
+
+ #include "rt2x00.h"
+ #include "rt2x00lib.h"
+@@ -34,11 +35,21 @@ static const char *
+ rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
+ {
+ struct rt2x00_platform_data *pdata = rt2x00dev->dev->platform_data;
++#ifdef CONFIG_OF
++ struct device_node *np;
++ const char *eep;
++#endif
+
+ if (pdata && pdata->eeprom_file_name)
+ return pdata->eeprom_file_name;
+
+- return NULL
++#ifdef CONFIG_OF
++ np = rt2x00dev->dev->of_node;
++ if (np && of_property_read_string(np, "ralink,eeprom", &eep) == 0)
++ return eep;
++#endif
++
++ return NULL;
+ }
+
+ static int rt2x00lib_request_eeprom_file(struct rt2x00_dev *rt2x00dev)
--- /dev/null
+From 339fe73f340161a624cc08e738d2244814852c3e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 17 Mar 2013 00:55:04 +0100
+Subject: [PATCH] rt2x00: load eeprom on SoC from a mtd device defines inside
+ OF
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/Kconfig | 1 +
+ drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c | 65 +++++++++++++++++++++++
+ 2 files changed, 66 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/Kconfig
++++ b/drivers/net/wireless/ralink/rt2x00/Kconfig
+@@ -219,6 +219,7 @@ config RT2800SOC
+ select RT2X00_LIB_EEPROM
+ select RT2800_LIB
+ select RT2800_LIB_MMIO
++ select MTD if SOC_RT288X || SOC_RT305X
+ ---help---
+ This adds support for Ralink WiSoC devices.
+ Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352.
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00eeprom.c
+@@ -26,11 +26,73 @@
+
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
+ #include <linux/of.h>
+
+ #include "rt2x00.h"
+ #include "rt2x00lib.h"
+
++static int rt2800lib_read_eeprom_mtd(struct rt2x00_dev *rt2x00dev)
++{
++ int ret = -EINVAL;
++#ifdef CONFIG_OF
++ static struct firmware mtd_fw;
++ struct device_node *np = rt2x00dev->dev->of_node, *mtd_np = NULL;
++ size_t retlen, len = rt2x00dev->ops->eeprom_size;
++ int i, size, offset = 0;
++ struct mtd_info *mtd;
++ const char *part;
++ const __be32 *list;
++ phandle phandle;
++
++ list = of_get_property(np, "ralink,mtd-eeprom", &size);
++ if (!list)
++ return -ENOENT;
++
++ phandle = be32_to_cpup(list++);
++ if (phandle)
++ mtd_np = of_find_node_by_phandle(phandle);
++ if (!mtd_np) {
++ dev_err(rt2x00dev->dev, "failed to load mtd phandle\n");
++ return -EINVAL;
++ }
++
++ part = of_get_property(mtd_np, "label", NULL);
++ if (!part)
++ part = mtd_np->name;
++
++ mtd = get_mtd_device_nm(part);
++ if (IS_ERR(mtd)) {
++ dev_err(rt2x00dev->dev, "failed to get mtd device \"%s\"\n", part);
++ return PTR_ERR(mtd);
++ }
++
++ if (size > sizeof(*list))
++ offset = be32_to_cpup(list);
++
++ ret = mtd_read(mtd, offset, len, &retlen, (u_char *) rt2x00dev->eeprom);
++ put_mtd_device(mtd);
++
++ if ((retlen != rt2x00dev->ops->eeprom_size) || ret) {
++ dev_err(rt2x00dev->dev, "failed to load eeprom from device \"%s\"\n", part);
++ return ret;
++ }
++
++ if (of_find_property(np, "ralink,mtd-eeprom-swap", NULL))
++ for (i = 0; i < len/sizeof(u16); i++)
++ rt2x00dev->eeprom[i] = swab16(rt2x00dev->eeprom[i]);
++
++ rt2x00dev->eeprom_file = &mtd_fw;
++ mtd_fw.size = len;
++ mtd_fw.data = (const u8 *) rt2x00dev->eeprom;
++
++ dev_info(rt2x00dev->dev, "loaded eeprom from mtd device \"%s\"\n", part);
++#endif
++
++ return ret;
++}
++
+ static const char *
+ rt2x00lib_get_eeprom_file_name(struct rt2x00_dev *rt2x00dev)
+ {
+@@ -58,6 +120,9 @@ static int rt2x00lib_request_eeprom_file
+ const char *ee_name;
+ int retval;
+
++ if (!rt2800lib_read_eeprom_mtd(rt2x00dev))
++ return 0;
++
+ ee_name = rt2x00lib_get_eeprom_file_name(rt2x00dev);
+ if (!ee_name && test_bit(REQUIRE_EEPROM_FILE, &rt2x00dev->cap_flags)) {
+ rt2x00_err(rt2x00dev, "Required EEPROM name is missing.");
--- /dev/null
+--- a/include/linux/rt2x00_platform.h
++++ b/include/linux/rt2x00_platform.h
+@@ -14,6 +14,9 @@
+
+ struct rt2x00_platform_data {
+ char *eeprom_file_name;
++
++ int disable_2ghz;
++ int disable_5ghz;
+ };
+
+ #endif /* _RT2X00_PLATFORM_H */
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+@@ -1026,6 +1026,22 @@ static int rt2x00lib_probe_hw_modes(stru
+ unsigned int num_rates;
+ unsigned int i;
+
++ if (rt2x00dev->dev->platform_data) {
++ struct rt2x00_platform_data *pdata;
++
++ pdata = rt2x00dev->dev->platform_data;
++ if (pdata->disable_2ghz)
++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
++ if (pdata->disable_5ghz)
++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
++ }
++
++ if ((spec->supported_bands & SUPPORT_BAND_BOTH) == 0) {
++ rt2x00_err(rt2x00dev, "No supported bands\n");
++ return -EINVAL;
++ }
++
++
+ num_rates = 0;
+ if (spec->supported_rates & SUPPORT_RATE_CCK)
+ num_rates += 4;
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
+@@ -409,6 +409,7 @@ struct hw_mode_spec {
+ unsigned int supported_bands;
+ #define SUPPORT_BAND_2GHZ 0x00000001
+ #define SUPPORT_BAND_5GHZ 0x00000002
++#define SUPPORT_BAND_BOTH (SUPPORT_BAND_2GHZ | SUPPORT_BAND_5GHZ)
+
+ unsigned int supported_rates;
+ #define SUPPORT_RATE_CCK 0x00000001
--- /dev/null
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+@@ -1004,8 +1004,13 @@ static void rt2x00lib_rate(struct ieee80
+
+ void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr)
+ {
++ struct rt2x00_platform_data *pdata;
+ const char *mac_addr;
+
++ pdata = rt2x00dev->dev->platform_data;
++ if (pdata && pdata->mac_address)
++ ether_addr_copy(eeprom_mac_addr, pdata->mac_address);
++
+ mac_addr = of_get_mac_address(rt2x00dev->dev->of_node);
+ if (mac_addr)
+ ether_addr_copy(eeprom_mac_addr, mac_addr);
+--- a/include/linux/rt2x00_platform.h
++++ b/include/linux/rt2x00_platform.h
+@@ -14,6 +14,7 @@
+
+ struct rt2x00_platform_data {
+ char *eeprom_file_name;
++ const u8 *mac_address;
+
+ int disable_2ghz;
+ int disable_5ghz;
--- /dev/null
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+@@ -1030,6 +1030,16 @@ static int rt2x00lib_probe_hw_modes(stru
+ struct ieee80211_rate *rates;
+ unsigned int num_rates;
+ unsigned int i;
++#ifdef CONFIG_OF
++ struct device_node *np = rt2x00dev->dev->of_node;
++ unsigned int enabled;
++ if (!of_property_read_u32(np, "ralink,2ghz",
++ &enabled) && !enabled)
++ spec->supported_bands &= ~SUPPORT_BAND_2GHZ;
++ if (!of_property_read_u32(np, "ralink,5ghz",
++ &enabled) && !enabled)
++ spec->supported_bands &= ~SUPPORT_BAND_5GHZ;
++#endif /* CONFIG_OF */
+
+ if (rt2x00dev->dev->platform_data) {
+ struct rt2x00_platform_data *pdata;
--- /dev/null
+From 04dbd87265f6ba4a373b211ba324b437d224fb2d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 17 Mar 2013 00:03:31 +0100
+Subject: [PATCH 21/38] rt2x00: make wmac loadable via OF on rt288x/305x SoC
+
+This patch ads the match table to allow loading the wmac support from a
+devicetree.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800pci.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c
+@@ -234,10 +234,17 @@ static int rt2800soc_probe(struct platfo
+ return rt2x00soc_probe(pdev, &rt2800soc_ops);
+ }
+
++static const struct of_device_id rt2880_wmac_match[] = {
++ { .compatible = "ralink,rt2880-wmac" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, rt2880_wmac_match);
++
+ static struct platform_driver rt2800soc_driver = {
+ .driver = {
+ .name = "rt2800_wmac",
+ .mod_name = KBUILD_MODNAME,
++ .of_match_table = rt2880_wmac_match,
+ },
+ .probe = rt2800soc_probe,
+ .remove = rt2x00soc_remove,
--- /dev/null
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -36,6 +36,7 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/of.h>
+
+ #include "rt2x00.h"
+ #include "rt2800lib.h"
+@@ -9285,6 +9286,17 @@ static int rt2800_init_eeprom(struct rt2
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
+
++ {
++ struct device_node *np = rt2x00dev->dev->of_node;
++ unsigned int led_polarity;
++
++ /* Allow overriding polarity from OF */
++ if (!of_property_read_u32(np, "ralink,led-polarity",
++ &led_polarity))
++ rt2x00_set_field16(&eeprom, EEPROM_FREQ_LED_POLARITY,
++ led_polarity);
++ }
++
+ rt2x00dev->led_mcu_reg = eeprom;
+ #endif /* CPTCFG_RT2X00_LIB_LEDS */
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00leds.c
+@@ -109,6 +109,9 @@ static int rt2x00leds_register_led(struc
+ led->led_dev.name = name;
+ led->led_dev.brightness = LED_OFF;
+
++ if (rt2x00_is_soc(rt2x00dev))
++ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
++
+ retval = led_classdev_register(device, &led->led_dev);
+ if (retval) {
+ rt2x00_err(rt2x00dev, "Failed to register led handler\n");
--- /dev/null
+--- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+@@ -1361,7 +1361,7 @@ static inline void rt2x00lib_set_if_comb
+ */
+ if_limit = &rt2x00dev->if_limits_ap;
+ if_limit->max = rt2x00dev->ops->max_ap_intf;
+- if_limit->types = BIT(NL80211_IFTYPE_AP);
++ if_limit->types = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_STATION);
+ #ifdef CPTCFG_MAC80211_MESH
+ if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT);
+ #endif
--- /dev/null
+From 9782a7f7488443568fa4d6088b73c9aff7eb8510 Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel@makrotopia.org>
+Date: Wed, 19 Apr 2017 16:14:53 +0200
+Subject: [PATCH] rt2x00: add support for external PA on MT7620
+To: Stanislaw Gruszka <sgruszka@redhat.com>
+Cc: Helmut Schaa <helmut.schaa@googlemail.com>,
+ linux-wireless@vger.kernel.org,
+ Kalle Valo <kvalo@codeaurora.org>
+
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+---
+ drivers/net/wireless/ralink/rt2x00/rt2800.h | 1 +
+ drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 70 +++++++++++++++++++++++++-
+ 2 files changed, 70 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800.h
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800.h
+@@ -2749,6 +2749,7 @@ enum rt2800_eeprom_word {
+ #define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f)
+ #define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0)
+ #define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600)
++#define EEPROM_NIC_CONF2_EXTERNAL_PA FIELD16(0xc000)
+
+ /*
+ * EEPROM LNA
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -4120,6 +4120,61 @@ static void rt2800_config_channel(struct
+ rt2800_iq_calibrate(rt2x00dev, rf->channel);
+ }
+
++ if (rt2x00_rt(rt2x00dev, RT6352)) {
++ if (test_bit(CAPABILITY_EXTERNAL_PA_TX0,
++ &rt2x00dev->cap_flags)) {
++ rt2x00_warn(rt2x00dev, "Using incomplete support for " \
++ "external PA\n");
++ reg = rt2800_register_read(rt2x00dev, RF_CONTROL3);
++ reg |= 0x00000101;
++ rt2800_register_write(rt2x00dev, RF_CONTROL3, reg);
++
++ reg = rt2800_register_read(rt2x00dev, RF_BYPASS3);
++ reg |= 0x00000101;
++ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
++
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 43, 0x73);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 43, 0x73);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 44, 0x73);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 44, 0x73);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 45, 0x73);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0x73);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 46, 0x27);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 46, 0x27);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0xC8);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0xC8);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 48, 0xA4);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 48, 0xA4);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 49, 0x05);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 49, 0x05);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x27);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 55, 0xC8);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 55, 0xC8);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 56, 0xA4);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 56, 0xA4);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 57, 0x05);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 57, 0x05);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 58, 0x27);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 58, 0x27);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 59, 0xC8);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 59, 0xC8);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 60, 0xA4);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 60, 0xA4);
++ rt2800_rfcsr_write_bank(rt2x00dev, 4, 61, 0x05);
++ rt2800_rfcsr_write_bank(rt2x00dev, 6, 61, 0x05);
++ rt2800_rfcsr_write_bank(rt2x00dev, 5, 05, 0x00);
++ rt2800_rfcsr_write_bank(rt2x00dev, 7, 05, 0x00);
++
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
++ 0x36303636);
++ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_ATTEN,
++ 0x6C6C6B6C);
++ rt2800_register_write(rt2x00dev, TX1_RF_GAIN_ATTEN,
++ 0x6C6C6B6C);
++ }
++ }
++
+ bbp = rt2800_bbp_read(rt2x00dev, 4);
+ rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
+ rt2800_bbp_write(rt2x00dev, 4, bbp);
+@@ -9314,7 +9369,8 @@ static int rt2800_init_eeprom(struct rt2
+ */
+ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
+
+- if (rt2x00_rt(rt2x00dev, RT3352)) {
++ if (rt2x00_rt(rt2x00dev, RT3352) ||
++ rt2x00_rt(rt2x00dev, RT6352)) {
+ if (rt2x00_get_field16(eeprom,
+ EEPROM_NIC_CONF1_EXTERNAL_TX0_PA_3352))
+ __set_bit(CAPABILITY_EXTERNAL_PA_TX0,
+@@ -9325,6 +9381,18 @@ static int rt2800_init_eeprom(struct rt2
+ &rt2x00dev->cap_flags);
+ }
+
++ eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF2);
++
++ if (rt2x00_rt(rt2x00dev, RT6352) && eeprom != 0 && eeprom != 0xffff) {
++ if (rt2x00_get_field16(eeprom,
++ EEPROM_NIC_CONF2_EXTERNAL_PA)) {
++ __set_bit(CAPABILITY_EXTERNAL_PA_TX0,
++ &rt2x00dev->cap_flags);
++ __set_bit(CAPABILITY_EXTERNAL_PA_TX1,
++ &rt2x00dev->cap_flags);
++ }
++ }
++
+ return 0;
+ }
+
--- /dev/null
+From pozega.tomislav@gmail.com Thu May 18 12:42:27 2017
+Return-path: <pozega.tomislav@gmail.com>
+Envelope-to: daniel@makrotopia.org
+Delivery-date: Thu, 18 May 2017 12:42:27 +0200
+Received: from mail by fudo.makrotopia.org with sa-checked (Exim 4.88)
+ (envelope-from <pozega.tomislav@gmail.com>)
+ id 1dBIsy-00088b-PU
+ for daniel@makrotopia.org; Thu, 18 May 2017 12:42:27 +0200
+X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on fudo.makrotopia.org
+X-Spam-Level:
+X-Spam-Status: No, score=-0.8 required=2.5 tests=DKIM_SIGNED,DKIM_VALID,
+ DKIM_VALID_AU,FREEMAIL_FROM,HTML_MESSAGE,RCVD_IN_DNSWL_LOW shortcircuit=no
+ autolearn=ham autolearn_force=no version=3.4.1
+Received: from mail-oi0-x22a.google.com ([2607:f8b0:4003:c06::22a])
+ by fudo.makrotopia.org with esmtps (TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128)
+ (Exim 4.88)
+ (envelope-from <pozega.tomislav@gmail.com>)
+ id 1dBIsv-00088Q-Dq
+ for daniel@makrotopia.org; Thu, 18 May 2017 12:42:24 +0200
+Received: by mail-oi0-x22a.google.com with SMTP id w10so48782189oif.0
+ for <daniel@makrotopia.org>; Thu, 18 May 2017 03:42:21 -0700 (PDT)
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=gmail.com; s=20161025;
+ h=mime-version:from:date:message-id:subject:to;
+ bh=9dF7PHDassYY74+N6dAhmsL/B9i5oG3SEuMzHuazhJo=;
+ b=cBGJ44v+o4ASyCPmHCBRMmRYnJCv4Gx6lzDiScKn0XqYmNHYpZTPg5cAY1GZFUhHdz
+ 9QT5fzhJKFikBliSuJc/7/pI8KzvyEAdvawiWA7/5fbeiTZ+zjJnzRVGezqkYDKxjR6u
+ 7TsoJxR2/oFwo7bOFlThhee+Nwf7qaX8AVal7JdkqovekX79JQ5vsKAa4LapDp7Cl0wr
+ KCh0WRUHGEgpTLJFyQ3ThPmLqc8bhmu+6/V/LJ53VOY7uksZHMhvaKkk9vDCoOuPnBMK
+ Cj2/c7z9RTErz/xlHg6HxnBe/pPc31XUsuPJUleOEdZASczPsreEEKacKCONVlP1wjAB
+ iOkA==
+X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
+ d=1e100.net; s=20161025;
+ h=x-gm-message-state:mime-version:from:date:message-id:subject:to;
+ bh=9dF7PHDassYY74+N6dAhmsL/B9i5oG3SEuMzHuazhJo=;
+ b=LJAe4ZwS9aNJypROW7j+I9aNfRBWyDYy0c8ABnDbLrIoF9P2AA/Vs/Cli5f7GjaAxr
+ 1JCx602ach+7R7QjQq/nqNmLuhRCfSvB0TGrq4R4v+CJ4ADO541+PddnFiU1dlIXQRP2
+ TE2FOydSO0FGJBMg+kY0eFiidBtYj1T5x7IHAhQzufiuiF6/1xZS8h61CYJjLzt/aR5y
+ JxOxsVvu3W2YQ0T5wKmAPlKtarFH6ZZgs446bRYt1MX5KAWzIoBM1+IPMMv7lSCpCaDR
+ fwH05aDyaJW2IzXH5R9Tq7gGYycYjx/SnO7JupJXJVvOzKgBJxp60JwJhCfqCwESDuuD
+ 8nNA==
+X-Gm-Message-State: AODbwcDOpdFZgbxAxFsVsqFdCBN3pRGDvEclZ1heVg2byNZ9BuG5kqJg
+ GvZ9x4NGt0v8lVGa3esDw0N1KiJENg==
+X-Received: by 10.157.17.217 with SMTP id y25mr1310632oty.137.1495104134863;
+ Thu, 18 May 2017 03:42:14 -0700 (PDT)
+MIME-Version: 1.0
+Received: by 10.157.0.105 with HTTP; Thu, 18 May 2017 03:42:14 -0700 (PDT)
+From: Tom Psyborg <pozega.tomislav@gmail.com>
+Date: Thu, 18 May 2017 12:42:14 +0200
+Message-ID: <CAKR_QVJBSKw2uCY4RbHZPvbGkMcvnBh+j6F+9t93mG3BakjX3Q@mail.gmail.com>
+Subject: [PATCH] rt2x00: remove unneccesary code
+To: linux-wireless <linux-wireless@vger.kernel.org>,
+ Linux Kernel Mailing List <linux-kernel@vger.kernel.org>, Arnd Bergmann <arnd@arndb.de>,
+ Jes Sorensen <jes.sorensen@gmail.com>, Stanislaw Gruszka <sgruszka@redhat.com>,
+ David Miller <davem@davemloft.net>, Helmut Schaa <helmut.schaa@googlemail.com>,
+ Kalle Valo <kvalo@codeaurora.org>, Daniel Golle <daniel@makrotopia.org>,
+ Mathias Kresin <dev@kresin.me>, Johannes Berg <johannes.berg@intel.com>,
+ Serge Vasilugin <vasilugin@yandex.ru>, Roman Yeryomin <roman@advem.lv>,
+ Networking <netdev@vger.kernel.org>
+Content-Type: multipart/alternative; boundary="94eb2c1905d2dc6361054fca0e62"
+Status: RO
+Content-Length: 11079
+Lines: 178
+
+--94eb2c1905d2dc6361054fca0e62
+Content-Type: text/plain; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+Use chanreg and dccal helpers to reduce the size of ePA code.
+
+Signed-off-by: Tomislav Po=C5=BEega <pozega.tomislav@gmail.com>
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+[daniel@makrotopia.org: fixed white-space so patch applies]
+---
+
+--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
++++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+@@ -4133,38 +4133,22 @@ static void rt2800_config_channel(struct
+ reg |= 0x00000101;
+ rt2800_register_write(rt2x00dev, RF_BYPASS3, reg);
+
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 43, 0x73);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 43, 0x73);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 44, 0x73);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 44, 0x73);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 45, 0x73);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 45, 0x73);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 46, 0x27);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 46, 0x27);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 47, 0xC8);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 47, 0xC8);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 48, 0xA4);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 48, 0xA4);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 49, 0x05);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 49, 0x05);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 54, 0x27);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 54, 0x27);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 55, 0xC8);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 55, 0xC8);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 56, 0xA4);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 56, 0xA4);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 57, 0x05);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 57, 0x05);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 58, 0x27);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 58, 0x27);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 59, 0xC8);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 59, 0xC8);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 60, 0xA4);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 60, 0xA4);
+- rt2800_rfcsr_write_bank(rt2x00dev, 4, 61, 0x05);
+- rt2800_rfcsr_write_bank(rt2x00dev, 6, 61, 0x05);
+- rt2800_rfcsr_write_bank(rt2x00dev, 5, 05, 0x00);
+- rt2800_rfcsr_write_bank(rt2x00dev, 7, 05, 0x00);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 43, 0x73);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 44, 0x73);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 45, 0x73);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 46, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 47, 0xC8);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 48, 0xA4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 49, 0x05);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 54, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 55, 0xC8);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 56, 0xA4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 57, 0x05);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 58, 0x27);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 59, 0xC8);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 60, 0xA4);
++ rt2800_rfcsr_write_chanreg(rt2x00dev, 61, 0x05);
++ rt2800_rfcsr_write_dccal(rt2x00dev, 05, 0x00);
+
+ rt2800_register_write(rt2x00dev, TX0_RF_GAIN_CORRECT,
+ 0x36303636);
--- /dev/null
+--- a/net/mac80211/Makefile
++++ b/net/mac80211/Makefile
+@@ -6,7 +6,6 @@ mac80211-y := \
+ driver-ops.o \
+ sta_info.o \
+ wep.o \
+- aead_api.o \
+ wpa.o \
+ scan.o offchannel.o \
+ ht.o agg-tx.o agg-rx.o \
+@@ -16,8 +15,8 @@ mac80211-y := \
+ rate.o \
+ michael.o \
+ tkip.o \
++ aes_ccm.o \
+ aes_cmac.o \
+- aes_gmac.o \
+ fils_aead.o \
+ cfg.o \
+ ethtool.o \
+--- a/net/mac80211/aead_api.c
++++ /dev/null
+@@ -1,115 +0,0 @@
+-/*
+- * Copyright 2003-2004, Instant802 Networks, Inc.
+- * Copyright 2005-2006, Devicescape Software, Inc.
+- * Copyright 2014-2015, Qualcomm Atheros, Inc.
+- *
+- * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License version 2 as
+- * published by the Free Software Foundation.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/types.h>
+-#include <linux/err.h>
+-#include <linux/scatterlist.h>
+-#include <crypto/aead.h>
+-
+-#include "aead_api.h"
+-
+-int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
+- u8 *data, size_t data_len, u8 *mic)
+-{
+- size_t mic_len = crypto_aead_authsize(tfm);
+- struct scatterlist sg[3];
+- struct aead_request *aead_req;
+- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+- u8 *__aad;
+-
+- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
+- if (!aead_req)
+- return -ENOMEM;
+-
+- __aad = (u8 *)aead_req + reqsize;
+- memcpy(__aad, aad, aad_len);
+-
+- sg_init_table(sg, 3);
+- sg_set_buf(&sg[0], __aad, aad_len);
+- 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);
+-
+- crypto_aead_encrypt(aead_req);
+- kzfree(aead_req);
+-
+- return 0;
+-}
+-
+-int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad, size_t aad_len,
+- u8 *data, size_t data_len, u8 *mic)
+-{
+- size_t mic_len = crypto_aead_authsize(tfm);
+- struct scatterlist sg[3];
+- struct aead_request *aead_req;
+- int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
+- u8 *__aad;
+- int err;
+-
+- if (data_len == 0)
+- return -EINVAL;
+-
+- aead_req = kzalloc(reqsize + aad_len, GFP_ATOMIC);
+- if (!aead_req)
+- return -ENOMEM;
+-
+- __aad = (u8 *)aead_req + reqsize;
+- memcpy(__aad, aad, aad_len);
+-
+- sg_init_table(sg, 3);
+- sg_set_buf(&sg[0], __aad, aad_len);
+- 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);
+-
+- err = crypto_aead_decrypt(aead_req);
+- kzfree(aead_req);
+-
+- return err;
+-}
+-
+-struct crypto_aead *
+-aead_key_setup_encrypt(const char *alg, const u8 key[],
+- size_t key_len, size_t mic_len)
+-{
+- struct crypto_aead *tfm;
+- int err;
+-
+- tfm = crypto_alloc_aead(alg, 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;
+-
+- return tfm;
+-
+-free_aead:
+- crypto_free_aead(tfm);
+- return ERR_PTR(err);
+-}
+-
+-void aead_key_free(struct crypto_aead *tfm)
+-{
+- crypto_free_aead(tfm);
+-}
+--- a/net/mac80211/aead_api.h
++++ /dev/null
+@@ -1,27 +0,0 @@
+-/*
+- * 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 _AEAD_API_H
+-#define _AEAD_API_H
+-
+-#include <crypto/aead.h>
+-#include <linux/crypto.h>
+-
+-struct crypto_aead *
+-aead_key_setup_encrypt(const char *alg, const u8 key[],
+- size_t key_len, size_t mic_len);
+-
+-int aead_encrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+- size_t aad_len, u8 *data,
+- size_t data_len, u8 *mic);
+-
+-int aead_decrypt(struct crypto_aead *tfm, u8 *b_0, u8 *aad,
+- size_t aad_len, u8 *data,
+- size_t data_len, u8 *mic);
+-
+-void aead_key_free(struct crypto_aead *tfm);
+-
+-#endif /* _AEAD_API_H */
+--- a/net/mac80211/aes_ccm.h
++++ b/net/mac80211/aes_ccm.h
+@@ -10,39 +10,17 @@
+ #ifndef AES_CCM_H
+ #define AES_CCM_H
+
+-#include "aead_api.h"
++#include <linux/crypto.h>
+
+-#define CCM_AAD_LEN 32
+-
+-static inline struct crypto_aead *
+-ieee80211_aes_key_setup_encrypt(const u8 key[], size_t key_len, size_t mic_len)
+-{
+- return aead_key_setup_encrypt("ccm(aes)", key, key_len, mic_len);
+-}
+-
+-static inline int
+-ieee80211_aes_ccm_encrypt(struct crypto_aead *tfm,
+- u8 *b_0, u8 *aad, u8 *data,
+- size_t data_len, u8 *mic)
+-{
+- return aead_encrypt(tfm, b_0, aad + 2,
+- be16_to_cpup((__be16 *)aad),
+- data, data_len, mic);
+-}
+-
+-static inline int
+-ieee80211_aes_ccm_decrypt(struct crypto_aead *tfm,
+- u8 *b_0, u8 *aad, u8 *data,
+- size_t data_len, u8 *mic)
+-{
+- return aead_decrypt(tfm, b_0, aad + 2,
+- be16_to_cpup((__be16 *)aad),
+- data, data_len, mic);
+-}
+-
+-static inline void ieee80211_aes_key_free(struct crypto_aead *tfm)
+-{
+- return aead_key_free(tfm);
+-}
++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_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_cipher *tfm);
+
+ #endif /* AES_CCM_H */
+--- /dev/null
++++ b/net/mac80211/aes_gcm.c
+@@ -0,0 +1,109 @@
++/*
++ * 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 <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/err.h>
++#include <crypto/aead.h>
++
++#include <net/mac80211.h>
++#include "key.h"
++#include "aes_gcm.h"
++
++int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
++ u8 *data, size_t data_len, u8 *mic)
++{
++ struct scatterlist sg[3];
++ struct aead_request *aead_req;
++ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
++ u8 *__aad;
++
++ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
++ if (!aead_req)
++ return -ENOMEM;
++
++ __aad = (u8 *)aead_req + reqsize;
++ memcpy(__aad, aad, GCM_AAD_LEN);
++
++ 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, IEEE80211_GCMP_MIC_LEN);
++
++ aead_request_set_tfm(aead_req, tfm);
++ aead_request_set_crypt(aead_req, sg, sg, data_len, j_0);
++ aead_request_set_ad(aead_req, sg[0].length);
++
++ crypto_aead_encrypt(aead_req);
++ kzfree(aead_req);
++ return 0;
++}
++
++int ieee80211_aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
++ u8 *data, size_t data_len, u8 *mic)
++{
++ struct scatterlist sg[3];
++ struct aead_request *aead_req;
++ int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
++ u8 *__aad;
++ int err;
++
++ if (data_len == 0)
++ return -EINVAL;
++
++ aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
++ if (!aead_req)
++ return -ENOMEM;
++
++ __aad = (u8 *)aead_req + reqsize;
++ memcpy(__aad, aad, GCM_AAD_LEN);
++
++ 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, IEEE80211_GCMP_MIC_LEN);
++
++ aead_request_set_tfm(aead_req, tfm);
++ aead_request_set_crypt(aead_req, sg, sg,
++ data_len + IEEE80211_GCMP_MIC_LEN, j_0);
++ aead_request_set_ad(aead_req, sg[0].length);
++
++ err = crypto_aead_decrypt(aead_req);
++ kzfree(aead_req);
++
++ return err;
++}
++
++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)
++ goto free_aead;
++ err = crypto_aead_setauthsize(tfm, IEEE80211_GCMP_MIC_LEN);
++ if (err)
++ goto free_aead;
++
++ return tfm;
++
++free_aead:
++ 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
++++ b/net/mac80211/aes_gcm.h
+@@ -9,38 +9,30 @@
+ #ifndef AES_GCM_H
+ #define AES_GCM_H
+
+-#include "aead_api.h"
++#include <linux/crypto.h>
+
+-#define GCM_AAD_LEN 32
+-
+-static inline int ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm,
+- u8 *j_0, u8 *aad, u8 *data,
+- size_t data_len, u8 *mic)
++static inline void
++ieee80211_aes_gcm_encrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
++ u8 *data, size_t data_len, u8 *mic)
+ {
+- return aead_encrypt(tfm, j_0, aad + 2,
+- be16_to_cpup((__be16 *)aad),
+- data, data_len, 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)
++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 aead_decrypt(tfm, j_0, aad + 2,
+- be16_to_cpup((__be16 *)aad),
+- data, data_len, mic);
++ return -EOPNOTSUPP;
+ }
+
+ static inline struct crypto_aead *
+ ieee80211_aes_gcm_key_setup_encrypt(const u8 key[], size_t key_len)
+ {
+- return aead_key_setup_encrypt("gcm(aes)", key,
+- key_len, IEEE80211_GCMP_MIC_LEN);
++ return NULL;
+ }
+
+-static inline void ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
++static inline void
++ieee80211_aes_gcm_key_free(struct crypto_aead *tfm)
+ {
+- return aead_key_free(tfm);
+ }
+
+ #endif /* AES_GCM_H */
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -306,7 +306,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;
+@@ -336,14 +337,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)
+@@ -351,6 +346,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] */
+@@ -407,7 +404,7 @@ static int ccmp_encrypt_skb(struct ieee8
+ u8 *pos;
+ u8 pn[6];
+ u64 pn64;
+- u8 aad[CCM_AAD_LEN];
++ u8 aad[2 * AES_BLOCK_SIZE];
+ u8 b_0[AES_BLOCK_SIZE];
+
+ if (info->control.hw_key &&
+@@ -462,9 +459,11 @@ static int ccmp_encrypt_skb(struct ieee8
+ return 0;
+
+ pos += IEEE80211_CCMP_HDR_LEN;
+- ccmp_special_blocks(skb, pn, b_0, aad);
+- return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+- skb_put(skb, mic_len));
++ 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);
++
++ return 0;
+ }
+
+
+@@ -537,13 +536,13 @@ 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,
+ skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
+ data_len,
+- skb->data + skb->len - mic_len))
++ skb->data + skb->len - mic_len, mic_len))
+ return RX_DROP_UNUSABLE;
+ }
+
+@@ -639,7 +638,7 @@ static int gcmp_encrypt_skb(struct ieee8
+ u8 *pos;
+ u8 pn[6];
+ u64 pn64;
+- u8 aad[GCM_AAD_LEN];
++ u8 aad[2 * AES_BLOCK_SIZE];
+ u8 j_0[AES_BLOCK_SIZE];
+
+ if (info->control.hw_key &&
+@@ -696,8 +695,10 @@ static int gcmp_encrypt_skb(struct ieee8
+
+ pos += IEEE80211_GCMP_HDR_LEN;
+ gcmp_special_blocks(skb, pn, j_0, aad);
+- return ieee80211_aes_gcm_encrypt(key->u.gcmp.tfm, j_0, aad, pos, len,
+- skb_put(skb, IEEE80211_GCMP_MIC_LEN));
++ 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
+@@ -1121,9 +1122,9 @@ ieee80211_crypto_aes_gmac_encrypt(struct
+ struct ieee80211_key *key = tx->key;
+ struct ieee80211_mmie_16 *mmie;
+ struct ieee80211_hdr *hdr;
+- u8 aad[GMAC_AAD_LEN];
++ u8 aad[20];
+ u64 pn64;
+- u8 nonce[GMAC_NONCE_LEN];
++ u8 nonce[12];
+
+ if (WARN_ON(skb_queue_len(&tx->skbs) != 1))
+ return TX_DROP;
+@@ -1169,7 +1170,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_key *key = rx->key;
+ struct ieee80211_mmie_16 *mmie;
+- u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN];
++ 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))
+--- /dev/null
++++ b/net/mac80211/aes_ccm.c
+@@ -0,0 +1,144 @@
++/*
++ * Copyright 2003-2004, Instant802 Networks, Inc.
++ * Copyright 2005-2006, Devicescape Software, Inc.
++ *
++ * Rewrite: Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/err.h>
++#include <crypto/aead.h>
++#include <crypto/aes.h>
++
++#include <net/mac80211.h>
++#include "key.h"
++#include "aes_ccm.h"
++
++static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, u8 *s_0,
++ u8 *a, u8 *b)
++{
++ 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);
++
++ /* 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 *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];
++ }
++
++ for (i = 0; i < mic_len; i++)
++ mic[i] = b[i] ^ s_0[i];
++}
++
++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)
++{
++ 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 0;
++}
++
++struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[],
++ size_t key_len,
++ size_t mic_len)
++{
++ struct crypto_cipher *tfm;
++
++ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
++ if (!IS_ERR(tfm))
++ crypto_cipher_setkey(tfm, key, key_len);
++
++ return tfm;
++}
++
++
++void ieee80211_aes_key_free(struct crypto_cipher *tfm)
++{
++ crypto_free_cipher(tfm);
++}
+--- 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
+- depends on CRYPTO_CCM
+- depends on CRYPTO_GCM
+ depends on CRYPTO_CMAC
+ depends on CRC32
+ ---help---
+--- a/net/mac80211/aes_gmac.h
++++ b/net/mac80211/aes_gmac.h
+@@ -15,10 +15,22 @@
+ #define GMAC_MIC_LEN 16
+ #define GMAC_NONCE_LEN 12
+
+-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
+@@ -88,7 +88,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 {
--- /dev/null
+Used for AP+STA support in OpenWrt - preserve AP mode keys across STA reconnects
+
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1058,7 +1058,6 @@ static int ieee80211_stop_ap(struct wiph
+ sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
+
+ __sta_info_flush(sdata, true);
+- ieee80211_free_keys(sdata, true);
+
+ sdata->vif.bss_conf.enable_beacon = false;
+ sdata->vif.bss_conf.ssid_len = 0;
--- /dev/null
+--- a/net/wireless/sysfs.c
++++ b/net/wireless/sysfs.c
+@@ -24,18 +24,35 @@ static inline struct cfg80211_registered
+ return container_of(dev, struct cfg80211_registered_device, wiphy.dev);
+ }
+
+-#define SHOW_FMT(name, fmt, member) \
++#define SHOW_FMT(name, fmt, member, mode) \
+ static ssize_t name ## _show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+ { \
+ return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
+ } \
+-static DEVICE_ATTR_RO(name)
++static DEVICE_ATTR_##mode(name)
+
+-SHOW_FMT(index, "%d", wiphy_idx);
+-SHOW_FMT(macaddress, "%pM", wiphy.perm_addr);
+-SHOW_FMT(address_mask, "%pM", wiphy.addr_mask);
++static ssize_t macaddress_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t len)
++{
++ u8 mac[ETH_ALEN];
++
++ if (!mac_pton(buf, mac))
++ return -EINVAL;
++
++ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
++ return -EINVAL;
++
++ memcpy(dev_to_rdev(dev)->wiphy.perm_addr, mac, ETH_ALEN);
++
++ return strnlen(buf, len);
++}
++
++SHOW_FMT(index, "%d", wiphy_idx, RO);
++SHOW_FMT(macaddress, "%pM", wiphy.perm_addr, RW);
++SHOW_FMT(address_mask, "%pM", wiphy.addr_mask, RO);
+
+ static ssize_t name_show(struct device *dev,
+ struct device_attribute *attr,
--- /dev/null
+Disable FILS support, since it pulls in crypto hash support
+
+--- a/net/mac80211/fils_aead.h
++++ b/net/mac80211/fils_aead.h
+@@ -10,7 +10,7 @@
+ #ifndef FILS_AEAD_H
+ #define FILS_AEAD_H
+
+-#if LINUX_VERSION_IS_GEQ(4,3,0)
++#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */
+ int fils_encrypt_assoc_req(struct sk_buff *skb,
+ struct ieee80211_mgd_assoc_data *assoc_data);
+ int fils_decrypt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+--- a/net/mac80211/fils_aead.c
++++ b/net/mac80211/fils_aead.c
+@@ -1,4 +1,4 @@
+-#if LINUX_VERSION_IS_GEQ(4,3,0)
++#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */
+ /*
+ * FILS AEAD for (Re)Association Request/Response frames
+ * Copyright 2016, Qualcomm Atheros, Inc.
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -550,7 +550,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+ NL80211_FEATURE_MAC_ON_CREATE |
+ NL80211_FEATURE_USERSPACE_MPM |
+ NL80211_FEATURE_FULL_AP_CLIENT_STATE;
+-#if LINUX_VERSION_IS_GEQ(4,3,0)
++#if 0 /* LINUX_VERSION_IS_GEQ(4,3,0) */
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA);
+ #endif
+
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sat, 7 Oct 2017 09:37:28 +0200
+Subject: [PATCH] Revert "mac80211: aes-cmac: switch to shash CMAC
+ driver"
+
+This reverts commit 26717828b75dd5c46e97f7f4a9b937d038bb2852.
+Reduces mac80211 dependencies for LEDE
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/aes_cmac.c
++++ b/net/mac80211/aes_cmac.c
+@@ -22,50 +22,126 @@
+ #define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
+ #define AAD_LEN 20
+
+-static const u8 zero[CMAC_TLEN_256];
+
+-void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
+- const u8 *data, size_t data_len, u8 *mic)
++void gf_mulx(u8 *pad)
++{
++ int i, carry;
++
++ carry = pad[0] & 0x80;
++ for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
++ pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
++ pad[AES_BLOCK_SIZE - 1] <<= 1;
++ if (carry)
++ pad[AES_BLOCK_SIZE - 1] ^= 0x87;
++}
++
++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)
+ {
+- SHASH_DESC_ON_STACK(desc, tfm);
+- u8 out[AES_BLOCK_SIZE];
++ u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
++ const u8 *pos, *end;
++ size_t i, e, left, total_len;
++
++ memset(cbc, 0, AES_BLOCK_SIZE);
++
++ total_len = 0;
++ for (e = 0; e < num_elem; e++)
++ total_len += len[e];
++ left = total_len;
++
++ e = 0;
++ pos = addr[0];
++ end = pos + len[0];
++
++ while (left >= AES_BLOCK_SIZE) {
++ for (i = 0; i < AES_BLOCK_SIZE; i++) {
++ cbc[i] ^= *pos++;
++ if (pos >= end) {
++ e++;
++ pos = addr[e];
++ end = pos + len[e];
++ }
++ }
++ if (left > AES_BLOCK_SIZE)
++ crypto_cipher_encrypt_one(tfm, cbc, cbc);
++ left -= AES_BLOCK_SIZE;
++ }
++
++ memset(pad, 0, AES_BLOCK_SIZE);
++ crypto_cipher_encrypt_one(tfm, pad, pad);
++ gf_mulx(pad);
++
++ if (left || total_len == 0) {
++ for (i = 0; i < left; i++) {
++ cbc[i] ^= *pos++;
++ if (pos >= end) {
++ e++;
++ pos = addr[e];
++ end = pos + len[e];
++ }
++ }
++ cbc[left] ^= 0x80;
++ gf_mulx(pad);
++ }
++
++ for (i = 0; i < AES_BLOCK_SIZE; i++)
++ pad[i] ^= cbc[i];
++ crypto_cipher_encrypt_one(tfm, pad, pad);
++ memcpy(mac, pad, mac_len);
++}
+
+- desc->tfm = tfm;
+
+- crypto_shash_init(desc);
+- crypto_shash_update(desc, aad, AAD_LEN);
+- crypto_shash_update(desc, data, data_len - CMAC_TLEN);
+- crypto_shash_finup(desc, zero, CMAC_TLEN, out);
++void ieee80211_aes_cmac(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];
++
++ memset(zero, 0, CMAC_TLEN);
++ addr[0] = aad;
++ len[0] = AAD_LEN;
++ addr[1] = data;
++ len[1] = data_len - CMAC_TLEN;
++ addr[2] = zero;
++ len[2] = CMAC_TLEN;
+
+- memcpy(mic, out, CMAC_TLEN);
++ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN);
+ }
+
+-void ieee80211_aes_cmac_256(struct crypto_shash *tfm, const u8 *aad,
++void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
+ const u8 *data, size_t data_len, u8 *mic)
+ {
+- SHASH_DESC_ON_STACK(desc, tfm);
++ 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;
+
+- desc->tfm = tfm;
+-
+- crypto_shash_init(desc);
+- crypto_shash_update(desc, aad, AAD_LEN);
+- crypto_shash_update(desc, data, data_len - CMAC_TLEN_256);
+- crypto_shash_finup(desc, zero, CMAC_TLEN_256, mic);
++ aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256);
+ }
+
+-struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
+- size_t key_len)
++struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
++ size_t key_len)
+ {
+- struct crypto_shash *tfm;
++ struct crypto_cipher *tfm;
+
+- tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
++ tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
+ if (!IS_ERR(tfm))
+- crypto_shash_setkey(tfm, key, key_len);
++ crypto_cipher_setkey(tfm, key, key_len);
+
+ return tfm;
+ }
+
+-void ieee80211_aes_cmac_key_free(struct crypto_shash *tfm)
++
++void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm)
+ {
+- crypto_free_shash(tfm);
++ crypto_free_cipher(tfm);
+ }
+--- a/net/mac80211/aes_cmac.h
++++ b/net/mac80211/aes_cmac.h
+@@ -10,14 +10,13 @@
+ #define AES_CMAC_H
+
+ #include <linux/crypto.h>
+-#include <crypto/hash.h>
+
+-struct crypto_shash *ieee80211_aes_cmac_key_setup(const u8 key[],
+- size_t key_len);
+-void ieee80211_aes_cmac(struct crypto_shash *tfm, const u8 *aad,
++struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
++ size_t key_len);
++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_shash *tfm, const u8 *aad,
++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_shash *tfm);
++void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm);
+
+ #endif /* AES_CMAC_H */
+--- a/net/mac80211/key.h
++++ b/net/mac80211/key.h
+@@ -93,7 +93,7 @@ struct ieee80211_key {
+ } ccmp;
+ struct {
+ u8 rx_pn[IEEE80211_CMAC_PN_LEN];
+- struct crypto_shash *tfm;
++ struct crypto_cipher *tfm;
+ u32 replays; /* dot11RSNAStatsCMACReplays */
+ u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
+ } aes_cmac;
--- /dev/null
+--- a/net/mac80211/Kconfig
++++ b/net/mac80211/Kconfig
+@@ -5,7 +5,6 @@ config MAC80211
+ depends on CRYPTO
+ depends on CRYPTO_ARC4
+ depends on CRYPTO_AES
+- depends on CRYPTO_CMAC
+ depends on CRC32
+ ---help---
+ This option enables the hardware independent IEEE 802.11
--- /dev/null
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -3750,6 +3750,12 @@ out:
+ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+ {
++#if defined(sk_pacing_shift) || LINUX_VERSION_IS_GEQ(4,15,0)
++ if (skb->sk && sk_fullsock(skb->sk) &&
++ skb->sk->sk_pacing_shift != 6)
++ skb->sk->sk_pacing_shift = 6;
++#endif
++
+ if (unlikely(ieee80211_multicast_to_unicast(skb, dev))) {
+ struct sk_buff_head queue;
+
--- /dev/null
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -292,7 +292,7 @@ void ieee80211_restart_hw(struct ieee802
+ }
+ EXPORT_SYMBOL(ieee80211_restart_hw);
+
+-#ifdef CONFIG_INET
++#ifdef __disabled__CONFIG_INET
+ static int ieee80211_ifa_changed(struct notifier_block *nb,
+ unsigned long data, void *arg)
+ {
+@@ -351,7 +351,7 @@ static int ieee80211_ifa_changed(struct
+ }
+ #endif
+
+-#if IS_ENABLED(CONFIG_IPV6)
++#if IS_ENABLED(__disabled__CONFIG_IPV6)
+ static int ieee80211_ifa6_changed(struct notifier_block *nb,
+ unsigned long data, void *arg)
+ {
+@@ -1114,14 +1114,14 @@ int ieee80211_register_hw(struct ieee802
+ if (result)
+ goto fail_flows;
+
+-#ifdef CONFIG_INET
++#ifdef __disabled__CONFIG_INET
+ local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
+ result = register_inetaddr_notifier(&local->ifa_notifier);
+ if (result)
+ goto fail_ifa;
+ #endif
+
+-#if IS_ENABLED(CONFIG_IPV6)
++#if IS_ENABLED(__disabled__CONFIG_IPV6)
+ local->ifa6_notifier.notifier_call = ieee80211_ifa6_changed;
+ result = register_inet6addr_notifier(&local->ifa6_notifier);
+ if (result)
+@@ -1130,13 +1130,13 @@ int ieee80211_register_hw(struct ieee802
+
+ return 0;
+
+-#if IS_ENABLED(CONFIG_IPV6)
++#if IS_ENABLED(__disabled__CONFIG_IPV6)
+ fail_ifa6:
+-#ifdef CONFIG_INET
++#ifdef __disabled__CONFIG_INET
+ unregister_inetaddr_notifier(&local->ifa_notifier);
+ #endif
+ #endif
+-#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
++#if defined(__disabled__CONFIG_INET) || defined(__disabled__CONFIG_IPV6)
+ fail_ifa:
+ #endif
+ ieee80211_txq_teardown_flows(local);
+@@ -1166,10 +1166,10 @@ void ieee80211_unregister_hw(struct ieee
+ tasklet_kill(&local->tx_pending_tasklet);
+ tasklet_kill(&local->tasklet);
+
+-#ifdef CONFIG_INET
++#ifdef __disabled__CONFIG_INET
+ unregister_inetaddr_notifier(&local->ifa_notifier);
+ #endif
+-#if IS_ENABLED(CONFIG_IPV6)
++#if IS_ENABLED(__disabled__CONFIG_IPV6)
+ unregister_inet6addr_notifier(&local->ifa6_notifier);
+ #endif
+
--- /dev/null
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -2215,7 +2215,7 @@ static int ieee80211_scan(struct wiphy *
+ * the frames sent while scanning on other channel will be
+ * lost)
+ */
+- if (sdata->u.ap.beacon &&
++ if (0 && sdata->u.ap.beacon &&
+ (!(wiphy->features & NL80211_FEATURE_AP_SCAN) ||
+ !(req->flags & NL80211_SCAN_FLAG_AP)))
+ return -EOPNOTSUPP;
--- /dev/null
+From: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+Date: Fri, 19 Feb 2016 11:01:49 +0100
+Subject: [PATCH] mac80211: add hdrlen to ieee80211_tx_data
+
+Add hdrlen to ieee80211_tx_data and use this
+when wep/ccmd/tkip. This is preparation for
+aligned4 code.
+
+Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+---
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -177,6 +177,7 @@ struct ieee80211_tx_data {
+ struct ieee80211_tx_rate rate;
+
+ unsigned int flags;
++ unsigned int hdrlen;
+ };
+
+
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -921,7 +921,7 @@ ieee80211_tx_h_fragment(struct ieee80211
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+ int frag_threshold = tx->local->hw.wiphy->frag_threshold;
+- int hdrlen;
++ int hdrlen = tx->hdrlen;
+ int fragnum;
+
+ /* no matter what happens, tx->skb moves to tx->skbs */
+@@ -942,8 +942,6 @@ ieee80211_tx_h_fragment(struct ieee80211
+ if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
+ return TX_DROP;
+
+- hdrlen = ieee80211_hdrlen(hdr->frame_control);
+-
+ /* internal error, why isn't DONTFRAG set? */
+ if (WARN_ON(skb->len + FCS_LEN <= frag_threshold))
+ return TX_DROP;
+@@ -1175,6 +1173,8 @@ ieee80211_tx_prepare(struct ieee80211_su
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+
++ tx->hdrlen = ieee80211_hdrlen(hdr->frame_control);
++
+ if (likely(sta)) {
+ if (!IS_ERR(sta))
+ tx->sta = sta;
+@@ -3468,6 +3468,7 @@ begin:
+ tx.local = local;
+ tx.skb = skb;
+ tx.sdata = vif_to_sdata(info->control.vif);
++ tx.hdrlen = ieee80211_padded_hdrlen(hw, hdr->frame_control);
+
+ if (txq->sta)
+ tx.sta = container_of(txq->sta, struct sta_info, sta);
+@@ -3796,6 +3797,7 @@ ieee80211_build_data_template(struct iee
+ hdr = (void *)skb->data;
+ tx.sta = sta_info_get(sdata, hdr->addr1);
+ tx.skb = skb;
++ tx.hdrlen = ieee80211_padded_hdrlen(&tx.local->hw, hdr->frame_control);
+
+ if (ieee80211_tx_h_select_key(&tx) != TX_CONTINUE) {
+ rcu_read_unlock();
+--- a/net/mac80211/util.c
++++ b/net/mac80211/util.c
+@@ -1232,6 +1232,7 @@ void ieee80211_send_auth(struct ieee8021
+ struct ieee80211_local *local = sdata->local;
+ struct sk_buff *skb;
+ struct ieee80211_mgmt *mgmt;
++ unsigned int hdrlen;
+ int err;
+
+ /* 24 + 6 = header + auth_algo + auth_transaction + status_code */
+@@ -1255,8 +1256,10 @@ void ieee80211_send_auth(struct ieee8021
+ skb_put_data(skb, extra, extra_len);
+
+ if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
++ hdrlen = ieee80211_hdrlen(mgmt->frame_control);
+ mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+- err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx);
++ err = ieee80211_wep_encrypt(local, skb, hdrlen, key,
++ key_len, key_idx);
+ WARN_ON(err);
+ }
+
+--- a/net/mac80211/wep.c
++++ b/net/mac80211/wep.c
+@@ -89,11 +89,11 @@ static void ieee80211_wep_get_iv(struct
+
+ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
+ struct sk_buff *skb,
++ unsigned int hdrlen,
+ int keylen, int keyidx)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+- unsigned int hdrlen;
+ u8 *newhdr;
+
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+@@ -101,7 +101,6 @@ static u8 *ieee80211_wep_add_iv(struct i
+ if (WARN_ON(skb_headroom(skb) < IEEE80211_WEP_IV_LEN))
+ return NULL;
+
+- hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ newhdr = skb_push(skb, IEEE80211_WEP_IV_LEN);
+ memmove(newhdr, newhdr + IEEE80211_WEP_IV_LEN, hdrlen);
+
+@@ -160,6 +159,7 @@ int ieee80211_wep_encrypt_data(struct cr
+ */
+ int ieee80211_wep_encrypt(struct ieee80211_local *local,
+ struct sk_buff *skb,
++ unsigned int hdrlen,
+ const u8 *key, int keylen, int keyidx)
+ {
+ u8 *iv;
+@@ -169,7 +169,7 @@ int ieee80211_wep_encrypt(struct ieee802
+ if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN))
+ return -1;
+
+- iv = ieee80211_wep_add_iv(local, skb, keylen, keyidx);
++ iv = ieee80211_wep_add_iv(local, skb, hdrlen, keylen, keyidx);
+ if (!iv)
+ return -1;
+
+@@ -307,13 +307,14 @@ static int wep_encrypt_skb(struct ieee80
+ struct ieee80211_key_conf *hw_key = info->control.hw_key;
+
+ if (!hw_key) {
+- if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
++ if (ieee80211_wep_encrypt(tx->local, skb, tx->hdrlen,
++ tx->key->conf.key,
+ tx->key->conf.keylen,
+ tx->key->conf.keyidx))
+ return -1;
+ } else if ((hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
+ (hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
+- if (!ieee80211_wep_add_iv(tx->local, skb,
++ if (!ieee80211_wep_add_iv(tx->local, skb, tx->hdrlen,
+ tx->key->conf.keylen,
+ tx->key->conf.keyidx))
+ return -1;
+--- a/net/mac80211/wep.h
++++ b/net/mac80211/wep.h
+@@ -22,6 +22,7 @@ int ieee80211_wep_encrypt_data(struct cr
+ size_t klen, u8 *data, size_t data_len);
+ int ieee80211_wep_encrypt(struct ieee80211_local *local,
+ struct sk_buff *skb,
++ unsigned int hdrlen,
+ const u8 *key, int keylen, int keyidx);
+ int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
+ size_t klen, u8 *data, size_t data_len);
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -44,7 +44,7 @@ ieee80211_tx_h_michael_mic_add(struct ie
+ skb->len < 24 || !ieee80211_is_data_present(hdr->frame_control))
+ return TX_CONTINUE;
+
+- hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ hdrlen = tx->hdrlen;
+ if (skb->len < hdrlen)
+ return TX_DROP;
+
+@@ -187,7 +187,6 @@ mic_fail_no_key:
+
+ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
+ {
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_key *key = tx->key;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ unsigned int hdrlen;
+@@ -202,7 +201,7 @@ static int tkip_encrypt_skb(struct ieee8
+ return 0;
+ }
+
+- hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ hdrlen = tx->hdrlen;
+ len = skb->len - hdrlen;
+
+ if (info->control.hw_key)
+@@ -420,7 +419,7 @@ static int ccmp_encrypt_skb(struct ieee8
+ return 0;
+ }
+
+- hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ hdrlen = tx->hdrlen;
+ len = skb->len - hdrlen;
+
+ if (info->control.hw_key)
+@@ -653,7 +652,7 @@ static int gcmp_encrypt_skb(struct ieee8
+ return 0;
+ }
+
+- hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ hdrlen = tx->hdrlen;
+ len = skb->len - hdrlen;
+
+ if (info->control.hw_key)
+@@ -793,7 +792,6 @@ static ieee80211_tx_result
+ ieee80211_crypto_cs_encrypt(struct ieee80211_tx_data *tx,
+ struct sk_buff *skb)
+ {
+- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_key *key = tx->key;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ int hdrlen;
+@@ -809,8 +807,7 @@ ieee80211_crypto_cs_encrypt(struct ieee8
+ pskb_expand_head(skb, iv_len, 0, GFP_ATOMIC)))
+ return TX_DROP;
+
+- hdrlen = ieee80211_hdrlen(hdr->frame_control);
+-
++ hdrlen = tx->hdrlen;
+ pos = skb_push(skb, iv_len);
+ memmove(pos, pos + iv_len, hdrlen);
+
--- /dev/null
+From: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+Date: Fri, 19 Feb 2016 11:01:50 +0100
+Subject: [PATCH] mac80211: add NEED_ALIGNED4_SKBS hw flag
+
+HW/driver should set NEED_ALIGNED4_SKBS flag in case
+require aligned skbs to four-byte boundaries.
+This affect only TX direction.
+
+Padding is added after ieee80211_hdr, before IV/LLC.
+
+Before we have to do memmove(hdrlen) twice in the
+dirver. Once before we pass this to HW and next
+in tx completion (to be sure monitor will report
+this tx frame correctly).
+
+With this patch we can skip this memmove() and save CPU.
+
+Currently this was tested with ath9k, both hw/sw crypt for
+wep/tkip/ccmp.
+
+Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
+---
+
+Index: backports-v4.18-rc7/include/net/mac80211.h
+===================================================================
+--- backports-v4.18-rc7.orig/include/net/mac80211.h
++++ backports-v4.18-rc7/include/net/mac80211.h
+@@ -2084,6 +2084,9 @@ struct ieee80211_txq {
+ * @IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP: The driver (or firmware) doesn't
+ * support QoS NDP for AP probing - that's most likely a driver bug.
+ *
++ * @IEEE80211_HW_NEEDS_ALIGNED4_SKBS: Driver need aligned skbs to four-byte.
++ * Padding will be added after ieee80211_hdr, before IV/LLC.
++ *
+ * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
+ */
+ enum ieee80211_hw_flags {
+@@ -2129,6 +2132,7 @@ enum ieee80211_hw_flags {
+ IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA,
+ IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP,
+ IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP,
++ IEEE80211_HW_NEEDS_ALIGNED4_SKBS,
+
+ /* keep last, obviously */
+ NUM_IEEE80211_HW_FLAGS
+Index: backports-v4.18-rc7/net/mac80211/debugfs.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/debugfs.c
++++ backports-v4.18-rc7/net/mac80211/debugfs.c
+@@ -214,6 +214,7 @@ static const char *hw_flag_names[] = {
+ FLAG(SUPPORTS_TDLS_BUFFER_STA),
+ FLAG(DEAUTH_NEED_MGD_TX_PREP),
+ FLAG(DOESNT_SUPPORT_QOS_NDP),
++ FLAG(NEEDS_ALIGNED4_SKBS),
+ #undef FLAG
+ };
+
+Index: backports-v4.18-rc7/net/mac80211/ieee80211_i.h
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/ieee80211_i.h
++++ backports-v4.18-rc7/net/mac80211/ieee80211_i.h
+@@ -1550,6 +1550,29 @@ ieee80211_vif_get_num_mcast_if(struct ie
+ return -1;
+ }
+
++static inline unsigned int
++ieee80211_hdr_padsize(struct ieee80211_hw *hw, unsigned int hdrlen)
++{
++ /*
++ * While hdrlen is already aligned to two-byte boundaries,
++ * simple check with & 2 will return correct padsize.
++ */
++ if (ieee80211_hw_check(hw, NEEDS_ALIGNED4_SKBS))
++ return hdrlen & 2;
++ return 0;
++}
++
++static inline unsigned int
++ieee80211_padded_hdrlen(struct ieee80211_hw *hw, __le16 fc)
++{
++ unsigned int hdrlen;
++
++ hdrlen = ieee80211_hdrlen(fc);
++ hdrlen += ieee80211_hdr_padsize(hw, hdrlen);
++
++ return hdrlen;
++}
++
+ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
+ struct ieee80211_rx_status *status,
+ unsigned int mpdu_len,
+Index: backports-v4.18-rc7/net/mac80211/sta_info.h
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/sta_info.h
++++ backports-v4.18-rc7/net/mac80211/sta_info.h
+@@ -301,7 +301,7 @@ struct ieee80211_fast_tx {
+ u8 hdr_len;
+ u8 sa_offs, da_offs, pn_offs;
+ u8 band;
+- u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
++ u8 hdr[30 + 2 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
+ sizeof(rfc1042_header)] __aligned(2);
+
+ struct rcu_head rcu_head;
+Index: backports-v4.18-rc7/net/mac80211/status.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/status.c
++++ backports-v4.18-rc7/net/mac80211/status.c
+@@ -653,9 +653,22 @@ void ieee80211_tx_monitor(struct ieee802
+ struct sk_buff *skb2;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_hdr *hdr = (void *)skb->data;
+ struct net_device *prev_dev = NULL;
++ unsigned int hdrlen, padsize;
+ int rtap_len;
+
++ /* Remove padding if was added */
++ if (ieee80211_hw_check(&local->hw, NEEDS_ALIGNED4_SKBS)) {
++ hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ padsize = ieee80211_hdr_padsize(&local->hw, hdrlen);
++
++ if (padsize && skb->len > hdrlen + padsize) {
++ memmove(skb->data + padsize, skb->data, hdrlen);
++ skb_pull(skb, padsize);
++ }
++ }
++
+ /* send frame to monitor interfaces now */
+ rtap_len = ieee80211_tx_radiotap_len(info);
+ if (WARN_ON_ONCE(skb_headroom(skb) < rtap_len)) {
+Index: backports-v4.18-rc7/net/mac80211/tkip.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/tkip.c
++++ backports-v4.18-rc7/net/mac80211/tkip.c
+@@ -201,10 +201,12 @@ void ieee80211_get_tkip_p2k(struct ieee8
+ {
+ struct ieee80211_key *key = (struct ieee80211_key *)
+ container_of(keyconf, struct ieee80211_key, conf);
++ struct ieee80211_hw *hw = &key->local->hw;
+ const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY];
+ struct tkip_ctx *ctx = &key->u.tkip.tx;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+- const u8 *data = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
++ const u8 *data = (u8 *)hdr + ieee80211_padded_hdrlen(hw,
++ hdr->frame_control);
+ u32 iv32 = get_unaligned_le32(&data[4]);
+ u16 iv16 = data[2] | (data[0] << 8);
+
+Index: backports-v4.18-rc7/net/mac80211/tx.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/tx.c
++++ backports-v4.18-rc7/net/mac80211/tx.c
+@@ -1169,8 +1169,7 @@ ieee80211_tx_prepare(struct ieee80211_su
+ info->flags &= ~IEEE80211_TX_INTFL_NEED_TXPROCESSING;
+
+ hdr = (struct ieee80211_hdr *) skb->data;
+-
+- tx->hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ tx->hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control);
+
+ if (likely(sta)) {
+ if (!IS_ERR(sta))
+@@ -2200,7 +2199,7 @@ netdev_tx_t ieee80211_monitor_start_xmit
+ goto fail;
+
+ hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
+- hdrlen = ieee80211_hdrlen(hdr->frame_control);
++ hdrlen = ieee80211_padded_hdrlen(&local->hw, hdr->frame_control);
+
+ if (skb->len < len_rthdr + hdrlen)
+ goto fail;
+@@ -2418,7 +2417,7 @@ static struct sk_buff *ieee80211_build_h
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_sub_if_data *ap_sdata;
+ enum nl80211_band band;
+- int ret;
++ int padsize, ret;
+
+ if (IS_ERR(sta))
+ sta = NULL;
+@@ -2638,6 +2637,9 @@ static struct sk_buff *ieee80211_build_h
+ hdrlen += 2;
+ }
+
++ /* Check aligned4 skb required */
++ padsize = ieee80211_hdr_padsize(&sdata->local->hw, hdrlen);
++
+ /*
+ * Drop unicast frames to unauthorised stations unless they are
+ * EAPOL frames from the local station.
+@@ -2718,6 +2720,7 @@ static struct sk_buff *ieee80211_build_h
+
+ skb_pull(skb, skip_header_bytes);
+ head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb);
++ head_need += padsize;
+
+ /*
+ * So we need to modify the skb header and hence need a copy of
+@@ -2750,6 +2753,9 @@ static struct sk_buff *ieee80211_build_h
+ memcpy(skb_push(skb, meshhdrlen), &mesh_hdr, meshhdrlen);
+ #endif
+
++ if (padsize)
++ memset(skb_push(skb, padsize), 0, padsize);
++
+ if (ieee80211_is_data_qos(fc)) {
+ __le16 *qos_control;
+
+@@ -2925,6 +2931,9 @@ void ieee80211_check_fast_xmit(struct st
+ fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
+ }
+
++ /* Check aligned4 skb required */
++ build.hdr_len += ieee80211_hdr_padsize(&local->hw, build.hdr_len);
++
+ /* We store the key here so there's no point in using rcu_dereference()
+ * but that's fine because the code that changes the pointers will call
+ * this function after doing so. For a single CPU that would be enough,
+@@ -3513,7 +3522,7 @@ begin:
+
+ if (tx.key &&
+ (tx.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
+- pn_offs = ieee80211_hdrlen(hdr->frame_control);
++ pn_offs = tx.hdrlen;
+
+ ieee80211_xmit_fast_finish(sta->sdata, sta, pn_offs,
+ tx.key, skb);
+Index: backports-v4.18-rc7/net/mac80211/util.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/util.c
++++ backports-v4.18-rc7/net/mac80211/util.c
+@@ -1274,6 +1274,7 @@ void ieee80211_send_auth(struct ieee8021
+ u32 tx_flags)
+ {
+ struct ieee80211_local *local = sdata->local;
++ struct ieee80211_hw *hw = &local->hw;
+ struct sk_buff *skb;
+ struct ieee80211_mgmt *mgmt;
+ unsigned int hdrlen;
+@@ -1300,7 +1301,7 @@ void ieee80211_send_auth(struct ieee8021
+ skb_put_data(skb, extra, extra_len);
+
+ if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
+- hdrlen = ieee80211_hdrlen(mgmt->frame_control);
++ hdrlen = ieee80211_padded_hdrlen(hw, mgmt->frame_control);
+ mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ err = ieee80211_wep_encrypt(local, skb, hdrlen, key,
+ key_len, key_idx);
--- /dev/null
+From: Chaitanya T K <chaitanya.mgit@gmail.com>
+Date: Mon, 27 Jun 2016 15:23:26 +0530
+Subject: [PATCH] mac80211: minstrel: Enable STBC and LDPC for VHT Rates
+
+If peer support reception of STBC and LDPC, enable them for better
+performance.
+
+Signed-off-by: Chaitanya TK <chaitanya.mgit@gmail.com>
+---
+
+--- a/include/linux/ieee80211.h
++++ b/include/linux/ieee80211.h
+@@ -1556,6 +1556,7 @@ struct ieee80211_vht_operation {
+ #define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300
+ #define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400
+ #define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700
++#define IEEE80211_VHT_CAP_RXSTBC_SHIFT 8
+ #define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800
+ #define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000
+ #define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -1130,7 +1130,7 @@ minstrel_ht_update_caps(void *priv, stru
+ struct minstrel_ht_sta_priv *msp = priv_sta;
+ struct minstrel_ht_sta *mi = &msp->ht;
+ struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
+- u16 sta_cap = sta->ht_cap.cap;
++ u16 ht_cap = sta->ht_cap.cap;
+ struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
+ struct sta_info *sinfo = container_of(sta, struct sta_info, sta);
+ int use_vht;
+@@ -1138,6 +1138,7 @@ minstrel_ht_update_caps(void *priv, stru
+ int ack_dur;
+ int stbc;
+ int i;
++ bool ldpc = false;
+
+ /* fall back to the old minstrel for legacy stations */
+ if (!sta->ht_cap.ht_supported)
+@@ -1175,16 +1176,24 @@ minstrel_ht_update_caps(void *priv, stru
+ }
+ mi->sample_tries = 4;
+
+- /* TODO tx_flags for vht - ATM the RC API is not fine-grained enough */
+ if (!use_vht) {
+- stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>
++ stbc = (ht_cap & IEEE80211_HT_CAP_RX_STBC) >>
+ IEEE80211_HT_CAP_RX_STBC_SHIFT;
+- mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
+
+- if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)
+- mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
++ if (ht_cap & IEEE80211_HT_CAP_LDPC_CODING)
++ ldpc = true;
++ } else {
++ stbc = (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK) >>
++ IEEE80211_VHT_CAP_RXSTBC_SHIFT;
++
++ if (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)
++ ldpc = true;
+ }
+
++ mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
++ if (ldpc)
++ mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
++
+ for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
+ u32 gflags = minstrel_mcs_groups[i].flags;
+ int bw, nss;
+@@ -1197,10 +1206,10 @@ minstrel_ht_update_caps(void *priv, stru
+
+ if (gflags & IEEE80211_TX_RC_SHORT_GI) {
+ if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+- if (!(sta_cap & IEEE80211_HT_CAP_SGI_40))
++ if (!(ht_cap & IEEE80211_HT_CAP_SGI_40))
+ continue;
+ } else {
+- if (!(sta_cap & IEEE80211_HT_CAP_SGI_20))
++ if (!(ht_cap & IEEE80211_HT_CAP_SGI_20))
+ continue;
+ }
+ }
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sat, 10 Feb 2018 12:41:51 +0100
+Subject: [PATCH] mac80211: minstrel: remove unnecessary debugfs cleanup
+ code
+
+debugfs entries are cleaned up by debugfs_remove_recursive already.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel.c
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel.c
+@@ -689,8 +689,8 @@ minstrel_alloc(struct ieee80211_hw *hw,
+
+ #ifdef CPTCFG_MAC80211_DEBUGFS
+ mp->fixed_rate_idx = (u32) -1;
+- mp->dbg_fixed_rate = debugfs_create_u32("fixed_rate_idx",
+- 0666, debugfsdir, &mp->fixed_rate_idx);
++ debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
++ &mp->fixed_rate_idx);
+ #endif
+
+ minstrel_init_cck_rates(mp);
+@@ -701,9 +701,6 @@ minstrel_alloc(struct ieee80211_hw *hw,
+ static void
+ minstrel_free(void *priv)
+ {
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+- debugfs_remove(((struct minstrel_priv *)priv)->dbg_fixed_rate);
+-#endif
+ kfree(priv);
+ }
+
+@@ -735,7 +732,6 @@ const struct rate_control_ops mac80211_m
+ .free_sta = minstrel_free_sta,
+ #ifdef CPTCFG_MAC80211_DEBUGFS
+ .add_sta_debugfs = minstrel_add_sta_debugfs,
+- .remove_sta_debugfs = minstrel_remove_sta_debugfs,
+ #endif
+ .get_expected_throughput = minstrel_get_expected_throughput,
+ };
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel.h
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel.h
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel.h
+@@ -109,11 +109,6 @@ struct minstrel_sta_info {
+
+ /* sampling table */
+ u8 *sample_table;
+-
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+- struct dentry *dbg_stats;
+- struct dentry *dbg_stats_csv;
+-#endif
+ };
+
+ struct minstrel_priv {
+@@ -137,7 +132,6 @@ struct minstrel_priv {
+ * - setting will be applied on next update
+ */
+ u32 fixed_rate_idx;
+- struct dentry *dbg_fixed_rate;
+ #endif
+ };
+
+@@ -156,7 +150,6 @@ minstrel_get_ewmsd10(struct minstrel_rat
+
+ extern const struct rate_control_ops mac80211_minstrel;
+ void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
+-void minstrel_remove_sta_debugfs(void *priv, void *priv_sta);
+
+ /* Recalculate success probabilities and counters for a given rate using EWMA */
+ void minstrel_calc_rate_stats(struct minstrel_rate_stats *mrs);
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel_debugfs.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel_debugfs.c
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel_debugfs.c
+@@ -214,19 +214,7 @@ minstrel_add_sta_debugfs(void *priv, voi
+ {
+ struct minstrel_sta_info *mi = priv_sta;
+
+- mi->dbg_stats = debugfs_create_file("rc_stats", 0444, dir, mi,
+- &minstrel_stat_fops);
+-
+- mi->dbg_stats_csv = debugfs_create_file("rc_stats_csv", 0444, dir, mi,
+- &minstrel_stat_csv_fops);
+-}
+-
+-void
+-minstrel_remove_sta_debugfs(void *priv, void *priv_sta)
+-{
+- struct minstrel_sta_info *mi = priv_sta;
+-
+- debugfs_remove(mi->dbg_stats);
+-
+- debugfs_remove(mi->dbg_stats_csv);
++ debugfs_create_file("rc_stats", S_IRUGO, dir, mi, &minstrel_stat_fops);
++ debugfs_create_file("rc_stats_csv", S_IRUGO, dir, mi,
++ &minstrel_stat_csv_fops);
+ }
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel_ht.c
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.c
+@@ -1393,7 +1393,6 @@ static const struct rate_control_ops mac
+ .free = minstrel_ht_free,
+ #ifdef CPTCFG_MAC80211_DEBUGFS
+ .add_sta_debugfs = minstrel_ht_add_sta_debugfs,
+- .remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
+ #endif
+ .get_expected_throughput = minstrel_ht_get_expected_throughput,
+ };
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.h
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel_ht.h
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.h
+@@ -110,17 +110,12 @@ struct minstrel_ht_sta_priv {
+ struct minstrel_ht_sta ht;
+ struct minstrel_sta_info legacy;
+ };
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+- struct dentry *dbg_stats;
+- struct dentry *dbg_stats_csv;
+-#endif
+ void *ratelist;
+ void *sample_table;
+ bool is_ht;
+ };
+
+ void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
+-void minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta);
+ int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
+ int prob_ewma);
+
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht_debugfs.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel_ht_debugfs.c
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht_debugfs.c
+@@ -303,17 +303,8 @@ minstrel_ht_add_sta_debugfs(void *priv,
+ {
+ struct minstrel_ht_sta_priv *msp = priv_sta;
+
+- msp->dbg_stats = debugfs_create_file("rc_stats", 0444, dir, msp,
+- &minstrel_ht_stat_fops);
+- msp->dbg_stats_csv = debugfs_create_file("rc_stats_csv", 0444, dir, msp,
+- &minstrel_ht_stat_csv_fops);
+-}
+-
+-void
+-minstrel_ht_remove_sta_debugfs(void *priv, void *priv_sta)
+-{
+- struct minstrel_ht_sta_priv *msp = priv_sta;
+-
+- debugfs_remove(msp->dbg_stats);
+- debugfs_remove(msp->dbg_stats_csv);
++ debugfs_create_file("rc_stats", S_IRUGO, dir, msp,
++ &minstrel_ht_stat_fops);
++ debugfs_create_file("rc_stats_csv", S_IRUGO, dir, msp,
++ &minstrel_ht_stat_csv_fops);
+ }
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sat, 10 Feb 2018 12:43:30 +0100
+Subject: [PATCH] mac80211: minstrel: merge with minstrel_ht, always enable
+ VHT support
+
+Legacy-only devices are not very common and the overhead of the extra
+code for HT and VHT rates is not big enough to justify all those extra
+lines of code to make it optional.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+Index: backports-v4.18-rc7/net/mac80211/Kconfig
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/Kconfig
++++ backports-v4.18-rc7/net/mac80211/Kconfig
+@@ -25,20 +25,6 @@ config MAC80211_RC_MINSTREL
+ ---help---
+ This option enables the 'minstrel' TX rate control algorithm
+
+-config MAC80211_RC_MINSTREL_HT
+- bool "Minstrel 802.11n support" if EXPERT
+- depends on MAC80211_RC_MINSTREL
+- default y
+- ---help---
+- This option enables the 'minstrel_ht' TX rate control algorithm
+-
+-config MAC80211_RC_MINSTREL_VHT
+- bool "Minstrel 802.11ac support" if EXPERT
+- depends on MAC80211_RC_MINSTREL_HT
+- default n
+- ---help---
+- This option enables VHT in the 'minstrel_ht' TX rate control algorithm
+-
+ choice
+ prompt "Default rate control algorithm"
+ depends on MAC80211_HAS_RC
+@@ -60,8 +46,7 @@ endchoice
+
+ config MAC80211_RC_DEFAULT
+ string
+- default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT
+- default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
++ default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL
+ default ""
+
+ endif
+Index: backports-v4.18-rc7/net/mac80211/Makefile
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/Makefile
++++ backports-v4.18-rc7/net/mac80211/Makefile
+@@ -51,13 +51,14 @@ mac80211-$(CONFIG_PM) += pm.o
+
+ CFLAGS_trace.o := -I$(src)
+
+-rc80211_minstrel-y := rc80211_minstrel.o
+-rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o
++rc80211_minstrel-y := \
++ rc80211_minstrel.o \
++ rc80211_minstrel_ht.o
+
+-rc80211_minstrel_ht-y := rc80211_minstrel_ht.o
+-rc80211_minstrel_ht-$(CPTCFG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o
++rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += \
++ rc80211_minstrel_debugfs.o \
++ rc80211_minstrel_ht_debugfs.o
+
+ mac80211-$(CPTCFG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
+-mac80211-$(CPTCFG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y)
+
+ ccflags-y += -DDEBUG
+Index: backports-v4.18-rc7/net/mac80211/main.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/main.c
++++ backports-v4.18-rc7/net/mac80211/main.c
+@@ -1264,18 +1264,12 @@ static int __init ieee80211_init(void)
+ if (ret)
+ return ret;
+
+- ret = rc80211_minstrel_ht_init();
+- if (ret)
+- goto err_minstrel;
+-
+ ret = ieee80211_iface_init();
+ if (ret)
+ goto err_netdev;
+
+ return 0;
+ err_netdev:
+- rc80211_minstrel_ht_exit();
+- err_minstrel:
+ rc80211_minstrel_exit();
+
+ return ret;
+@@ -1283,7 +1277,6 @@ static int __init ieee80211_init(void)
+
+ static void __exit ieee80211_exit(void)
+ {
+- rc80211_minstrel_ht_exit();
+ rc80211_minstrel_exit();
+
+ ieee80211s_stop();
+Index: backports-v4.18-rc7/net/mac80211/rate.h
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rate.h
++++ backports-v4.18-rc7/net/mac80211/rate.h
+@@ -95,18 +95,5 @@ static inline void rc80211_minstrel_exit
+ }
+ #endif
+
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_HT
+-int rc80211_minstrel_ht_init(void);
+-void rc80211_minstrel_ht_exit(void);
+-#else
+-static inline int rc80211_minstrel_ht_init(void)
+-{
+- return 0;
+-}
+-static inline void rc80211_minstrel_ht_exit(void)
+-{
+-}
+-#endif
+-
+
+ #endif /* IEEE80211_RATE_H */
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel.c
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel.c
+@@ -572,138 +572,6 @@ minstrel_rate_init(void *priv, struct ie
+ minstrel_update_rates(mp, mi);
+ }
+
+-static void *
+-minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
+-{
+- struct ieee80211_supported_band *sband;
+- struct minstrel_sta_info *mi;
+- struct minstrel_priv *mp = priv;
+- struct ieee80211_hw *hw = mp->hw;
+- int max_rates = 0;
+- int i;
+-
+- mi = kzalloc(sizeof(struct minstrel_sta_info), gfp);
+- if (!mi)
+- return NULL;
+-
+- for (i = 0; i < NUM_NL80211_BANDS; i++) {
+- sband = hw->wiphy->bands[i];
+- if (sband && sband->n_bitrates > max_rates)
+- max_rates = sband->n_bitrates;
+- }
+-
+- mi->r = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp);
+- if (!mi->r)
+- goto error;
+-
+- mi->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp);
+- if (!mi->sample_table)
+- goto error1;
+-
+- mi->last_stats_update = jiffies;
+- return mi;
+-
+-error1:
+- kfree(mi->r);
+-error:
+- kfree(mi);
+- return NULL;
+-}
+-
+-static void
+-minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta)
+-{
+- struct minstrel_sta_info *mi = priv_sta;
+-
+- kfree(mi->sample_table);
+- kfree(mi->r);
+- kfree(mi);
+-}
+-
+-static void
+-minstrel_init_cck_rates(struct minstrel_priv *mp)
+-{
+- static const int bitrates[4] = { 10, 20, 55, 110 };
+- struct ieee80211_supported_band *sband;
+- u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
+- int i, j;
+-
+- sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ];
+- if (!sband)
+- return;
+-
+- for (i = 0, j = 0; i < sband->n_bitrates; i++) {
+- struct ieee80211_rate *rate = &sband->bitrates[i];
+-
+- if (rate->flags & IEEE80211_RATE_ERP_G)
+- continue;
+-
+- if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
+- continue;
+-
+- for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
+- if (rate->bitrate != bitrates[j])
+- continue;
+-
+- mp->cck_rates[j] = i;
+- break;
+- }
+- }
+-}
+-
+-static void *
+-minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+-{
+- struct minstrel_priv *mp;
+-
+- mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
+- if (!mp)
+- return NULL;
+-
+- /* contention window settings
+- * Just an approximation. Using the per-queue values would complicate
+- * the calculations and is probably unnecessary */
+- mp->cw_min = 15;
+- mp->cw_max = 1023;
+-
+- /* number of packets (in %) to use for sampling other rates
+- * sample less often for non-mrr packets, because the overhead
+- * is much higher than with mrr */
+- mp->lookaround_rate = 5;
+- mp->lookaround_rate_mrr = 10;
+-
+- /* maximum time that the hw is allowed to stay in one MRR segment */
+- mp->segment_size = 6000;
+-
+- if (hw->max_rate_tries > 0)
+- mp->max_retry = hw->max_rate_tries;
+- else
+- /* safe default, does not necessarily have to match hw properties */
+- mp->max_retry = 7;
+-
+- if (hw->max_rates >= 4)
+- mp->has_mrr = true;
+-
+- mp->hw = hw;
+- mp->update_interval = 100;
+-
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+- mp->fixed_rate_idx = (u32) -1;
+- debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
+- &mp->fixed_rate_idx);
+-#endif
+-
+- minstrel_init_cck_rates(mp);
+-
+- return mp;
+-}
+-
+-static void
+-minstrel_free(void *priv)
+-{
+- kfree(priv);
+-}
+-
+ static u32 minstrel_get_expected_throughput(void *priv_sta)
+ {
+ struct minstrel_sta_info *mi = priv_sta;
+@@ -722,29 +590,8 @@ static u32 minstrel_get_expected_through
+ }
+
+ const struct rate_control_ops mac80211_minstrel = {
+- .name = "minstrel",
+ .tx_status_ext = minstrel_tx_status,
+ .get_rate = minstrel_get_rate,
+ .rate_init = minstrel_rate_init,
+- .alloc = minstrel_alloc,
+- .free = minstrel_free,
+- .alloc_sta = minstrel_alloc_sta,
+- .free_sta = minstrel_free_sta,
+-#ifdef CPTCFG_MAC80211_DEBUGFS
+- .add_sta_debugfs = minstrel_add_sta_debugfs,
+-#endif
+ .get_expected_throughput = minstrel_get_expected_throughput,
+ };
+-
+-int __init
+-rc80211_minstrel_init(void)
+-{
+- return ieee80211_rate_control_register(&mac80211_minstrel);
+-}
+-
+-void
+-rc80211_minstrel_exit(void)
+-{
+- ieee80211_rate_control_unregister(&mac80211_minstrel);
+-}
+-
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel.h
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel.h
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel.h
+@@ -158,7 +158,5 @@ int minstrel_get_tp_avg(struct minstrel_
+ /* debugfs */
+ int minstrel_stats_open(struct inode *inode, struct file *file);
+ int minstrel_stats_csv_open(struct inode *inode, struct file *file);
+-ssize_t minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos);
+-int minstrel_stats_release(struct inode *inode, struct file *file);
+
+ #endif
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel_debugfs.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel_debugfs.c
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel_debugfs.c
+@@ -54,22 +54,6 @@
+ #include <net/mac80211.h>
+ #include "rc80211_minstrel.h"
+
+-ssize_t
+-minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
+-{
+- struct minstrel_debugfs_info *ms;
+-
+- ms = file->private_data;
+- return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
+-}
+-
+-int
+-minstrel_stats_release(struct inode *inode, struct file *file)
+-{
+- kfree(file->private_data);
+- return 0;
+-}
+-
+ int
+ minstrel_stats_open(struct inode *inode, struct file *file)
+ {
+@@ -135,14 +119,6 @@ minstrel_stats_open(struct inode *inode,
+ return 0;
+ }
+
+-static const struct file_operations minstrel_stat_fops = {
+- .owner = THIS_MODULE,
+- .open = minstrel_stats_open,
+- .read = minstrel_stats_read,
+- .release = minstrel_stats_release,
+- .llseek = default_llseek,
+-};
+-
+ int
+ minstrel_stats_csv_open(struct inode *inode, struct file *file)
+ {
+@@ -200,21 +176,3 @@ minstrel_stats_csv_open(struct inode *in
+
+ return 0;
+ }
+-
+-static const struct file_operations minstrel_stat_csv_fops = {
+- .owner = THIS_MODULE,
+- .open = minstrel_stats_csv_open,
+- .read = minstrel_stats_read,
+- .release = minstrel_stats_release,
+- .llseek = default_llseek,
+-};
+-
+-void
+-minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir)
+-{
+- struct minstrel_sta_info *mi = priv_sta;
+-
+- debugfs_create_file("rc_stats", S_IRUGO, dir, mi, &minstrel_stat_fops);
+- debugfs_create_file("rc_stats_csv", S_IRUGO, dir, mi,
+- &minstrel_stat_csv_fops);
+-}
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel_ht.c
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.c
+@@ -137,12 +137,10 @@
+ } \
+ }
+
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ static bool minstrel_vht_only = true;
+ module_param(minstrel_vht_only, bool, 0644);
+ MODULE_PARM_DESC(minstrel_vht_only,
+ "Use only VHT rates when VHT is supported by sta.");
+-#endif
+
+ /*
+ * To enable sufficiently targeted rate sampling, MCS rates are divided into
+@@ -171,7 +169,6 @@ const struct mcs_group minstrel_mcs_grou
+
+ CCK_GROUP,
+
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ VHT_GROUP(1, 0, BW_20),
+ VHT_GROUP(2, 0, BW_20),
+ VHT_GROUP(3, 0, BW_20),
+@@ -195,7 +192,6 @@ const struct mcs_group minstrel_mcs_grou
+ VHT_GROUP(1, 1, BW_80),
+ VHT_GROUP(2, 1, BW_80),
+ VHT_GROUP(3, 1, BW_80),
+-#endif
+ };
+
+ static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
+@@ -1146,12 +1142,10 @@ minstrel_ht_update_caps(void *priv, stru
+
+ BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB);
+
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ if (vht_cap->vht_supported)
+ use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0);
+ else
+-#endif
+- use_vht = 0;
++ use_vht = 0;
+
+ msp->is_ht = true;
+ memset(mi, 0, sizeof(*mi));
+@@ -1226,10 +1220,9 @@ minstrel_ht_update_caps(void *priv, stru
+
+ /* HT rate */
+ if (gflags & IEEE80211_TX_RC_MCS) {
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ if (use_vht && minstrel_vht_only)
+ continue;
+-#endif
++
+ mi->supported[i] = mcs->rx_mask[nss - 1];
+ if (mi->supported[i])
+ n_supported++;
+@@ -1349,16 +1342,88 @@ minstrel_ht_free_sta(void *priv, struct
+ kfree(msp);
+ }
+
++static void
++minstrel_ht_init_cck_rates(struct minstrel_priv *mp)
++{
++ static const int bitrates[4] = { 10, 20, 55, 110 };
++ struct ieee80211_supported_band *sband;
++ u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef);
++ int i, j;
++
++ sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ];
++ if (!sband)
++ return;
++
++ for (i = 0, j = 0; i < sband->n_bitrates; i++) {
++ struct ieee80211_rate *rate = &sband->bitrates[i];
++
++ if (rate->flags & IEEE80211_RATE_ERP_G)
++ continue;
++
++ if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
++ continue;
++
++ for (j = 0; j < ARRAY_SIZE(bitrates); j++) {
++ if (rate->bitrate != bitrates[j])
++ continue;
++
++ mp->cck_rates[j] = i;
++ break;
++ }
++ }
++}
++
+ static void *
+ minstrel_ht_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+ {
+- return mac80211_minstrel.alloc(hw, debugfsdir);
++ struct minstrel_priv *mp;
++
++ mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC);
++ if (!mp)
++ return NULL;
++
++ /* contention window settings
++ * Just an approximation. Using the per-queue values would complicate
++ * the calculations and is probably unnecessary */
++ mp->cw_min = 15;
++ mp->cw_max = 1023;
++
++ /* number of packets (in %) to use for sampling other rates
++ * sample less often for non-mrr packets, because the overhead
++ * is much higher than with mrr */
++ mp->lookaround_rate = 5;
++ mp->lookaround_rate_mrr = 10;
++
++ /* maximum time that the hw is allowed to stay in one MRR segment */
++ mp->segment_size = 6000;
++
++ if (hw->max_rate_tries > 0)
++ mp->max_retry = hw->max_rate_tries;
++ else
++ /* safe default, does not necessarily have to match hw properties */
++ mp->max_retry = 7;
++
++ if (hw->max_rates >= 4)
++ mp->has_mrr = true;
++
++ mp->hw = hw;
++ mp->update_interval = 100;
++
++#ifdef CPTCFG_MAC80211_DEBUGFS
++ mp->fixed_rate_idx = (u32) -1;
++ debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
++ &mp->fixed_rate_idx);
++#endif
++
++ minstrel_ht_init_cck_rates(mp);
++
++ return mp;
+ }
+
+ static void
+ minstrel_ht_free(void *priv)
+ {
+- mac80211_minstrel.free(priv);
++ kfree(priv);
+ }
+
+ static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
+@@ -1417,14 +1482,14 @@ static void __init init_sample_table(voi
+ }
+
+ int __init
+-rc80211_minstrel_ht_init(void)
++rc80211_minstrel_init(void)
+ {
+ init_sample_table();
+ return ieee80211_rate_control_register(&mac80211_minstrel_ht);
+ }
+
+ void
+-rc80211_minstrel_ht_exit(void)
++rc80211_minstrel_exit(void)
+ {
+ ieee80211_rate_control_unregister(&mac80211_minstrel_ht);
+ }
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.h
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel_ht.h
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.h
+@@ -15,11 +15,7 @@
+ */
+ #define MINSTREL_MAX_STREAMS 3
+ #define MINSTREL_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ #define MINSTREL_VHT_STREAM_GROUPS 6 /* BW(=3) * SGI(=2) */
+-#else
+-#define MINSTREL_VHT_STREAM_GROUPS 0
+-#endif
+
+ #define MINSTREL_HT_GROUPS_NB (MINSTREL_MAX_STREAMS * \
+ MINSTREL_HT_STREAM_GROUPS)
+@@ -34,11 +30,7 @@
+ #define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB)
+ #define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1)
+
+-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
+ #define MCS_GROUP_RATES 10
+-#else
+-#define MCS_GROUP_RATES 8
+-#endif
+
+ struct mcs_group {
+ u32 flags;
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht_debugfs.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel_ht_debugfs.c
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht_debugfs.c
+@@ -15,6 +15,22 @@
+ #include "rc80211_minstrel.h"
+ #include "rc80211_minstrel_ht.h"
+
++static ssize_t
++minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
++{
++ struct minstrel_debugfs_info *ms;
++
++ ms = file->private_data;
++ return simple_read_from_buffer(buf, len, ppos, ms->buf, ms->len);
++}
++
++static int
++minstrel_stats_release(struct inode *inode, struct file *file)
++{
++ kfree(file->private_data);
++ return 0;
++}
++
+ static char *
+ minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
+ {
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sat, 10 Feb 2018 12:45:47 +0100
+Subject: [PATCH] mac80211: minstrel: reduce minstrel_mcs_groups size
+
+By storing a shift value for all duration values of a group, we can
+reduce precision by a neglegible amount to make it fit into a u16 value.
+This improves cache footprint and reduces size:
+
+Before:
+ text data bss dec hex filename
+ 10024 116 0 10140 279c rc80211_minstrel_ht.o
+
+After:
+ text data bss dec hex filename
+ 9368 116 0 9484 250c rc80211_minstrel_ht.o
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -52,22 +52,23 @@
+ _streams - 1
+
+ /* MCS rate information for an MCS group */
+-#define MCS_GROUP(_streams, _sgi, _ht40) \
++#define MCS_GROUP(_streams, _sgi, _ht40, _s) \
+ [GROUP_IDX(_streams, _sgi, _ht40)] = { \
+ .streams = _streams, \
++ .shift = _s, \
+ .flags = \
+ IEEE80211_TX_RC_MCS | \
+ (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
+ (_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
+ .duration = { \
+- MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26), \
+- MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52), \
+- MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78), \
+- MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104), \
+- MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156), \
+- MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208), \
+- MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234), \
+- MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) \
++ MCS_DURATION(_streams, _sgi, _ht40 ? 54 : 26) >> _s, \
++ MCS_DURATION(_streams, _sgi, _ht40 ? 108 : 52) >> _s, \
++ MCS_DURATION(_streams, _sgi, _ht40 ? 162 : 78) >> _s, \
++ MCS_DURATION(_streams, _sgi, _ht40 ? 216 : 104) >> _s, \
++ MCS_DURATION(_streams, _sgi, _ht40 ? 324 : 156) >> _s, \
++ MCS_DURATION(_streams, _sgi, _ht40 ? 432 : 208) >> _s, \
++ MCS_DURATION(_streams, _sgi, _ht40 ? 486 : 234) >> _s, \
++ MCS_DURATION(_streams, _sgi, _ht40 ? 540 : 260) >> _s \
+ } \
+ }
+
+@@ -80,9 +81,10 @@
+ #define BW2VBPS(_bw, r3, r2, r1) \
+ (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
+
+-#define VHT_GROUP(_streams, _sgi, _bw) \
++#define VHT_GROUP(_streams, _sgi, _bw, _s) \
+ [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \
+ .streams = _streams, \
++ .shift = _s, \
+ .flags = \
+ IEEE80211_TX_RC_VHT_MCS | \
+ (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
+@@ -90,25 +92,25 @@
+ _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
+ .duration = { \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 117, 54, 26)), \
++ BW2VBPS(_bw, 117, 54, 26)) >> _s, \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 234, 108, 52)), \
++ BW2VBPS(_bw, 234, 108, 52)) >> _s, \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 351, 162, 78)), \
++ BW2VBPS(_bw, 351, 162, 78)) >> _s, \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 468, 216, 104)), \
++ BW2VBPS(_bw, 468, 216, 104)) >> _s, \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 702, 324, 156)), \
++ BW2VBPS(_bw, 702, 324, 156)) >> _s, \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 936, 432, 208)), \
++ BW2VBPS(_bw, 936, 432, 208)) >> _s, \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 1053, 486, 234)), \
++ BW2VBPS(_bw, 1053, 486, 234)) >> _s, \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 1170, 540, 260)), \
++ BW2VBPS(_bw, 1170, 540, 260)) >> _s, \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 1404, 648, 312)), \
++ BW2VBPS(_bw, 1404, 648, 312)) >> _s, \
+ MCS_DURATION(_streams, _sgi, \
+- BW2VBPS(_bw, 1560, 720, 346)) \
++ BW2VBPS(_bw, 1560, 720, 346)) >> _s \
+ } \
+ }
+
+@@ -121,19 +123,20 @@
+ (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \
+ CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE))
+
+-#define CCK_DURATION_LIST(_short) \
+- CCK_ACK_DURATION(10, _short), \
+- CCK_ACK_DURATION(20, _short), \
+- CCK_ACK_DURATION(55, _short), \
+- CCK_ACK_DURATION(110, _short)
++#define CCK_DURATION_LIST(_short, _s) \
++ CCK_ACK_DURATION(10, _short) >> _s, \
++ CCK_ACK_DURATION(20, _short) >> _s, \
++ CCK_ACK_DURATION(55, _short) >> _s, \
++ CCK_ACK_DURATION(110, _short) >> _s
+
+-#define CCK_GROUP \
++#define CCK_GROUP(_s) \
+ [MINSTREL_CCK_GROUP] = { \
+ .streams = 0, \
+ .flags = 0, \
++ .shift = _s, \
+ .duration = { \
+- CCK_DURATION_LIST(false), \
+- CCK_DURATION_LIST(true) \
++ CCK_DURATION_LIST(false, _s), \
++ CCK_DURATION_LIST(true, _s) \
+ } \
+ }
+
+@@ -151,47 +154,47 @@ MODULE_PARM_DESC(minstrel_vht_only,
+ * BW -> SGI -> #streams
+ */
+ const struct mcs_group minstrel_mcs_groups[] = {
+- MCS_GROUP(1, 0, BW_20),
+- MCS_GROUP(2, 0, BW_20),
+- MCS_GROUP(3, 0, BW_20),
+-
+- MCS_GROUP(1, 1, BW_20),
+- MCS_GROUP(2, 1, BW_20),
+- MCS_GROUP(3, 1, BW_20),
+-
+- MCS_GROUP(1, 0, BW_40),
+- MCS_GROUP(2, 0, BW_40),
+- MCS_GROUP(3, 0, BW_40),
+-
+- MCS_GROUP(1, 1, BW_40),
+- MCS_GROUP(2, 1, BW_40),
+- MCS_GROUP(3, 1, BW_40),
+-
+- CCK_GROUP,
+-
+- VHT_GROUP(1, 0, BW_20),
+- VHT_GROUP(2, 0, BW_20),
+- VHT_GROUP(3, 0, BW_20),
+-
+- VHT_GROUP(1, 1, BW_20),
+- VHT_GROUP(2, 1, BW_20),
+- VHT_GROUP(3, 1, BW_20),
+-
+- VHT_GROUP(1, 0, BW_40),
+- VHT_GROUP(2, 0, BW_40),
+- VHT_GROUP(3, 0, BW_40),
+-
+- VHT_GROUP(1, 1, BW_40),
+- VHT_GROUP(2, 1, BW_40),
+- VHT_GROUP(3, 1, BW_40),
+-
+- VHT_GROUP(1, 0, BW_80),
+- VHT_GROUP(2, 0, BW_80),
+- VHT_GROUP(3, 0, BW_80),
+-
+- VHT_GROUP(1, 1, BW_80),
+- VHT_GROUP(2, 1, BW_80),
+- VHT_GROUP(3, 1, BW_80),
++ MCS_GROUP(1, 0, BW_20, 5),
++ MCS_GROUP(2, 0, BW_20, 4),
++ MCS_GROUP(3, 0, BW_20, 4),
++
++ MCS_GROUP(1, 1, BW_20, 5),
++ MCS_GROUP(2, 1, BW_20, 4),
++ MCS_GROUP(3, 1, BW_20, 4),
++
++ MCS_GROUP(1, 0, BW_40, 4),
++ MCS_GROUP(2, 0, BW_40, 4),
++ MCS_GROUP(3, 0, BW_40, 4),
++
++ MCS_GROUP(1, 1, BW_40, 4),
++ MCS_GROUP(2, 1, BW_40, 4),
++ MCS_GROUP(3, 1, BW_40, 4),
++
++ CCK_GROUP(8),
++
++ VHT_GROUP(1, 0, BW_20, 5),
++ VHT_GROUP(2, 0, BW_20, 4),
++ VHT_GROUP(3, 0, BW_20, 4),
++
++ VHT_GROUP(1, 1, BW_20, 5),
++ VHT_GROUP(2, 1, BW_20, 4),
++ VHT_GROUP(3, 1, BW_20, 4),
++
++ VHT_GROUP(1, 0, BW_40, 4),
++ VHT_GROUP(2, 0, BW_40, 4),
++ VHT_GROUP(3, 0, BW_40, 4),
++
++ VHT_GROUP(1, 1, BW_40, 4),
++ VHT_GROUP(2, 1, BW_40, 4),
++ VHT_GROUP(3, 1, BW_40, 4),
++
++ VHT_GROUP(1, 0, BW_80, 4),
++ VHT_GROUP(2, 0, BW_80, 4),
++ VHT_GROUP(3, 0, BW_80, 4),
++
++ VHT_GROUP(1, 1, BW_80, 4),
++ VHT_GROUP(2, 1, BW_80, 4),
++ VHT_GROUP(3, 1, BW_80, 4),
+ };
+
+ static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
+@@ -307,7 +310,8 @@ minstrel_ht_get_tp_avg(struct minstrel_h
+ if (group != MINSTREL_CCK_GROUP)
+ nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
+
+- nsecs += minstrel_mcs_groups[group].duration[rate];
++ nsecs += minstrel_mcs_groups[group].duration[rate] <<
++ minstrel_mcs_groups[group].shift;
+
+ /*
+ * For the throughput calculation, limit the probability value to 90% to
+@@ -755,12 +759,19 @@ minstrel_ht_tx_status(void *priv, struct
+ minstrel_ht_update_rates(mp, mi);
+ }
+
++static inline int
++minstrel_get_duration(int index)
++{
++ const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
++ unsigned int duration = group->duration[index % MCS_GROUP_RATES];
++ return duration << group->shift;
++}
++
+ static void
+ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
+ int index)
+ {
+ struct minstrel_rate_stats *mrs;
+- const struct mcs_group *group;
+ unsigned int tx_time, tx_time_rtscts, tx_time_data;
+ unsigned int cw = mp->cw_min;
+ unsigned int ctime = 0;
+@@ -779,8 +790,7 @@ minstrel_calc_retransmit(struct minstrel
+ mrs->retry_count_rtscts = 2;
+ mrs->retry_updated = true;
+
+- group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
+- tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;
++ tx_time_data = minstrel_get_duration(index) * ampdu_len / 1000;
+
+ /* Contention time for first 2 tries */
+ ctime = (t_slot * cw) >> 1;
+@@ -874,20 +884,24 @@ minstrel_ht_get_max_amsdu_len(struct min
+ int group = mi->max_prob_rate / MCS_GROUP_RATES;
+ const struct mcs_group *g = &minstrel_mcs_groups[group];
+ int rate = mi->max_prob_rate % MCS_GROUP_RATES;
++ unsigned int duration;
+
+ /* Disable A-MSDU if max_prob_rate is bad */
+ if (mi->groups[group].rates[rate].prob_ewma < MINSTREL_FRAC(50, 100))
+ return 1;
+
++ duration = g->duration[rate];
++ duration <<= g->shift;
++
+ /* If the rate is slower than single-stream MCS1, make A-MSDU limit small */
+- if (g->duration[rate] > MCS_DURATION(1, 0, 52))
++ if (duration > MCS_DURATION(1, 0, 52))
+ return 500;
+
+ /*
+ * If the rate is slower than single-stream MCS4, limit A-MSDU to usual
+ * data packet size
+ */
+- if (g->duration[rate] > MCS_DURATION(1, 0, 104))
++ if (duration > MCS_DURATION(1, 0, 104))
+ return 1600;
+
+ /*
+@@ -895,7 +909,7 @@ minstrel_ht_get_max_amsdu_len(struct min
+ * rate success probability is less than 75%, limit A-MSDU to twice the usual
+ * data packet size
+ */
+- if (g->duration[rate] > MCS_DURATION(1, 0, 260) ||
++ if (duration > MCS_DURATION(1, 0, 260) ||
+ (minstrel_ht_get_prob_ewma(mi, mi->max_tp_rate[0]) <
+ MINSTREL_FRAC(75, 100)))
+ return 3200;
+@@ -942,13 +956,6 @@ minstrel_ht_update_rates(struct minstrel
+ rate_control_set_rates(mp->hw, mi->sta, rates);
+ }
+
+-static inline int
+-minstrel_get_duration(int index)
+-{
+- const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
+- return group->duration[index % MCS_GROUP_RATES];
+-}
+-
+ static int
+ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
+ {
+--- a/net/mac80211/rc80211_minstrel_ht.h
++++ b/net/mac80211/rc80211_minstrel_ht.h
+@@ -33,9 +33,10 @@
+ #define MCS_GROUP_RATES 10
+
+ struct mcs_group {
+- u32 flags;
+- unsigned int streams;
+- unsigned int duration[MCS_GROUP_RATES];
++ u16 flags;
++ u8 streams;
++ u8 shift;
++ u16 duration[MCS_GROUP_RATES];
+ };
+
+ extern const struct mcs_group minstrel_mcs_groups[];
+--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
++++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
+@@ -58,6 +58,7 @@ minstrel_ht_stats_dump(struct minstrel_h
+ static const int bitrates[4] = { 10, 20, 55, 110 };
+ int idx = i * MCS_GROUP_RATES + j;
+ unsigned int prob_ewmsd;
++ unsigned int duration;
+
+ if (!(mi->supported[i] & BIT(j)))
+ continue;
+@@ -95,7 +96,9 @@ minstrel_ht_stats_dump(struct minstrel_h
+ p += sprintf(p, " %3u ", idx);
+
+ /* tx_time[rate(i)] in usec */
+- tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
++ duration = mg->duration[j];
++ duration <<= mg->shift;
++ tx_time = DIV_ROUND_CLOSEST(duration, 1000);
+ p += sprintf(p, "%6u ", tx_time);
+
+ tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
+@@ -204,6 +207,7 @@ minstrel_ht_stats_csv_dump(struct minstr
+ static const int bitrates[4] = { 10, 20, 55, 110 };
+ int idx = i * MCS_GROUP_RATES + j;
+ unsigned int prob_ewmsd;
++ unsigned int duration;
+
+ if (!(mi->supported[i] & BIT(j)))
+ continue;
+@@ -238,7 +242,10 @@ minstrel_ht_stats_csv_dump(struct minstr
+ }
+
+ p += sprintf(p, "%u,", idx);
+- tx_time = DIV_ROUND_CLOSEST(mg->duration[j], 1000);
++
++ duration = mg->duration[j];
++ duration <<= mg->shift;
++ tx_time = DIV_ROUND_CLOSEST(duration, 1000);
+ p += sprintf(p, "%u,", tx_time);
+
+ tp_max = minstrel_ht_get_tp_avg(mi, i, j, MINSTREL_FRAC(100, 100));
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sat, 10 Feb 2018 13:43:07 +0100
+Subject: [PATCH] mac80211: minstrel: fix using short preamble CCK rates on
+ HT clients
+
+mi->supported[MINSTREL_CCK_GROUP] needs to be updated
+
+Fixes: 782dda00ab8e ("mac80211: minstrel_ht: move short preamble check out of get_rate")
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+Index: backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/rc80211_minstrel_ht.c
++++ backports-v4.18-rc7/net/mac80211/rc80211_minstrel_ht.c
+@@ -1135,7 +1135,6 @@ minstrel_ht_update_caps(void *priv, stru
+ struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
+ u16 ht_cap = sta->ht_cap.cap;
+ struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
+- struct sta_info *sinfo = container_of(sta, struct sta_info, sta);
+ int use_vht;
+ int n_supported = 0;
+ int ack_dur;
+@@ -1267,8 +1266,7 @@ minstrel_ht_update_caps(void *priv, stru
+ if (!n_supported)
+ goto use_legacy;
+
+- if (test_sta_flag(sinfo, WLAN_STA_SHORT_PREAMBLE))
+- mi->cck_supported_short |= mi->cck_supported_short << 4;
++ mi->supported[MINSTREL_CCK_GROUP] |= mi->cck_supported_short << 4;
+
+ /* create an initial rate table with the lowest supported rates */
+ minstrel_ht_update_stats(mp, mi);
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 1 Mar 2018 13:27:54 +0100
+Subject: [PATCH] mac80211: minstrel: fix CCK rate group streams value
+
+Fixes a harmless underflow issue when CCK rates are actively being used
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -131,7 +131,7 @@
+
+ #define CCK_GROUP(_s) \
+ [MINSTREL_CCK_GROUP] = { \
+- .streams = 0, \
++ .streams = 1, \
+ .flags = 0, \
+ .shift = _s, \
+ .duration = { \
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 1 Mar 2018 13:28:48 +0100
+Subject: [PATCH] mac80211: minstrel: fix sampling/reporting of CCK rates
+ in HT mode
+
+Long/short preamble selection cannot be sampled separately, since it
+depends on the BSS state. Because of that, sampling attempts to
+currently not used preamble modes are not counted in the statistics,
+which leads to CCK rates being sampled too often.
+
+Fix statistics accounting for long/short preamble by increasing the
+index where necessary.
+Fix excessive CCK rate sampling by dropping unsupported sample attempts.
+
+This improves throughput on 2.4 GHz channels
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -281,7 +281,8 @@ minstrel_ht_get_stats(struct minstrel_pr
+ break;
+
+ /* short preamble */
+- if (!(mi->supported[group] & BIT(idx)))
++ if ((mi->supported[group] & BIT(idx + 4)) &&
++ (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
+ idx += 4;
+ }
+ return &mi->groups[group].rates[idx];
+@@ -1080,18 +1081,23 @@ minstrel_ht_get_rate(void *priv, struct
+ return;
+
+ sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
++ sample_idx %= MCS_GROUP_RATES;
++
++ if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP] &&
++ (sample_idx >= 4) != txrc->short_preamble)
++ return;
++
+ info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+ rate->count = 1;
+
+- if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
++ if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP]) {
+ int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
+ rate->idx = mp->cck_rates[idx];
+ } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) {
+ ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES,
+ sample_group->streams);
+ } else {
+- rate->idx = sample_idx % MCS_GROUP_RATES +
+- (sample_group->streams - 1) * 8;
++ rate->idx = sample_idx + (sample_group->streams - 1) * 8;
+ }
+
+ rate->flags = sample_group->flags;
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Sat, 3 Mar 2018 18:48:58 +0100
+Subject: [PATCH] mac80211: minstrel: do not sample rates 3 times slower than
+ max_prob_rate
+
+These rates are highly unlikely to be used quickly, even if the link
+deteriorates rapidly. This improves throughput in cases where CCK rates
+are not reliable enough to be skipped entirely during sampling.
+Sampling these rates regularly can cost a lot of airtime.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/rc80211_minstrel_ht.c
++++ b/net/mac80211/rc80211_minstrel_ht.c
+@@ -1004,10 +1004,13 @@ minstrel_get_sample_rate(struct minstrel
+ return -1;
+
+ /*
+- * Do not sample if the probability is already higher than 95%
+- * to avoid wasting airtime.
++ * Do not sample if the probability is already higher than 95%,
++ * or if the rate is 3 times slower than the current max probability
++ * rate, to avoid wasting airtime.
+ */
+- if (mrs->prob_ewma > MINSTREL_FRAC(95, 100))
++ sample_dur = minstrel_get_duration(sample_idx);
++ if (mrs->prob_ewma > MINSTREL_FRAC(95, 100) ||
++ minstrel_get_duration(mi->max_prob_rate) * 3 < sample_dur)
+ return -1;
+
+ /*
+@@ -1017,7 +1020,6 @@ minstrel_get_sample_rate(struct minstrel
+
+ cur_max_tp_streams = minstrel_mcs_groups[tp_rate1 /
+ MCS_GROUP_RATES].streams;
+- sample_dur = minstrel_get_duration(sample_idx);
+ if (sample_dur >= minstrel_get_duration(tp_rate2) &&
+ (cur_max_tp_streams - 1 <
+ minstrel_mcs_groups[sample_group].streams ||
--- /dev/null
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 8 Mar 2018 21:00:56 +0100
+Subject: [PATCH] mac80211: fix memory accounting with A-MSDU aggregation
+
+fq uses skb->truesize for memory usage tracking. Increments/decrements
+are done on enqueue/dequeue.
+When A-MSDU aggregation is performed on tx side, the packet is
+aggregated with the last packet in the queue belonging to the same flow.
+There are multiple bugs here:
+- The truesize field of the aggregated packet isn't updated, so memory
+usage is underestimated
+- fq->memory_usage isn't adjusted.
+
+Because of the combination of both bugs, this only causes tx issues in
+rare cases, mainly when the A-MSDU head needs to be reallocated.
+
+Fix this by adjusting both truesize of the A-MSDU head and adding the
+truesize delta to fq->memory_usage.
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -3171,6 +3171,7 @@ static bool ieee80211_amsdu_aggregate(st
+ u8 max_subframes = sta->sta.max_amsdu_subframes;
+ int max_frags = local->hw.max_tx_fragments;
+ int max_amsdu_len = sta->sta.max_amsdu_len;
++ int orig_truesize;
+ __be16 len;
+ void *data;
+ bool ret = false;
+@@ -3201,12 +3202,13 @@ static bool ieee80211_amsdu_aggregate(st
+ flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func);
+ head = skb_peek_tail(&flow->queue);
+ if (!head)
+- goto out;
++ goto unlock;
+
++ orig_truesize = head->truesize;
+ orig_len = head->len;
+
+ if (skb->len + head->len > max_amsdu_len)
+- goto out;
++ goto unlock;
+
+ if (!ieee80211_amsdu_prepare_head(sdata, fast_tx, head))
+ goto out;
+@@ -3249,6 +3251,9 @@ static bool ieee80211_amsdu_aggregate(st
+ fq_recalc_backlog(fq, tin, flow);
+
+ out:
++ fq->memory_usage += head->truesize - orig_truesize;
++
++unlock:
+ spin_unlock_bh(&fq->lock);
+
+ return ret;
--- /dev/null
+From 4f717a2589be649afddbbd3ac58b67ebfa7426f7 Mon Sep 17 00:00:00 2001
+From: Sven Eckelmann <sven@narfation.org>
+Date: Wed, 6 Jun 2018 10:18:31 +0200
+Subject: [PATCH v2] cfg80211: initialize sinfo in cfg80211_get_station
+
+Most of the implementations behind cfg80211_get_station will not initialize
+sinfo to zero before manipulating it. For example, the member "filled",
+which indicates the filled in parts of this struct, is often only modified
+by enabling certain bits in the bitfield while keeping the remaining bits
+in their original state. A caller without a preinitialized sinfo.filled can
+then no longer decide which parts of sinfo were filled in by
+cfg80211_get_station (or actually the underlying implementations).
+
+cfg80211_get_station must therefore take care that sinfo is initialized to
+zero. Otherwise, the caller may tries to read information which was not
+filled in and which must therefore also be considered uninitialized. In
+batadv_v_elp_get_throughput's case, an invalid "random" expected throughput
+may be stored for this neighbor and thus the B.A.T.M.A.N V algorithm may
+switch to non-optimal neighbors for certain destinations.
+
+Fixes: 7406353d43c8 ("cfg80211: implement cfg80211_get_station cfg80211 API")
+Reported-by: Thomas Lauer <holminateur@gmail.com>
+Reported-by: Marcel Schmidt <ff.z-casparistrasse@mailbox.org>
+Cc: b.a.t.m.a.n@lists.open-mesh.org
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+
+Forwarded: https://patchwork.kernel.org/patch/10449857/
+---
+ net/wireless/util.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -1749,6 +1749,8 @@ int cfg80211_get_station(struct net_devi
+ if (!rdev->ops->get_station)
+ return -EOPNOTSUPP;
+
++ memset(sinfo, 0, sizeof(*sinfo));
++
+ return rdev_get_station(rdev, dev, mac_addr, sinfo);
+ }
+ EXPORT_SYMBOL(cfg80211_get_station);
--- /dev/null
+Index: backports-v4.18-rc7/include/net/cfg80211.h
+===================================================================
+--- backports-v4.18-rc7.orig/include/net/cfg80211.h
++++ backports-v4.18-rc7/include/net/cfg80211.h
+@@ -2857,6 +2857,7 @@ struct cfg80211_external_auth_params {
+ * (as advertised by the nl80211 feature flag.)
+ * @get_tx_power: store the current TX power into the dbm variable;
+ * return 0 if successful
++ * @set_antenna_gain: set antenna gain to reduce maximum tx power if necessary
+ *
+ * @set_wds_peer: set the WDS peer for a WDS interface
+ *
+@@ -3157,6 +3158,7 @@ struct cfg80211_ops {
+ enum nl80211_tx_power_setting type, int mbm);
+ int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
+ int *dbm);
++ int (*set_antenna_gain)(struct wiphy *wiphy, int dbi);
+
+ int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *addr);
+Index: backports-v4.18-rc7/include/net/mac80211.h
+===================================================================
+--- backports-v4.18-rc7.orig/include/net/mac80211.h
++++ backports-v4.18-rc7/include/net/mac80211.h
+@@ -1348,6 +1348,7 @@ enum ieee80211_smps_mode {
+ *
+ * @power_level: requested transmit power (in dBm), backward compatibility
+ * value only that is set to the minimum of all interfaces
++ * @max_antenna_gain: maximum antenna gain adjusted by user config (in dBi)
+ *
+ * @chandef: the channel definition to tune to
+ * @radar_enabled: whether radar detection is enabled
+@@ -1368,6 +1369,7 @@ enum ieee80211_smps_mode {
+ struct ieee80211_conf {
+ u32 flags;
+ int power_level, dynamic_ps_timeout;
++ int max_antenna_gain;
+
+ u16 listen_interval;
+ u8 ps_dtim_period;
+Index: backports-v4.18-rc7/include/uapi/linux/nl80211.h
+===================================================================
+--- backports-v4.18-rc7.orig/include/uapi/linux/nl80211.h
++++ backports-v4.18-rc7/include/uapi/linux/nl80211.h
+@@ -2238,6 +2238,9 @@ enum nl80211_commands {
+ * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes
+ * a flow is assigned on each round of the DRR scheduler.
+ *
++ * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce
++ * transmit power to stay within regulatory limits. u32, dBi.
++ *
+ * @NUM_NL80211_ATTR: total number of nl80211_attrs available
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -2677,6 +2680,8 @@ enum nl80211_attrs {
+ NL80211_ATTR_TXQ_MEMORY_LIMIT,
+ NL80211_ATTR_TXQ_QUANTUM,
+
++ NL80211_ATTR_WIPHY_ANTENNA_GAIN,
++
+ /* add attributes here, update the policy in nl80211.c */
+
+ __NL80211_ATTR_AFTER_LAST,
+Index: backports-v4.18-rc7/net/mac80211/cfg.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/cfg.c
++++ backports-v4.18-rc7/net/mac80211/cfg.c
+@@ -2489,6 +2489,19 @@ static int ieee80211_get_tx_power(struct
+ return 0;
+ }
+
++static int ieee80211_set_antenna_gain(struct wiphy *wiphy, int dbi)
++{
++ struct ieee80211_local *local = wiphy_priv(wiphy);
++
++ if (dbi < 0)
++ return -EINVAL;
++
++ local->user_antenna_gain = dbi;
++ ieee80211_hw_config(local, 0);
++
++ return 0;
++}
++
+ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *addr)
+ {
+@@ -3856,6 +3869,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,
++ .set_antenna_gain = ieee80211_set_antenna_gain,
+ .set_wds_peer = ieee80211_set_wds_peer,
+ .rfkill_poll = ieee80211_rfkill_poll,
+ CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
+Index: backports-v4.18-rc7/net/mac80211/ieee80211_i.h
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/ieee80211_i.h
++++ backports-v4.18-rc7/net/mac80211/ieee80211_i.h
+@@ -1350,6 +1350,7 @@ struct ieee80211_local {
+ int dynamic_ps_forced_timeout;
+
+ int user_power_level; /* in dBm, for all interfaces */
++ int user_antenna_gain; /* in dBi */
+
+ enum ieee80211_smps_mode smps_mode;
+
+Index: backports-v4.18-rc7/net/mac80211/main.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/mac80211/main.c
++++ backports-v4.18-rc7/net/mac80211/main.c
+@@ -93,7 +93,7 @@ static u32 ieee80211_hw_conf_chan(struct
+ struct ieee80211_sub_if_data *sdata;
+ struct cfg80211_chan_def chandef = {};
+ u32 changed = 0;
+- int power;
++ int power, max_power;
+ u32 offchannel_flag;
+
+ offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+@@ -150,6 +150,12 @@ static u32 ieee80211_hw_conf_chan(struct
+ }
+ rcu_read_unlock();
+
++ max_power = chandef.chan->max_reg_power;
++ if (local->user_antenna_gain > 0) {
++ max_power -= local->user_antenna_gain;
++ power = min(power, max_power);
++ }
++
+ if (local->hw.conf.power_level != power) {
+ changed |= IEEE80211_CONF_CHANGE_POWER;
+ local->hw.conf.power_level = power;
+@@ -611,6 +617,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_
+ IEEE80211_RADIOTAP_MCS_HAVE_BW;
+ local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
+ IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
++ local->user_antenna_gain = 0;
+ local->hw.uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
+ local->hw.uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+ local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
+Index: backports-v4.18-rc7/net/wireless/nl80211.c
+===================================================================
+--- backports-v4.18-rc7.orig/net/wireless/nl80211.c
++++ backports-v4.18-rc7/net/wireless/nl80211.c
+@@ -428,6 +428,7 @@ static const struct nla_policy nl80211_p
+ [NL80211_ATTR_TXQ_LIMIT] = { .type = NLA_U32 },
+ [NL80211_ATTR_TXQ_MEMORY_LIMIT] = { .type = NLA_U32 },
+ [NL80211_ATTR_TXQ_QUANTUM] = { .type = NLA_U32 },
++ [NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 },
+ };
+
+ /* policy for the key attributes */
+@@ -2531,6 +2532,20 @@ static int nl80211_set_wiphy(struct sk_b
+ if (result)
+ return result;
+ }
++
++ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) {
++ int idx, dbi = 0;
++
++ if (!rdev->ops->set_antenna_gain)
++ return -EOPNOTSUPP;
++
++ idx = NL80211_ATTR_WIPHY_ANTENNA_GAIN;
++ dbi = nla_get_u32(info->attrs[idx]);
++
++ result = rdev->ops->set_antenna_gain(&rdev->wiphy, dbi);
++ if (result)
++ return result;
++ }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
+ info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {